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/sht11: Major refactoring #9317

Merged
merged 5 commits into from
Jun 27, 2018
Merged

drivers/sht11: Major refactoring #9317

merged 5 commits into from
Jun 27, 2018

Conversation

maribu
Copy link
Member

@maribu maribu commented Jun 8, 2018

  • Renamed driver to sht1x to reflect that fact SHT10, SHT11 and SHT15 are supported
  • Removed sensor specific shell commands in favor of SAUL
  • Major refactoring and new features:
    • Use RIOT's GPIO interface to access the sensor to increase portability
    • Changed API to allow more than one sensor per board
    • Added sht1x_params.h that specifies how the sensors is connected - each board can overwrite default settings by #defining SHT1X_PARAM_CLK and SHT1X_PARAM_DATA
    • Changed arithmetic to use integer calculations only instead of floating point arithmetic
    • Added support for checking the CRC sum
    • Allow optional skipping of the CRC check to speed up measuring
    • Added support for advanced features like reducing the resolution and skipping calibration to speed up measuring
    • Allow specifying the supply voltage of sensor which heavily influences the temperature result (and use that information to calculate the correct temperature)
    • Reset sensor on initialization to bring it in a well known state
    • Support for the obscure heater feature. (Can be useful to check the temperature sensor?)
  • Confirmed new integer only arithmetic by unit tests
  • Added SAUL integration

Hint: Before testing on the MSBA2 or other lpc2387 based boards, please apply this PR containing various bugfixes for the gpio driver.

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

Thanks for refactoring this sensor @maribu ! It's already much better than before.

I think the shell commands could be kept and I have some comments to improve the module organisation (using pseudomodules) and also regarding the way the sensor is initialized/configured.

@@ -302,7 +302,7 @@ ifneq (,$(filter servo,$(USEMODULE)))
FEATURES_REQUIRED += periph_pwm
endif

ifneq (,$(filter sht11,$(USEMODULE)))
ifneq (,$(filter sht1x,$(USEMODULE)))
Copy link
Contributor

Choose a reason for hiding this comment

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

it's better to use pseudomodule for specific version of the sensor (sht10, sht11, sht15) and to load the generic module when the specific one is loaded.
You can declare the pseudomodules in RIOTBASE/makefiles/pseudomodules.inc.mk (see sx1272, sx1276 as example) and here use the following makefile rule:

ifneq (,$(filter sht1%,$(USEMODULE)))
  USEMODULE += sht1x
  USEMODULE += xtimer
endif

your Makefile needs to contain these lines:

~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
USEMODULE += sht11
USEMODULE += sht1x
Copy link
Contributor

Choose a reason for hiding this comment

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

use the pseudomodule related to the concrete version of the sensor (sht10,11,15)

*/

/**
* @defgroup drivers_sht1x SHT10/SHT1X/SHT15 Humidity and Temperature Sensors
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be SHT10/SHT11/SHT15

/**
* @defgroup drivers_sht1x SHT10/SHT1X/SHT15 Humidity and Temperature Sensors
* @ingroup drivers_sensors
* @brief Driver for Sensirion SHT10/SHT1/SHT15 Humidity and Temperature
Copy link
Contributor

Choose a reason for hiding this comment

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

typo on SHT11

* @file
* @brief SHT1X Device Driver
*
* @author Freie Universität Berlin, Computer Systems & Telematics
Copy link
Contributor

Choose a reason for hiding this comment

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

The author is invalid, maybe it was already like this ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I could remove the author tag and keep them in the copyright declaration. The author tag does not provide additional information compared to the copyright declaration.

saul_entries[(i * 3) + 2].dev = &(sht1x_devs[i]);
saul_entries[(i * 3) ].name = "SHT1X temperature";
saul_entries[(i * 3) + 1].name = "SHT1X humidity";
saul_entries[(i * 3) + 2].name = "SHT1X config (Low resolution | "
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the calibration should be passed in the driver params.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was not actually calibrating the sensor - the calibration data is stored inside the sensor. But the sensor can be configured to not use them, which speeds up measurements about 10 ms. So this should be a runtime option, as this trade-off between speed and precision depends on the situation.

But the configuration was removed from SAUL anyway (as suggested), so that comment no longer applies.

@@ -8,9 +8,6 @@ endif
ifneq (,$(filter ps,$(USEMODULE)))
SRC += sc_ps.c
endif
ifneq (,$(filter sht11,$(USEMODULE)))
Copy link
Contributor

Choose a reason for hiding this comment

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

I would keep the shell commands

BOARD ?= native
include ../Makefile.tests_common

USEMODULE += sht1x
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment about the version of sensor, better use the pseudomodule which will implicitly load the common concrete module.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure the device specific pseudo modules should be used for unit tests that are not device specific? I would prefer to keep sht1x here, otherwise it is not obvious that is applies to all variants.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure the device specific pseudo modules should be used for unit tests that are not device specific?

Ok, I initially missed that subtlety. If you want to test conversion functions in a unit test way then I would recommend that you add this in a real unittest under the unittests application.
The driver_sht1x should be a helper application for testing real hardware. Instead of native, the default board could msba2 or msp430 since they embed one of this sensor. This application could either call the driver initialization, use a default configuration and then periodically read the sensor values or, just use the shell commands to give full control on the device.

continue;
}
int16_t got_hum = sht1x_humidity(&dev, raw_hum, temp);
if (
Copy link
Contributor

Choose a reason for hiding this comment

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

This file needs to be uncrustified

const char *res_temp[] = {"12", "14"};
const char *res_hum[] = {"8", "12"};
const char *voltages[] = {"5.0", "4.0", "3.5", "3.0", "2.5"};
sht1x_dev_t dev = {.conf = 0};
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use the sht1x_init with the default params ? This is the common usage for other sensors.

Copy link
Member Author

Choose a reason for hiding this comment

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

Because this would require an actual sensor to be present, but the unit tests are intended to run on "native" without any hardware. The unit tests verify that the integer arithmetic still gives the same results as the floating point arithmetic given in the data sheet. Because these tests are computationally expensive, it makes no sense to run them on embedded hardware.

Also, using default parameters would dramatically decrease test coverage. The unit tests iterate over all possible configuration states in the for loops and verify that the calculations are correct for all of them - including the configuration that was chosen to be the default one.

@maribu maribu force-pushed the sht1x branch 2 times, most recently from 8ba8ff3 to 7685085 Compare June 10, 2018 19:54
@maribu
Copy link
Member Author

maribu commented Jun 10, 2018

@aabadie: Thanks for your review. Unless I have overlooked anything, I have addressed all issues you pointed out with the exception of the issues for the unit tests I commented on.

Please review again and give feedback if the two points with the unit tests can remain as they are for the reasons I stated in the comments above, or whether I should address them somehow.

Kind regards,
Marian

@maribu
Copy link
Member Author

maribu commented Jun 10, 2018

Hmm, coccinelle wants me to cast implicitly from int to int16_t, even though this cast will loose precision on pretty much all >= 32 bit systems. Implicit casts that loose precision are easily overlooked. As casts that loose precision can easily result in bugs, it is widely considered as good coding style to at least make the cast explicit to spotlight the loose in precision. GCC and clang even provide a warning (-Wconversion) to motivate developers to do the conversion explicitly when loosing precision. Maybe coccinelle can be configured similarly?

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

Thanks for addressing the initial comments.
I found other small issues with typos and doxygen. See below.

I also have comments related to the unittests: if you want to test the conversion functions under different parameters and independently of the platform, I think it's better to create a new unittest under the unittests application.
The driver_sht1x application should be testable on real hardware.

The last big comment is about the way you split the auto_init from the saul registry initialization. I think the implementation files could be merged, using conditional macros.

Maybe I missed some subtlety, so forgive me it's the case.

@@ -302,7 +302,8 @@ ifneq (,$(filter servo,$(USEMODULE)))
FEATURES_REQUIRED += periph_pwm
endif

ifneq (,$(filter sht11,$(USEMODULE)))
ifneq (,$(filter sht1%,$(USEMODULE)))
USEMODULE += sht1x
Copy link
Contributor

Choose a reason for hiding this comment

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

This module also depends on periph_gpio so you should also add here FEATURES_REQUIRED += periph_gpio

} sht1x_dev_t;

/**
* @brief Parameters requried to set up the SHT1X device driver
Copy link
Contributor

Choose a reason for hiding this comment

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

typo requried

* @brief Parameters requried to set up the SHT1X device driver
*/
typedef struct {
gpio_t clk; /**< GPIO conntected to the clock pin of the SHT1X */
Copy link
Contributor

Choose a reason for hiding this comment

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

typo conntected


/**
* @brief Calculate the temperature from the raw input
* @note This internal funciton is exposed for unit tests
Copy link
Contributor

Choose a reason for hiding this comment

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

typo funciton

*
* @param dev SHT1X sensor to read
* @param temp Store the measured temperature in E-02 °C here
* @param hum Store the measured relative humidit in E-02 % here
Copy link
Contributor

Choose a reason for hiding this comment

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

typo humidit

@@ -307,8 +304,8 @@ void auto_init(void)
auto_init_lis3dh();
#endif
#ifdef MODULE_LIS3MDL
extern void auto_init_lis3mdl(void);
auto_init_lis3mdl();
extern void auto_init_lis3mdl(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

unrelated

BOARD ?= native
include ../Makefile.tests_common

USEMODULE += sht1x
Copy link
Contributor

Choose a reason for hiding this comment

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

Sure the device specific pseudo modules should be used for unit tests that are not device specific?

Ok, I initially missed that subtlety. If you want to test conversion functions in a unit test way then I would recommend that you add this in a real unittest under the unittests application.
The driver_sht1x should be a helper application for testing real hardware. Instead of native, the default board could msba2 or msp430 since they embed one of this sensor. This application could either call the driver initialization, use a default configuration and then periodically read the sensor values or, just use the shell commands to give full control on the device.

case 1:
return &sht1x_devs[0];
case 2:
if ((argv[1][0] >= '0') && (argv[1][0] <= '9') && (!argv[1][1])) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just use int dev_idx = atoi(argv[1]);, easier to read.

const sht1x_dev_t *dev = get_dev(argc, argv);

if (!dev) {
return -1;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add an error message.

Copy link
Member Author

Choose a reason for hiding this comment

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

The error message is printed by get_dev() :-)

extern const saul_driver_t sht1x_saul_hum_driver;
/** @} */

void auto_init_sht1x_saul(void)
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for a saul specific function, you could add it to auto_init_sht1x but guard it with an #ifdef if the saul module is loaded. If you do this, auto_init_sht1x_saul.c can be removed. And the auto_init_sht1x.c could be with the other saul devices auto init files.

@maribu maribu force-pushed the sht1x branch 3 times, most recently from 166d36b to 22485ee Compare June 11, 2018 20:47
@maribu
Copy link
Member Author

maribu commented Jun 11, 2018

@aabadie: Thanks for the review and for pointing me to the unit tests app. This is much better now :-)

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

SAUL integration and unittests looks good now. Thanks!

Please address the remaining minor comments (doxygen, typos). It would also be nice to have a test application in tests/driver_sht1x: it could a simple application that load the auto_init, sht1x and shell_commands and start a shell. This way one can play on real hardware using shell commands. What do you think ?

*
* @param dev Device from which the raw value was received
* @param raw The raw (unprocessed) temperature value
* @param temp The temperate at which the humidity was measure in E-02 °C
Copy link
Contributor

Choose a reason for hiding this comment

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

typo 'temperature'

#ifdef MODULE_SHT11
#include "sht11.h"
#ifdef MODULE_SHT1X
void auto_init_sht1x(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to declare this function here. Just use extern before the call to the function.

#ifdef MODULE_SHT11
DEBUG("Auto init SHT11 module.\n");
sht11_init();
#ifdef MODULE_SHT1X
Copy link
Contributor

Choose a reason for hiding this comment

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

I would move this just before the #ifdef MODULE_AUTO_INIT_SAUL.

@maribu maribu force-pushed the sht1x branch 5 times, most recently from 82446a1 to d2289b7 Compare June 12, 2018 12:54
@maribu
Copy link
Member Author

maribu commented Jun 12, 2018

Unless I have overlooked anything, I have address all open issues and also added an on-device test for the driver. This test will read both temperature and humidity value three times for each configuration and then drop to the shell for manual testing. I added the MSBA2 as default board, because I tested on that. Please note that the driver does only work on the MSBA2 after the gpio driver bugs addressed by this PR are fixed.

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

Thanks for updating again @maribu. It's getting closer.

Found another typo in the new test application.
By the way, some of my previous comments are not addressed.

@@ -0,0 +1,172 @@
/*
* Copyright (C) 2018 2018 Otto-von-Guericke-Universität Magdeburg
Copy link
Contributor

Choose a reason for hiding this comment

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

2018 appears twice

@maribu
Copy link
Member Author

maribu commented Jun 12, 2018

In case you wonder why I put thumbs up on every comment: I in fact missed some and would like to tick them with a check mark. As there is no check mark, the thumbs up is what comes nearest to it. So it is just for me to check that I actually applied every comment

@maribu
Copy link
Member Author

maribu commented Jun 12, 2018

Done :-)

@aabadie aabadie added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: drivers Area: Device drivers labels Jun 12, 2018
Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

I like. I wanted to ACK but found 2 minor things remaining. See below.

@@ -105,6 +106,10 @@ PSEUDOMODULES += si7013
PSEUDOMODULES += si7020
PSEUDOMODULES += si7021

# include variants of SX127X drivers as pseudo modules
Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I understand. This block should be moved to its original place (before the si1145 pseudo modules). Normally only changes related to sht11/10/15 should appear.

/** @} */

/**
* @name Commands that can be send to the SHT1X driver
Copy link
Contributor

Choose a reason for hiding this comment

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

s/send/sent/

@aabadie aabadie added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jun 12, 2018
@aabadie
Copy link
Contributor

aabadie commented Jun 12, 2018

Just triggered Murdock, maybe some other things will raise.

@maribu
Copy link
Member Author

maribu commented Jun 13, 2018

Done. I believe I still have to add some boards to BOARD_INSUFFICIENT_MEMORY for the test, but lets wait for Murdock to complete

@aabadie
Copy link
Contributor

aabadie commented Jun 13, 2018

Murdock is still failing, I think you have to remove the DIRS = drivers in boards/common/msb-430/Makefile

@maribu
Copy link
Member Author

maribu commented Jun 13, 2018

The default pin configuration is invalid on telosb, wsn430-v1_3b, wsn430-v1_4 and z1. How should I handle that?

@maribu
Copy link
Member Author

maribu commented Jun 13, 2018

I just changed the way the SAUL info texts are added. The new way is a bit more clever and matches the strategy other drivers use

@aabadie
Copy link
Contributor

aabadie commented Jun 13, 2018

The default pin configuration is invalid on telosb, wsn430-v1_3b, wsn430-v1_4 and z1. How should I handle that?

No idea, this is related to 16bit platform but the error is weird. Maybe @cladmi has an idea ?

@maribu
Copy link
Member Author

maribu commented Jun 13, 2018

Hi,

cpu/msp430fxyz/include/periph_cpu.h contains:

typedef uint16_t gpio_t;
[...]
#define GPIO_PIN(x, y)      ((gpio_t)(((x & 0xff) << 8) | (1 << (y & 0xff))))

so for y > 15 the result of (1 << (y & 0xff)) is (as far as I know) not strictly defined, as a << b is only defined for 0 <= b < BITWIDTH(a). Changing that line to

#define GPIO_PIN(x, y)      ((gpio_t)(((x & 0xff) << 8) | (1 << (y & 0x0f))))

would make the result valid again. But maybe it is desired that the compilation fails for invalid pin specifications?

PS: I'm checking that right now with a dummy commit added on top of the PR. So please don't merge until I remove that again.
PPS: Test succeeded. Should the GPIO_PIN macro be changed (in a separate PR)?

@maribu
Copy link
Member Author

maribu commented Jun 14, 2018

@cladmi: Would this be a viable solution? If so, should I create an PR for that, or do you want to handle it?

maribu added 5 commits June 27, 2018 08:57
The sensor family SHT10, SHT11 and SHT15 only differ in their accuracy (as in
calibration, not as in resolution). Thus, the same driver can be used for all.
The new driver name better reflects this fact.
- Use RIOT's GPIO interface to access the sensor to increase portability
- Changed API to allow more than one sensor per board
- Added `sht1x_params.h` that specifies how the sensors is connected - each
  board can overwrite default settings by #defining SHT1X_PARAM_CLK and
  SHT1X_PARAM_DATA
- Changed arithmetic to use integer calculations only instead of floating point
  arithmetic
- Added support for checking the CRC sum
- Allow optional skipping of the CRC check to speed up measuring
- Added support for advanced features like reducing the resolution and skipping
  calibration to speed up measuring
- Allow specifying the supply voltage of sensor which heavily influences the
  temperature result (and use that information to calculate the correct
  temperature)
- Reset sensor on initialization to bring it in a well known state
- Support for the obscure heater feature. (Can be useful to check the
  temperature sensor?)
- Updated old SHT11 shell commands to the new driver interface, thus allowing
  more than one SHT10/11/15 sensor to be used
- Added new shell command to allow full configuration of all attached SHT1x
  sensors
- Removed old command for setting the SHT11 temperature offset, as this feature
  is implemented in the new configuration command
- Added unit tests for new integer only arithmetic
    - Temperature conversion differs at most 0.01°C from double arithmetic
    - Humidity conversions differs at most 0.1% from double arithmetic
@maribu
Copy link
Member Author

maribu commented Jun 27, 2018

@aabadie: I just rebased the PR against current master (and removed the testing commit). The issue with compilation on msp430fxyz boards is now fixed :-)

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

Looks good now.

Untested-ACK

@aabadie aabadie merged commit 6e6716a into RIOT-OS:master Jun 27, 2018
@maribu maribu deleted the sht1x branch June 27, 2018 08:28
@cladmi cladmi added this to the Release 2018.07 milestone Jul 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants