SHT3x driver - small changes
README.md has been shortened
This commit is contained in:
parent
b0ebf3385e
commit
3fee4b8f0c
1 changed files with 110 additions and 78 deletions
|
|
@ -1,63 +1,48 @@
|
|||
# Driver for **SHT3x** digital **temperature and humidity sensor**
|
||||
|
||||
This driver is written for usage with the ESP8266 and FreeRTOS using the I2C interface driver. It supports multiple sensors connected to the same or different I2C interfaces.
|
||||
This driver is written for usage with the ESP8266 and FreeRTOS using the I2C interface driver. It supports multiple SHT3x sensors connected to the same or different I2C interfaces.
|
||||
|
||||
## About the sensor
|
||||
|
||||
SHT3x is a digital temperature and humidity sensor that uses an I2C interface with up to 1 MHz communication speed. It can operate with **three levels of repeatability** (low, medium and high) and in two different modes, the **single shot data acquisition mode** (or short **single shot mode**) and the **periodic data acquisition mode** (or short **periodic mode**).
|
||||
|
||||
### Repeatability
|
||||
## Measurement process
|
||||
|
||||
Repeatability or test–retest reliability is the variation in measurement results taken by the sensor under the same conditions, and in a short period of time. It is a measure for the noise on the physical sensor output. The higher the repeatability the smaller are changes in the output subsequent measurements.
|
||||
Once the SHT3x sensor is initialized, it can be used for measurements.
|
||||
|
||||
The repeatability settings influences the measurement duration as well as the power consumption of the sensor. The measurement takes 3 ms with low repeatability, 5 ms with medium repeatability and 13.5 ms with high repeatability. That is, the measurement produces a noticeable delay in execution.
|
||||
### Single shot mode
|
||||
|
||||
While the sensor measures at the lowest repeatability, the average current consumption is 800 μA. That is, the higher the repeatability level, the longer the measurement takes and the higher the power consumption. The sensor consumes only 0.2 μA in standby mode.
|
||||
In **single shot mode**, a measurement command triggers the acquisition of **exactly one data pair**. Each data pair consists of temperature and humidity as 16-bit decimal values.
|
||||
|
||||
### Single shot data acquisition mode
|
||||
Due to the measurement duration of up to 30 ms, the measurement process is separated into steps to avoid blocking the user task during measurements:
|
||||
|
||||
In this mode, a measurement command triggers the acquisition of **exactly one data pair**. Each data pair consists of temperature and humidity as 16-bit decimal values.
|
||||
1. Trigger the sensor with function **_sht3x_start_measurement_** to start exactly one single measurement.
|
||||
|
||||
### Periodic data acquisition mode
|
||||
2. Wait the measurement duration until the results are available using passive waiting with function **_vTaskDelay_** or busy waiting with function **_sht3x_is_measuring_**.
|
||||
|
||||
In this mode, one issued measurement command yields a stream of data pairs. Each data pair again consists of temperature and humidity as 16-bit decimal values. As soon as the measurement command has been sent to the sensor, it performs measurements **periodically at a rate of 0.5, 1, 2, 4 or 10 measurements per second (mps)**. The data pairs can be read with a fetch command at the same rate.
|
||||
3. Fetch the results as floating point sensor values with function **sht3x_get_results_** or as raw data with function **sht3x_get_raw_data_**.
|
||||
|
||||
As in the *single shot mode*, the repeatability setting affects both the measurement duration and the current consumption of the sensor, see above.
|
||||
In the *single shot mode*, the user task has to perform all steps every time new sensor values are needed. When using the *single image mode*, however, a delay of up to 30 ms is generated for each measurement.
|
||||
|
||||
The advantage of this mode is that the sensor can switch between successive measurements into the sleep mode, which is more energy-efficient. This is particularly useful when the measurement rate is less than 1 measurement per second.
|
||||
|
||||
## How the driver works
|
||||
### Periodic mode
|
||||
|
||||
The driver supports multiple SHT3x sensors at the same time. They can be connected with different addresses at the same I2C bus or with arbitrary addresses to different I2C buses. Each sensor has to be initialized at the beginning using function **_sht3x_init_sensor_**. Parameters are the I2C bus and address at which the sensor is connected.
|
||||
In this mode, one issued measurement command yields a stream of data pairs. Each data pair consists again of temperature and humidity as 16-bit decimal values. As soon as the measurement command has been sent to the sensor, it automatically performs measurements **periodically at a rate of 0.5, 1, 2, 4 or 10 measurements per second (mps)**. The data pairs can be fetched with the same rate or a less rate.
|
||||
|
||||
### Measurement process
|
||||
As in *single shot mode*, the measurement process is separated into the following steps:
|
||||
|
||||
Once the sensor is initialized and tested, it can be used for measurements. In order to avoid blocking of user tasks during measurements due to their duration, the measurement process is splitted into the following steps:
|
||||
1. Trigger the sensor with function **sht3x_start_measurement_** and the rate of periodic measurements to start periodic measurements.
|
||||
|
||||
1. Trigger the sensor to start the measurement either in *single shot mode* or in *periodic mode*.
|
||||
2. Wait the measurement duration until the results are available using passive waiting with function **_vTaskDelay_** or busy waiting with function **_sht3x_is_measuring_**.
|
||||
|
||||
2. Fetch the values from the sensor once in *single shot mode* or periodically in *periodic mode*
|
||||
3. Fetch the results as floating point sensor values with function **sht3x_get_results_** or as raw data with function **sht3x_get_raw_data_**.
|
||||
|
||||
Between the first step and the second step, the sensor performs the measurement, which can take up to 30 ms. During that time the user task has to wait.
|
||||
However, in contrast to the *single shot mode*, steps 1 and 2 have to be executed only once. Once the measurement is started, the user task hast can simply fetch data periodically.
|
||||
|
||||
#### Single shot data acquisition mode
|
||||
The rate of fetching the data must be not greater than the rate of periodic measuring rate of the sensor, however, it *should be less* to avoid conflicts caused by the timing tolerance of the sensor.
|
||||
|
||||
In the *single shot mode*, the user task has to execute both steps every time new sensor values are needed, including the waiting time. The advantage of this mode is that the sensor can switch between successive measurements into the sleep mode which is more power-efficient. However, using the *single shot mode* produces a delay of up to 30 ms for each measurement.
|
||||
|
||||
#### Periodic data acquisition mode
|
||||
|
||||
In the *periodic mode*, the sensor automatically performs periodic measurements. Once the sensor has been triggered to start periodic measurements, new measurement results become available every 100 ms, 250 ms, 500 ms, 1000 ms or 2000 ms. The user task has simply to fetch them. Of course, the rate of fetching new measurement results must be less than the rate used by the sensor. The only waiting time required in this mode is the time between the start of the periodic measurements and the time when the first measurement results become available.
|
||||
|
||||
As in the *single shot mode* the sensor switches to the sleep mode between successive measurements. Thus, the *periodic mode* becomes as power-efficient as the *single shot mode* when at least one measurement result per second is required by the user task. Only, if the user task requires new measurement results seldom, e.g. one measurement per minute, then the *single shot mode* is the better choice.
|
||||
|
||||
### Starting measurement
|
||||
|
||||
Measurements are started using function **_sht3x_start_measurement_**. The SHT3x data acquisition mode to be used is defined by a parameter. In both modes, the highest repeatability is used.
|
||||
|
||||
If the measurement could be started successfully, the function returns an estimated duration until the first measurement results become available. The user task can use this duration with function **_vTaskDelay_** to wait until the measurement results are available. Alternatively, function **_sht3x_is_running_** can be used to realize a busy waiting. This function returns the remaining duration until the measurement will be finished.
|
||||
|
||||
Please note: Since *vTaskDelay* can only handle delays as multiples of 10 ms, the duration obtained as return value from function *sht3x_start_measurement* is 30 ms for high repeatability and 20 ms for medium as well as low repeatability.
|
||||
|
||||
### Measured data
|
||||
## Measurement results
|
||||
|
||||
Once new measurement results are available, either function **_sht3x_get_raw_data_** or function **_sht3x_get_results_** can be used to fetch the results.
|
||||
|
||||
|
|
@ -66,13 +51,23 @@ Function **__sht3x_get_raw_data_** fetches only the raw sensor data in 16-decima
|
|||
Function **_sht3x_get_results_** combines function *sht3x_read_raw_data* and function
|
||||
*sht3x_compute_values_* to get the latest sensor values. This is the preferred approach to get sensor values by the user task.
|
||||
|
||||
In the **periodic mode**, the function *sht3x get_results* can be executed repeatedly without a new call of function *sht3_start_measurement* and without a new waiting time. However, the rate of the repeated call should be less than the half of the periodic measuring rate of the sensor.
|
||||
|
||||
## Error Handling
|
||||
|
||||
Most driver functions return a simple boolean value to indicate whether its execution was successful or an error happened. In later case, the member **_error_code_** of the sensor device data structure is set which indicates what error happened.
|
||||
Most driver functions return a simple boolean value to indicate whether its execution was successful or an error happened. In the latter case, the member **_error_code_** of the sensor device data structure is set which indicates what error happened.
|
||||
|
||||
There are two different error levels that are ORed into one single *error_code*, errors in the I2C communication and errors with the SHT3x sensor itself. To test for a certain error you can AND the *error_code* with one of the error masks, **_SHT3x_I2C_ERROR_MASK_** for I2C errors and **_SHT3x_DRV_ERROR_MASK_** for other errors and then test for a certain error code.
|
||||
|
||||
|
||||
## Repeatability
|
||||
|
||||
The SHT3x sensor supports **three levels of repeatability** (low, medium and high). Repeatability is the variation in measurement results taken by the sensor under the same conditions, and in a short period of time. It is a measure for the noise on the physical sensor output. The higher the repeatability the smaller are changes in the output subsequent measurements.
|
||||
|
||||
The repeatability settings influences the measurement duration as well as the power consumption of the sensor. The measurement takes 3 ms with low repeatability, 5 ms with medium repeatability and 13.5 ms with high repeatability. That is, the measurement produces a noticeable delay in execution.
|
||||
|
||||
While the sensor measures at the lowest repeatability, the average current consumption is 800 μA. That is, the higher the repeatability level, the longer the measurement takes and the higher the power consumption. The sensor consumes only 0.2 μA in standby mode.
|
||||
|
||||
Measurements started using function **_sht3x_start_measurement_** always use highest repeatability level by default. User task can change this by setting member **_repeatability_** of the sensor device data structure before function **_sht3x_start_measurement_** is called.
|
||||
|
||||
There are two different error levels that are ORed into one single *error_code*, errors in I2C communication and errors with the SHT3x sensor itself. To test for a certain error you can AND the *error_code* with one of the error masks, **_SHT3x_I2C_ERROR_MASK_** for I2C errors and **_SHT3x_DRV_ERROR_MASK_** for other errors and then test for a certain error code.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
@ -90,16 +85,15 @@ i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K))
|
|||
...
|
||||
```
|
||||
|
||||
```
|
||||
sht3x_init_driver();
|
||||
```
|
||||
|
||||
Once I2C interfaces are initialized, function **_sht3x_init_sensor_** has to be called for each sensor to initialize the sensor and to check its availability as well as its error state. The parameters specify the I2C bus and address to which it is connected.
|
||||
Once I2C interfaces are initialized, function **_sht3x_init_sensor_** has to be called for each SHT3x sensor to initialize the sensor and to check its availability as well as its error state. The parameters specify the I2C bus to which it is connected and its I2C slave address.
|
||||
|
||||
```
|
||||
static sht3x_sensor_t* sensor; // pointer to sensor device data structure
|
||||
...
|
||||
sensor = sht3x_init_sensor (I2C_BUS, SHT3x_ADDR_2);
|
||||
if ((sensor = sht3x_init_sensor (I2C_BUS, SHT3x_ADDR_2)))
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Function **_sht3x_init_sensor_** returns a pointer to the sensor device data structure or NULL in case of error.
|
||||
|
|
@ -110,54 +104,51 @@ Last, the user task that uses the sensor has to be created.
|
|||
xTaskCreate(user_task, "user_task", 256, NULL, 2, 0);
|
||||
```
|
||||
|
||||
The user task can use the sensor in two different ways, either in *periodic mode* or in *single shot mode*.
|
||||
In the **periodic mode**, the user task has to start the periodic measurement only once at the beginning of the task. After that, it has only to wait for the results of the first measurement. In the task loop itself, it simply fetches the next measurement results in each cycle.
|
||||
|
||||
In *periodic mode* the user task calls function **_sht3x_start_measurement_** only once and fetches the measurement result in each cycle with function **_sht3x_get_results_** without any delay. In this mode the user task could look like the following:
|
||||
Thus, in this mode the user task could look like the following:
|
||||
|
||||
```
|
||||
void user_task(void *pvParameters)
|
||||
void user_task (void *pvParameters)
|
||||
{
|
||||
sht3x_values_t values;
|
||||
int32_t duration;
|
||||
|
||||
// start periodic measurements with 1 measurement per second
|
||||
duration = sht3x_start_measurement (sensor, periodic_1mps);
|
||||
|
||||
// busy waiting
|
||||
// while (sht3x_is_measuring (sensor) > 0) ;
|
||||
|
||||
// suspend the task for waiting
|
||||
// passive waiting until first measurement results are available
|
||||
if (duration > 0)
|
||||
vTaskDelay (duration/portTICK_PERIOD_MS);
|
||||
|
||||
TickType_t last_wakeup = xTaskGetTickCount();
|
||||
|
||||
// busy waiting until first measurement results are available
|
||||
// while (sht3x_is_measuring (sensor) > 0) ;
|
||||
|
||||
TickType_t last_wakeup = xTaskGetTickCount();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// retrieve the values and do something with them
|
||||
// get the values and do something with them
|
||||
if (sht3x_get_results (sensor, &values))
|
||||
printf("%.3f SHT3x Sensor: %.2f °C, %.2f %%\n",
|
||||
(double)sdk_system_get_time()*1e-3,
|
||||
values.temperature, values.humidity);
|
||||
|
||||
// passive waiting until 2 seconds are over
|
||||
// passive waiting until 2 seconds (cycle time) are over
|
||||
vTaskDelayUntil(&last_wakeup, 2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
```
|
||||
At the beginning of the task, the periodic measurement is started by function **_sht3x_start_measurement_** with a rate of 1 measurements per second. Using the duration returned from this function, the task is delayed using **_vTaskDelay_**. This is the duration until the first measurement results become available. The busy waiting alternative is shown in comments.
|
||||
|
||||
Inside the task loop, the measurement results are fetched periodically using function **_sht3x_get_results_** with a rate of once per second.
|
||||
At the beginning of the task, the periodic measurement is started by function **_sht3x_start_measurement_** with a rate of 1 measurement per second. Using the measurement duration returned from this function, the task is delayed using **_vTaskDelay_** to wait for first measurement results. The busy waiting alternative using function **_sht3x_is_measuring_** is shown in comments. Inside the task loop, the measurement results are fetched periodically using function **_sht3x_get_results_** with a rate of once per second.
|
||||
|
||||
In the *single shot mode*, the measurement in each cycle consist of the three steps:
|
||||
|
||||
- start the measurement using function **sht3x_start_measurement_**
|
||||
- waiting the measurement duration
|
||||
- fetch the results using function **sht3x_get_results_**
|
||||
In the **single shot mode**, the measurement has to be triggered
|
||||
in each cycle. Waiting for measurement results is also required in each cylce, before the results can be fetched.
|
||||
|
||||
Thus the user task could look like the following:
|
||||
|
||||
```
|
||||
void user_task(void *pvParameters)
|
||||
void user_task (void *pvParameters)
|
||||
{
|
||||
sht3x_values_t values;
|
||||
int32_t duration;
|
||||
|
|
@ -169,13 +160,13 @@ void user_task(void *pvParameters)
|
|||
// trigger one measurement in single shot mode
|
||||
duration = sht3x_start_measurement (sensor, single_shot);
|
||||
|
||||
// busy waiting
|
||||
// while (sht3x_is_measuring (sensor) > 0) ;
|
||||
|
||||
// passive waiting until measurement results are available
|
||||
if (duration > 0)
|
||||
vTaskDelay (duration/portTICK_PERIOD_MS);
|
||||
|
||||
// busy waiting until first measurement results are available
|
||||
// while (sht3x_is_measuring (sensor) > 0) ;
|
||||
|
||||
// retrieve the values and do something with them
|
||||
if (sht3x_get_results (sensor, &values))
|
||||
printf("%.3f SHT3x Sensor: %.2f °C, %.2f %%\n",
|
||||
|
|
@ -185,8 +176,40 @@ void user_task(void *pvParameters)
|
|||
// passive waiting until 5 seconds are over
|
||||
vTaskDelayUntil(&last_wakeup, 5000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In contrast to the *periodic mode*, the function **_sht3x_start_measurement_** is called inside the task loop to start exactly one measurement in each cycle. The task is then also delayed every time using function **_vTaskDelay_** before the results are fetched with function **_sht3x_get_results_** in each cycle.
|
||||
|
||||
The code could be extended by an error handling. In the event of an error, most driver functions use the **_error_code_** element of the data structure of the sensor device. This indicates which error has occurred. Error codes are a combination of I2C communication error codes and SHT3x sensor error codes. To test a particular error, the *error code* can be AND with one of the error masks **_SHT3x_I2C_ERROR_MASK_** or **_SHT3x_DRV_ERROR_MASK_**.
|
||||
|
||||
For example, error handling for **_sht3x_get_results_** could look like:
|
||||
```
|
||||
|
||||
if (sht3x_get_results (sensor, &values))
|
||||
{
|
||||
// no error happened
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
// error happened
|
||||
|
||||
switch (sensor->error_code & SHT3x_I2C_ERROR_MASK)
|
||||
{
|
||||
case SHT3x_I2C_BUSY: ...
|
||||
case SHT3x_I2C_READ_FAILED: ...
|
||||
...
|
||||
}
|
||||
switch (sensor->error_code & SHT3x_DRV_ERROR_MASK)
|
||||
{
|
||||
case SHT3x_MEAS_NOT_RUNNING: ...
|
||||
case SHT3x_READ_RAW_DATA_FAILED: ...
|
||||
case SHT3x_WRONG_CRC_TEMPERATURE: ...
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
In contrast to the *periodic mode*, the function **_sht3x_start_measurement_** is called inside the task loop to start the measurement in each cycle. The task is then also delayed every time.
|
||||
|
||||
## Full Example
|
||||
|
||||
|
|
@ -207,30 +230,37 @@ In contrast to the *periodic mode*, the function **_sht3x_start_measurement_** i
|
|||
|
||||
static sht3x_sensor_t* sensor; // sensor device data structure
|
||||
|
||||
/*
|
||||
* User task that fetches latest measurement results of sensor every 2
|
||||
* seconds. It starts the SHT3x in periodic mode with 1 measurements per
|
||||
* second (*periodic_1mps*). It uses busy waiting for first measurement
|
||||
* results.
|
||||
*/
|
||||
void user_task (void *pvParameters)
|
||||
{
|
||||
sht3x_values_t values;
|
||||
|
||||
// start periodic measurement mode
|
||||
// start periodic measurements with 1 measurement per second
|
||||
sht3x_start_measurement (sensor, periodic_1mps);
|
||||
|
||||
// busy waiting until measurement results are available
|
||||
while (sht3x_is_measuring (sensor) > 0) ;
|
||||
if (duration > 0)
|
||||
vTaskDelay (duration/portTICK_PERIOD_MS);
|
||||
|
||||
TickType_t last_wakeup = xTaskGetTickCount();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// retrieve the values and do something with them
|
||||
// get the values and do something with them
|
||||
if (sht3x_get_results (sensor, &values))
|
||||
printf("%.3f SHT3x Sensor: %.2f °C, %.2f %%\n",
|
||||
(double)sdk_system_get_time()*1e-3,
|
||||
values.temperature, values.humidity);
|
||||
|
||||
// passive waiting until 2 seconds are over
|
||||
|
||||
// passive waiting until 2 seconds (cycle time) are over
|
||||
vTaskDelayUntil(&last_wakeup, 2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
|
|
@ -245,11 +275,13 @@ void user_init(void)
|
|||
i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K);
|
||||
|
||||
// Create sensors
|
||||
sensor = sht3x_init_sensor (I2C_BUS, SHT3x_ADDR_2);
|
||||
|
||||
// Create a user task that uses the sensor
|
||||
xTaskCreate(user_task, "user_task", 256, NULL, 2, 0);
|
||||
if ((sensor = sht3x_init_sensor (I2C_BUS, SHT3x_ADDR_2)))
|
||||
{
|
||||
// Create a user task that uses the sensor
|
||||
xTaskCreate(user_task, "user_task", 256, NULL, 2, 0);
|
||||
|
||||
}
|
||||
|
||||
// That's it.
|
||||
}
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue