SHT3x driver - some minor changes

- lookup tables made const to be held in flash
- crc8 computation changed to a non table lookup version
- measurement duration is now given in ticks and can be used directly
  for vTaskDelay (documentation and examples changed accordingly)
This commit is contained in:
Gunar Schorcht 2017-10-13 17:43:43 +02:00
parent 5a0fc09989
commit 1525f61fe3
5 changed files with 55 additions and 73 deletions

View file

@ -17,7 +17,7 @@
* +------------------------+ +----------+ * +------------------------+ +----------+
*/ */
// #define SINGLE_SHOT_MODE #define SINGLE_SHOT_MODE
#include "espressif/esp_common.h" #include "espressif/esp_common.h"
#include "esp/uart.h" #include "esp/uart.h"
@ -55,7 +55,7 @@ void user_task (void *pvParameters)
// passive waiting until measurement results are available // passive waiting until measurement results are available
if (duration > 0) if (duration > 0)
vTaskDelay (duration/portTICK_PERIOD_MS); vTaskDelay (duration);
// retrieve the values and do something with them // retrieve the values and do something with them
if (sht3x_get_results (sensor, &values)) if (sht3x_get_results (sensor, &values))

View file

@ -18,7 +18,7 @@
* | GPIO 12 (SDA) ------- SDA | * | GPIO 12 (SDA) ------- SDA |
* +------------------------+ +----------+ * +------------------------+ +----------+
*/ */
#include "espressif/esp_common.h" #include "espressif/esp_common.h"
#include "esp/uart.h" #include "esp/uart.h"
@ -61,7 +61,7 @@ void user_task_sensor1 (void *pvParameters)
// passive waiting until measurement results are available // passive waiting until measurement results are available
if (duration > 0) if (duration > 0)
vTaskDelay (duration/portTICK_PERIOD_MS); vTaskDelay (duration);
// retrieve the values and do something with them // retrieve the values and do something with them
if (sht3x_get_results (sensor1, &values)) if (sht3x_get_results (sensor1, &values))

View file

@ -119,7 +119,7 @@ void user_task (void *pvParameters)
// passive waiting until first measurement results are available // passive waiting until first measurement results are available
if (duration > 0) if (duration > 0)
vTaskDelay (duration/portTICK_PERIOD_MS); vTaskDelay (duration);
// busy waiting until first measurement results are available // busy waiting until first measurement results are available
// while (sht3x_is_measuring (sensor) > 0) ; // while (sht3x_is_measuring (sensor) > 0) ;
@ -140,7 +140,7 @@ void user_task (void *pvParameters)
} }
``` ```
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. 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 in RTOS ticks 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 has to be triggered 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. in each cycle. Waiting for measurement results is also required in each cylce, before the results can be fetched.
@ -162,7 +162,7 @@ void user_task (void *pvParameters)
// passive waiting until measurement results are available // passive waiting until measurement results are available
if (duration > 0) if (duration > 0)
vTaskDelay (duration/portTICK_PERIOD_MS); vTaskDelay (duration);
// busy waiting until first measurement results are available // busy waiting until first measurement results are available
// while (sht3x_is_measuring (sensor) > 0) ; // while (sht3x_is_measuring (sensor) > 0) ;
@ -233,7 +233,7 @@ static sht3x_sensor_t* sensor; // sensor device data structure
/* /*
* User task that fetches latest measurement results of sensor every 2 * User task that fetches latest measurement results of sensor every 2
* seconds. It starts the SHT3x in periodic mode with 1 measurements per * seconds. It starts the SHT3x in periodic mode with 1 measurements per
* second (*periodic_1mps*). It uses busy waiting for first measurement * second (*periodic_1mps*). It uses passive waiting for first measurement
* results. * results.
*/ */
void user_task (void *pvParameters) void user_task (void *pvParameters)
@ -242,9 +242,10 @@ void user_task (void *pvParameters)
// start periodic measurements with 1 measurement per second // start periodic measurements with 1 measurement per second
sht3x_start_measurement (sensor, periodic_1mps); sht3x_start_measurement (sensor, periodic_1mps);
// passive waiting until measurement results are available
if (duration > 0) if (duration > 0)
vTaskDelay (duration/portTICK_PERIOD_MS); vTaskDelay (duration);
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();

View file

@ -61,14 +61,14 @@
#define SHT3x_FETCH_DATA_CMD 0xE000 #define SHT3x_FETCH_DATA_CMD 0xE000
#define SHT3x_HEATER_OFF_CMD 0x3066 #define SHT3x_HEATER_OFF_CMD 0x3066
uint16_t SHT3x_MEASURE_CMD[6][3] = { {0x2c06,0x2c0d,0x2c10}, // [SINGLE_SHOT][H,M,L] const uint16_t SHT3x_MEASURE_CMD[6][3] = { {0x2c06,0x2c0d,0x2c10}, // [SINGLE_SHOT][H,M,L]
{0x2032,0x2024,0x202f}, // [PERIODIC_05][H,M,L] {0x2032,0x2024,0x202f}, // [PERIODIC_05][H,M,L]
{0x2130,0x2126,0x212d}, // [PERIODIC_05][H,M,L] {0x2130,0x2126,0x212d}, // [PERIODIC_05][H,M,L]
{0x2236,0x2220,0x222b}, // [PERIODIC_05][H,M,L] {0x2236,0x2220,0x222b}, // [PERIODIC_05][H,M,L]
{0x2234,0x2322,0x2329}, // [PERIODIC_05][H,M,L] {0x2234,0x2322,0x2329}, // [PERIODIC_05][H,M,L]
{0x2737,0x2721,0x272a} }; // [PERIODIC_05][H,M,L] {0x2737,0x2721,0x272a} }; // [PERIODIC_05][H,M,L]
int32_t SHT3x_MEASURE_DURATION[3] = {30,20,20}; // [High, Medium, Low] const int32_t SHT3x_MEASURE_DURATION[3] = {3,2,2}; // tick counts [High, Medium, Low]
#ifdef SHT3x_DEBUG #ifdef SHT3x_DEBUG
#define debug(s, f, ...) printf("%s %s: " s "\n", "SHT3x", f, ## __VA_ARGS__) #define debug(s, f, ...) printf("%s %s: " s "\n", "SHT3x", f, ## __VA_ARGS__)
@ -111,7 +111,7 @@ sht3x_sensor_t* sht3x_init_sensor(uint8_t bus, uint8_t addr)
dev->mode = single_shot; dev->mode = single_shot;
dev->repeatability = high; dev->repeatability = high;
dev->meas_started = false; dev->meas_started = false;
dev->meas_start_time = 0; dev->meas_start_tick = 0;
dev->active = true; dev->active = true;
@ -149,10 +149,10 @@ int32_t sht3x_start_measurement (sht3x_sensor_t* dev, sht3x_mode_t mode)
// start measurement according to selected mode and return an duration estimate // start measurement according to selected mode and return an duration estimate
if (sht3x_send_command(dev, SHT3x_MEASURE_CMD[dev->mode][dev->repeatability])) if (sht3x_send_command(dev, SHT3x_MEASURE_CMD[dev->mode][dev->repeatability]))
{ {
dev->meas_start_time = sdk_system_get_time (); dev->meas_start_tick = xTaskGetTickCount ();
dev->meas_started = true; dev->meas_started = true;
dev->meas_first = true; dev->meas_first = true;
return SHT3x_MEASURE_DURATION[dev->repeatability]; // in ms return SHT3x_MEASURE_DURATION[dev->repeatability]; // in RTOS ticks
} }
dev->error_code |= SHT3x_SEND_MEAS_CMD_FAILED; dev->error_code |= SHT3x_SEND_MEAS_CMD_FAILED;
@ -181,7 +181,7 @@ int32_t sht3x_is_measuring (sht3x_sensor_t* dev)
uint32_t elapsed_time; uint32_t elapsed_time;
elapsed_time = (sdk_system_get_time() - dev->meas_start_time) / 1000; // in ms elapsed_time = (xTaskGetTickCount() - dev->meas_start_tick); // in RTOS ticks
if (elapsed_time >= SHT3x_MEASURE_DURATION[dev->repeatability]) if (elapsed_time >= SHT3x_MEASURE_DURATION[dev->repeatability])
return 0; return 0;
@ -371,46 +371,24 @@ static bool sht3x_get_status (sht3x_sensor_t* dev, uint16_t* status)
} }
const uint8_t g_polynom = 0x31;
static uint8_t crc8_table[256]; // lookup table with precomputed crc values
static bool crc8_first_time = true; // indicator whether table has still to be created
static void generate_crc8_table()
{
const uint8_t g_polynom = 0x31;
for (int i=0; i < 256; i++)
{
uint8_t value = (uint8_t)i;
for (uint8_t bit = 0; bit < 8; bit++)
{
bool xor = value & 0x80;
value = value << 1;
value = xor ? value ^ g_polynom : value;
}
crc8_table[i] = value;
}
}
static uint8_t crc8 (uint8_t data[], int len) static uint8_t crc8 (uint8_t data[], int len)
{ {
// generate crc lookup table first time it is called
if (crc8_first_time)
{
crc8_first_time = false;
generate_crc8_table ();
}
// initialization value // initialization value
uint8_t crc = 0xff; uint8_t crc = 0xff;
// iterate over all bytes // iterate over all bytes
for (int i=0; i < len; i++) for (int i=0; i < len; i++)
{ {
uint8_t b = data[i]; crc ^= data[i];
uint8_t data = (uint8_t)(b ^ crc);
crc = (uint8_t)(crc8_table[data]); for (int i = 0; i < 8; i++)
{
bool xor = crc & 0x80;
crc = crc << 1;
crc = xor ? crc ^ g_polynom : crc;
}
} }
return crc; return crc;

View file

@ -137,7 +137,7 @@ typedef struct {
sht3x_repeat_t repeatability; // used repeatability sht3x_repeat_t repeatability; // used repeatability
bool meas_started; // indicates whether measurement started bool meas_started; // indicates whether measurement started
uint32_t meas_start_time; // measurement start time in microseconds TickType_t meas_start_tick; // measurement start time in RTOS ticks
bool meas_first; // first measurement in periodic mode bool meas_first; // first measurement in periodic mode
} sht3x_sensor_t; } sht3x_sensor_t;
@ -161,28 +161,31 @@ sht3x_sensor_t* sht3x_init_sensor (uint8_t bus, uint8_t addr);
* @brief Start single shot or periodic measurements * @brief Start single shot or periodic measurements
* *
* The function starts the measurement either in *single shot mode* * The function starts the measurement either in *single shot mode*
* (exactly one measurement) or *periodic mode* (periodic measurements). * (exactly one measurement) or *periodic mode* (periodic measurements) and
* returns an estimated measurement duration given in RTOS ticks.
* *
* In the *single shot mode*, this function has to be called for each * In the *single shot mode*, this function has to be called for each
* measurement. The measurement duration returned by the function has to be * measurement. The measurement duration returned by the function has to be
* waited every time before the results can be fetched. * waited every time before the results can be fetched.
* *
* In the *periodic mode*, this function has to be called only once. Also the * In the *periodic mode*, this function has to be called only once. Also
* measurement duration must be waited only once until the first results are * the measurement duration must be waited only once until the first
* available. After this first measurement, the sensor then automatically * results are available. After this first measurement, the sensor then
* performs all subsequent measurements. The rate of periodic measurements can * automatically performs all subsequent measurements. The rate of periodic
* be 10, 4, 2, 1 or 0.5 measurements per second (mps). The user task can * measurements can be 10, 4, 2, 1 or 0.5 measurements per second (mps). Due
* fetch the results with the half or less rate. The rate of the periodic * to inaccuracies in timing of the sensor, the user task should fetch the
* measurements is defined by the parameter *mode*. * results at a lower rate. The rate of the periodic measurements is defined
* by the parameter *mode*.
* *
* On success, the function returns an estimated measurement duration. This * On success, the function returns an estimated measurement duration given
* defines the duration needed by the sensor before first results become * in RTOS ticks. This defines the duration needed by the sensor before
* available. The user task has to wait this time before it can fetch the * first results become available. The user task has to wait this time
* results using function *sht3x_get_results* or *sht3x_get_raw_data*. * before it can fetch the results using function *sht3x_get_results* or
* *sht3x_get_raw_data*.
* *
* @param dev pointer to sensor device data structure * @param dev pointer to sensor device data structure
* @param mode measurement mode, see type *sht3x_mode_t* * @param mode measurement mode, see type *sht3x_mode_t*
* @return true on success, false on error * @return measurement duration in RTOS ticks or -1 on error
*/ */
int32_t sht3x_start_measurement (sht3x_sensor_t* dev, sht3x_mode_t mode); int32_t sht3x_start_measurement (sht3x_sensor_t* dev, sht3x_mode_t mode);
@ -190,9 +193,9 @@ int32_t sht3x_start_measurement (sht3x_sensor_t* dev, sht3x_mode_t mode);
/** /**
* @brief Check whether measurement is still running * @brief Check whether measurement is still running
* *
* The function can be used to test whether a measurement has been started * The function can be used to test whether a measurement has been
* at all and how long it still takes before measurement results become * started and how long it still takes before measurement results
* available. The return value can be * become available. The return value is given in RTOS ticks and can be
* *
* >0 in case the measurement is is still running, * >0 in case the measurement is is still running,
* 0 in case the measurement has been already finished, or * 0 in case the measurement has been already finished, or
@ -201,8 +204,8 @@ int32_t sht3x_start_measurement (sht3x_sensor_t* dev, sht3x_mode_t mode);
* That is, a return value greater than 0 indicates that the measurement * That is, a return value greater than 0 indicates that the measurement
* results are still not available and the user task has to wait that time. * results are still not available and the user task has to wait that time.
* *
* @param dev pointer to sensor device data structure * @param dev pointer to sensor device data structure
* @return remaining measurement duration or -1 on error * @return remaining measurement duration in RTOS ticks or -1 on error
*/ */
int32_t sht3x_is_measuring (sht3x_sensor_t* dev); int32_t sht3x_is_measuring (sht3x_sensor_t* dev);