-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
drivers: add driver for FXOS8700 3-axis accelerometer/magnetometer #8978
Conversation
9dda5b2
to
caffc42
Compare
Nice! This sensor can be found on the frdm-kw41z board. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments below. I will test on the frdm-kw41z board. I can provide a board config for that particular setup when I get it running.
*/ | ||
static const saul_reg_info_t fxos8700_saul_info[] = | ||
{ | ||
HDC1000_SAUL_INFO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy pasta
drivers/fxos8700/fxos8700.c
Outdated
DEBUG("[fxos8700] Could not read WHOAMI (%d)\n", rv); | ||
return FXOS8700_NOBUS; | ||
} | ||
dev->whoami = config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any use case for saving this value? It seems like it is never used by the implementation.
drivers/include/fxos8700.h
Outdated
} fxos8700_params_t; | ||
|
||
/** | ||
* @brief Device descriptor for a AT30TSE75x device |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy pasta, and weird indentation
drivers/include/fxos8700.h
Outdated
} fxos8700_t; | ||
|
||
/** | ||
* @brief Individual hybrid measurement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird indent
drivers/include/fxos8700.h
Outdated
uint8_t ydr:1; /*!< bit: 0 Start Conversion Event In */ | ||
uint8_t xdr:1; /*!< bit: 1 Synchronization Event In */ | ||
} bit; /*!< Structure used for bit access */ | ||
uint8_t reg; /*!< Type used for register access */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and everywhere else: use /**
(and of course /**<
) for doxygen comments in RIOT.
drivers/include/fxos8700.h
Outdated
uint8_t xdr:1; /*!< bit: 1 Synchronization Event In */ | ||
} bit; /*!< Structure used for bit access */ | ||
uint8_t reg; /*!< Type used for register access */ | ||
} FXOS8700_STATUS_Type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type, and the other bit fields below, are not actually used by the implementation.
Additionally, it is not required by a compiler to pack the bit fields in the struct, so this bit representation will not be guaranteed to match the hardware register bits. It is more robust to use bit mask macros or other bit operations in the implementation. The compiler should be smart enough to optimize the accesses in a good way when one of the operands is a numeric literal or static constant.
The cache does not handle multiple instances. |
Otherwise we will likely end up with various cache implementations in each sensor driver, with plenty of opportunity for mistakes and difficulties testing them in a reliable way. |
b22891e
to
495a94a
Compare
I think it is a good verification to read the whoami register during init, to check that the device is responding and that the connected device is actually a FXOS8700 sensor by comparing the actual value against the expected value. Just that it does not need to be saved in the context struct. |
495a94a
to
921de7a
Compare
@gebart. Thank you for the quick review! I resolved you comments. WHOAMI comparison is still here but its value is not saved now. Regarding the cache, I don't know how many sensors in RIOT are relevant (one sensor should provide multiple types of information). If this cache functionality is useful for many other sensors, we can think of generalizing it. But I think this should be another PR. |
52a33f5
to
933f2dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor code style issues.
drivers/fxos8700/fxos8700.c
Outdated
int32_t acc_raw_z = (int32_t) ((data[4]<<6) | (data[5]>>2)); | ||
acc->x = (int16_t)(acc_raw_x*244/1000); | ||
acc->y = (int16_t)(acc_raw_y*244/1000); | ||
acc->z = (int16_t)(acc_raw_z*244/1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code style: add spaces around operators
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, for clarity it may be better to have parentheses around (raw * 244) / 1000
, though it changes nothing in the generated code since the associativity is left to right for the multiplication and division operators.
drivers/fxos8700/fxos8700.c
Outdated
if (mag) { | ||
mag->x = (int16_t) ((data[6] <<8) | data[7]); | ||
mag->y = (int16_t) ((data[8] <<8) | data[9]); | ||
mag->z = (int16_t) ((data[10]<<8) | data[11]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces around bit shift operators
drivers/fxos8700/fxos8700.c
Outdated
|
||
int fxos8700_read_cached(const fxos8700_t *dev, fxos8700_measurement_t* acc, fxos8700_measurement_t* mag) | ||
{ | ||
uint32_t now = xtimer_now_usec(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: It may be less computationally expensive to use xtimer_now and convert the renew interval to ticks instead, since you can precompute that us to tick conversion at compilation time rather than do a conversion from ticks to us in every read. See this as an optional comment, and maybe just remember for future drivers, I assume this function will be called somewhat infrequently since the renew interval is set to 1 second.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! I will remember for the future driver implementations which require frequent xtimer access 👍
Are you using this sensor externally or integrated on any dev board? Do you have any updated board configurations you want to add here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rough pass of review. I found problems with doxygen and style and have minor comments in the driver implementation (return code, defines, etc)
drivers/fxos8700/fxos8700_saul.c
Outdated
*/ | ||
|
||
/** | ||
* @ingroup driver_fxos8700 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be drivers_fxos8700
drivers/fxos8700/fxos8700.c
Outdated
static int fxos8700_read_regs(fxos8700_t* dev, uint8_t reg, uint8_t* data, size_t len) | ||
{ | ||
i2c_acquire(dev->p.i2c); | ||
if(i2c_read_regs(dev->p.i2c, dev->p.addr, reg, (char*) data, len) <= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing space after if
here and in other places below
drivers/fxos8700/fxos8700.c
Outdated
return FXOS8700_BUSERR; | ||
} | ||
|
||
while(!(ready & 0x08)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing space after while
here and below. Maybe unscrustify the file ?
drivers/fxos8700/fxos8700.c
Outdated
@@ -0,0 +1,205 @@ | |||
/* | |||
* Copyright (C) 2017 UC Berkeley |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be 2018 ?
drivers/fxos8700/fxos8700_saul.c
Outdated
@@ -0,0 +1,58 @@ | |||
/* | |||
* Copyright (C) 2017 Hyung-Sin Kim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not UC Berkeley ?
drivers/include/fxos8700.h
Outdated
} | ||
#endif | ||
|
||
/** @} */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line should be after #endif
below
drivers/fxos8700/fxos8700.c
Outdated
if (config != FXOS8700_WHO_AM_I_VAL) { | ||
i2c_release(dev->p.i2c); | ||
DEBUG("[fxos8700] WHOAMI is wrong (%2x)\n", config); | ||
return FXOS8700_NOBUS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add another return status for this case ? Something line FXOS8700_NODEV
?
drivers/fxos8700/fxos8700.c
Outdated
/* Configure the ODR to maximum (400Hz in hybrid mode) */ | ||
config = 0x00; | ||
if (fxos8700_write_regs(dev, FXOS8700_REG_CTRL_REG1, &config, 1) != FXOS8700_OK) { | ||
return FXOS8700_NOBUS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be FXOS8700_BUSERR instead ? Here and in other places below.
drivers/fxos8700/fxos8700.c
Outdated
#define FXOS8700_RENEW_INTERVAL 1000000ul | ||
#endif | ||
|
||
#define ACCEL_ONLY_MODE 0x00 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe put parenthesis around these hexadecimal defines
drivers/fxos8700/fxos8700.c
Outdated
i2c_acquire(dev->p.i2c); | ||
if(i2c_read_regs(dev->p.i2c, dev->p.addr, reg, (char*) data, len) <= 0) { | ||
DEBUG("[fxos8700] Can't read register 0x%x\n", reg); | ||
i2c_release(dev->p.i2c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use for example:
#define DEV_I2C (dev->p.i2c)
at the beginning of this file. Same with addr attribute and maybe others
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed the style of the current HDC1000 implementation. Is this style a strict requirement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that was more a suggestion for future maintenance, technically it doesn't change anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Thanks!
72211b9
to
b7484c4
Compare
drivers/fxos8700/fxos8700.c
Outdated
#define MAG_ONLY_MODE (0x01) | ||
#define HYBRID_MODE (0x03) | ||
|
||
static fxos8700_measurement_t acc_cached, mag_cached; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of those static variable; why no having them as attributes of fxos8700_t
?
Because otherwise this will be a problem with multiple instances of this device as already reported by @gebart here.That could be a best temporary solution until we have a module for managing cache.
Maybe saul could do it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree and updated this PR reflecting this comment. Thanks!
ef2c5c5
to
7e388d3
Compare
drivers/include/fxos8700.h
Outdated
* @brief Device descriptor for a FXOS8700 device | ||
*/ | ||
typedef struct { | ||
fxos8700_measurement_t acc_cached; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The attributes of this struct are missing documentation, same with the fxos8700_measurement_t struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved
Could you also add a test application ? |
ab7d496
to
64b1963
Compare
4b747d3
to
2e6a557
Compare
1098e15
to
9195661
Compare
@gebart, I checked that it works at least in my case (hamilton), as below. Dev: fxos8700 Type: SENSE_ACCEL Can you retry? |
I will check again tomorrow |
My frdm-kw41z is giving strange values, I will try again with a frdm-k22f board tomorrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found the source of my problems. Negative values of acceleration are not handled correctly, see my comment below regarding the bit shift
drivers/fxos8700/fxos8700.c
Outdated
} | ||
|
||
/* Read all data at once */ | ||
if (fxos8700_read_regs(dev, FXOS8700_REG_OUT_X_MSB, &data[0], 12)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change magic 12
into sizeof something or a macro definition.
drivers/fxos8700/fxos8700.c
Outdated
if (acc) { | ||
int32_t acc_raw_x = (int32_t) ((data[0] << 6) | (data[1] >> 2)); | ||
int32_t acc_raw_y = (int32_t) ((data[2] << 6) | (data[3] >> 2)); | ||
int32_t acc_raw_z = (int32_t) ((data[4] << 6) | (data[5] >> 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the shift of 6 loses the sign bit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives reasonable results for negative numbers:
int32_t acc_raw_x = (int16_t) ((data[0] << 8) | data[1]) >> 2;
int32_t acc_raw_y = (int16_t) ((data[2] << 8) | data[3]) >> 2;
int32_t acc_raw_z = (int16_t) ((data[4] << 8) | data[5]) >> 2;
acc->x = (int16_t) ((acc_raw_x * 244) / 1000);
acc->y = (int16_t) ((acc_raw_y * 244) / 1000);
acc->z = (int16_t) ((acc_raw_z * 244) / 1000);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point. Thanks!!
drivers/fxos8700/fxos8700.c
Outdated
int32_t acc_raw_z = (int32_t) ((data[4] << 6) | (data[5] >> 2)); | ||
acc->x = (int16_t) ((acc_raw_x * 244) / 1000); | ||
acc->y = (int16_t) ((acc_raw_y * 244) / 1000); | ||
acc->z = (int16_t) ((acc_raw_z * 244) / 1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are really discarding quite a lot of bits of precision with this division. You could just as well configure the sensor to +/- 8 g range and use x * 976 / 1000
instead and get the benefit of an increased sensor range without any difference in accuracy compared to the current implementation
80b99b8
to
48d3bd9
Compare
@gebart, thank you for improving this driver!
|
48d3bd9
to
ba6ef8b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codewise it looks good now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comment regarding the lost bits when using 2 or 4 g full scale range still applies, but I don't intend to block this PR just for that.
Optionally, change the division from 1000 to 100 and change the SAUL scale from -3 to -4 when +/- 2 G range is selected |
ba6ef8b
to
67673b2
Compare
67673b2
to
beaf08b
Compare
@gebart, I updated, but I think this driver does not lose any bit regardless of resolution setting since it provides "FXOS8700_USE_ACC_RAW_VALUES" mode. |
👍 |
@Hyungsin in future PRs, please create fixup/squash commits for changes you add after the initial review to make the review process easier. You can amend typos or other minor corrections, but for anything a little bigger, such as when you added the different scaling factor configurations in this PR, use a separate commit. Then squash the commits when the reviewer requests it. It makes it easier for the reviewer to know what has changed between iterations. |
@gebart, good point. I should keep this in mind! |
All green here. Let's merge. |
This PR provides a driver for the FXOS8700 sensor, which reads 3-axis acceleration and magnetic field.
Driver implementation style is similar to HDC1000 driver.