Skip to content
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/shtc1: Initial support for the SHTC1 temperature and humidity sensor #7866

Closed
wants to merge 14 commits into from

Conversation

shr70
Copy link
Contributor

@shr70 shr70 commented Oct 26, 2017

This commit adds an implementation for the shtc1 temperature and humidity sensor

Furthermore a test is supplied for the driver

@miri64 miri64 added Area: drivers Area: Device drivers Type: new feature The issue requests / The PR implemements a new feature for RIOT labels Oct 28, 2017
Copy link
Member

@PeterKietzmann PeterKietzmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shr70 thanks for your contribution and the time you already spent! There are a couple of style and conceptual comments in line. Please also consider implementation SAUL for your driver.

drivers/include/shtc1.h Outdated Show resolved Hide resolved


/**
* @brief initializes the sensor and i2c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Start with capital letter here and be consistent with i2c or I2C here and all following occurences

/**
* @brief reads out id
*
* When working correctly id should equal xxxx'xxxx'xx00'0111
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please prefix with @details. This concerns every occasion where you document some details to the function.
Maybe use capital letters fir ID here and following?

* Where x is unspecified
*
* @param[in] dev The I2C Device
* @param[out] id contains the id read from i2c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID is specific to the device, not to the I2 bus I assume?

* @param[out] id contains the id read from i2c
*
* @return 0 on everything done
* @return -1 on error occured
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on error is enough


int8_t shtc1_measure(i2c_t dev, crc_type_t crc, shtc1_values_t* received_values)
{
uint8_t data[] = { 0x7C, 0xA2 };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check out the peripheral functions i2c_read/write_reg(s), define register addresses in a separate header file and document what you intend to do here. Same applies for following occurrences.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i2c_read/write_reg() is not possible, as the shtc1 expects a stop condition after the command is send. Thats why I choose to use a i2c_write_bytes(command) and i2c_read_bytes() solution.

int8_t shtc1_measure(i2c_t dev, crc_type_t crc, shtc1_values_t* received_values)
{
uint8_t data[] = { 0x7C, 0xA2 };
i2c_write_bytes(dev, 0x70, data, 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The device address will be part of the params definition later (compare device driver guide linked above))

* @brief reads temperature and humidity values
*
* @param[in] dev The I2C Device
* @param[out] received_values the received values are going to be saved here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document all parameters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document the unit of the returned values

}
received_values->temp = (175.0*temp_f/65536)-45;
received_values->rel_humidity = 100*(abs_humidity/65536.0);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we abstain from extra divisions and normalization operations to represent a value in persent or something. Do you think we can simplify here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that a conversion of the temperature to °C is neccessary. The raw values does not hold a lot of information to a user.
The relative humidity can be changed back to the absolute one as this should be clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

puts("Error: END of main().");
/* should be never reached */
return 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't need the extra shell command. Just put the actual code directly in main() and periodically read out sensor values.

@shr70
Copy link
Contributor Author

shr70 commented Dec 6, 2017

Remodeled the driver according to driver guide. Now I will add in the requested changes

@PeterKietzmann
Copy link
Member

@shr70 I've seen activity in this PR. And thanks for your feedback! I will come back t you the next days

Copy link
Member

@PeterKietzmann PeterKietzmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shr70 the code looks way better than before, thanks for your efforts! Please address above comment and rebase. Now the driver needmys to be tested, does anyone own this device?
Furthermore: It is not necessary but how about adding a SAUL adaption?

@PeterKietzmann
Copy link
Member

@shr70 can you recommend a breakout board or is this device mounted on a board supported by RIOT?

@shr70 shr70 force-pushed the shtc1 branch 2 times, most recently from cf63cee to f700b22 Compare December 18, 2017 14:01
@shr70
Copy link
Contributor Author

shr70 commented Dec 18, 2017

@PeterKietzmann We tested this driver with a predecessor of the Jiminy-Board. The SHTC1 was part of a sensor shield. If you can not get your hands on the SHTC1 we might be able to send you one of our old shields.

@shr70 shr70 force-pushed the shtc1 branch 4 times, most recently from f6700f6 to 5695c13 Compare December 18, 2017 15:12
@PeterKietzmann
Copy link
Member

@shr70 that would be pretty helpful! Can you send me an e-mail please?

@shr70 shr70 force-pushed the shtc1 branch 2 times, most recently from 8addc91 to 443cffe Compare January 9, 2018 14:43
@PeterKietzmann
Copy link
Member

@shr70 would you adapt this PR according to #9162? After the I2C remodeling has been done I'd give it an other review

@shr70
Copy link
Contributor Author

shr70 commented Oct 9, 2018

@PeterKietzmann sorry for the late reply, I was busy with my exams. Can you check the driver again? It should now be properly adjusted to the new I2C interface.

@PeterKietzmann PeterKietzmann added the Community: Hack'n'ACK candidate This PR is a candidate for review and discussion during one of RIOT's monthly Hack'n'ACK parties label Oct 15, 2018
typedef struct {
i2c_t bus; /**< I2C bus descriptor */
uint8_t addr; /**< I2C address of the sensor */
shtc1_crc_type_t crc; /**< crc check enabled or disabled (CRC_ENABLED/CRC_DISABLED) */
Copy link
Member

@PeterKietzmann PeterKietzmann Oct 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align comments

* @{
*/
typedef struct {
shtc1_values_t values; /**< Values struct, where all read data will be stored */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my understanding: Why did you integrate the values struct here? For caching purposes?

*
* @return SHTC1_OK if a measurement completed. The values will be stored in the values struct. Temperature in °C and humidity in %
* @return SHTC1_ERROR on checksum error
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reduce line width of the doc


/**
* @brief Reads temperature and humidity values
* @details The values wil be saved in the device descriptor (values struct). The temperature is in °C and the humidity in %
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will

* @return SHTC1_OK if a measurement completed. The values will be stored in the values struct. Temperature in °C and humidity in %
* @return SHTC1_ERROR on checksum error
*/
int8_t shtc1_measure(shtc1_t* const dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be nice to have a function that directly returns the data instead of fiddling around with the device struct? Furthermore, I expected some intentions to cache sensor data when you introduced shtc1_values_t. If this was the case, wouldn't you need a distinction between triggering a new read and getting cached data?

Copy link
Contributor

@Josar Josar Nov 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shtc1_values_t are used in the device struckt shtc1_t.

Just passing the struckt instead of dev, temp, hum pointer is much more convinient. IMHO.
We could discuss to add raw and processed data to the shtc1_values_t. What do you think.

typedef struct {
float temp; /**< Temperature after an according call to the measurement function */
float rel_humidity; /**< Relative humidity after an according call to the measuerment funtion*/
unsigned int id; /**< ID read from the sensor, only available after shtc1_id() was called */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id has 16 bit right? So you better take uint16_t here.

#define SHTC1_COMMAND_RESET_LOW 0x5D
#define SHTC1_COMMAND_ID_HIGH 0xEF
#define SHTC1_COMMAND_ID_LOW 0xC8
#define SHTC1_ID 0x07 /* ID Mask */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if we have a convention for that but I expected parentheses around the values. Would you mind to add?

}
/* Receive the measurement */
uint8_t received[6];
if(i2c_read_bytes(dev->params.bus, dev->params.addr, received, 6, 0)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe spend a comment about the format (upper 8bit, lower 8bit, crc)

Copy link
Member

@PeterKietzmann PeterKietzmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shr70 find some comments and questions inline. Generally the code looks good to me. The only open question is about the sensor data in the device struct (aka caching capabilities?). Maybe @aabadie can shed some light into the current "best practices" for drivers.
I just learned that with my Jiminy I need #7943 in order to test the driver. So let's try to get this it done before.

@PeterKietzmann
Copy link
Member

Still waiting for #7943. And I sill would really much like to return the measurement values via return or pointers instead of via device struct.

@Josar
Copy link
Contributor

Josar commented Dec 18, 2018

@PeterKietzmann the current implementation saves the measured values in the dev.values.temp and dev.values.rel_humidity so they can be used multiple times and are stored and valid until a new measurement is done.

I just don't see how this is more fiddling around then passing 3 parameter for the device, temperature and humidity as it is done in sht1x or sht3x drivers.

@PeterKietzmann
Copy link
Member

PeterKietzmann commented Jan 7, 2019

@Josar what means "fiddedling around" is a matter of taste, that's for sure. I'm with you that having access to cached sensor data without triggering a measurement is a reasonable feature. However, my primary concern was and still is a similar interface to other sensors drivers.
What do you think about a driver that implements (i) init (ii) trigger measurement (iii) get cached data (iv) convenience function that combines (ii) and (iii)? (iii) and (iv) with parameters for both temperature and humidity.
We came to a similar consensus in #7822.

@PeterKietzmann
Copy link
Member

@Josar #7822 was merged which allows me to test this one one clarified about the API and rebased.

@PeterKietzmann
Copy link
Member

@Josar still around?

@Josar
Copy link
Contributor

Josar commented Jan 30, 2019

Desk full of work. And waiting for your comments on the Api.

@Josar #7822 was merged which allows me to test this one one clarified about the API and rebased.

@PeterKietzmann
Copy link
Member

I sill would really much like to return the measurement values via return or pointers instead of via device struct

What do you think about a driver that implements (i) init (ii) trigger measurement (iii) get cached data (iv) convenience function that combines (ii) and (iii)? (iii) and (iv) with parameters for both temperature and humidity.
We came to a similar consensus in #7822.

... is what I proposed. @haukepetersen, @aabadie please state your opinion on the shtc1_measure(shtc1_t* const dev) function and how measured values should be returned so we can finally converge here

@keestux
Copy link
Contributor

keestux commented Jan 31, 2019

BTW Notice that this prototype is most likely a programming mistake.

int8_t shtc1_measure(shtc1_t* const dev)

The dev object is not const, only the pointer is. And inside the function that has hardly any value. Except maybe for a compiler to know that you are not going to change the pointer. You can still write struct members.

I'm not sure if that paradigm comes from @Josar or @shr70 but I really think we should change it. I've seen this in sht2x as well.

@stale
Copy link

stale bot commented Aug 10, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Aug 10, 2019
@PeterKietzmann PeterKietzmann added the State: don't stale State: Tell state-bot to ignore this issue label Aug 19, 2019
@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Aug 19, 2019
@benpicco
Copy link
Contributor

superseded by #12924

@benpicco benpicco closed this Dec 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers Community: Hack'n'ACK candidate This PR is a candidate for review and discussion during one of RIOT's monthly Hack'n'ACK parties State: don't stale State: Tell state-bot to ignore this issue Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants