foxBMS - Unit Tests  1.2.1
The foxBMS Unit Tests API Documentation
htsensor.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file htsensor.c
44  * @author foxBMS Team
45  * @date 2021-08-05 (date of creation)
46  * @updated 2021-11-08 (date of last update)
47  * @ingroup DRIVERS
48  * @prefix HTSEN
49  *
50  * @brief Driver for the Sensirion SHT35-DIS I2C humidity/temperature sensor
51  *
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "htsensor.h"
56 
57 #include "database.h"
58 #include "i2c.h"
59 
60 /*========== Macros and Definitions =========================================*/
61 
62 /** Sensor I2C address */
63 #define HTSEN_I2C_ADDRESS (0x44u)
64 
65 /** Timeout to avoid infinite loops when waiting for results */
66 #define HTSEN_READ_TIMEOUT_10ms (10u)
67 
68 /** Timeout to wait for measurement in 10ms */
69 #define HTSEN_TIME_MEAS_WAIT_10ms (2u)
70 
71 /** Conversion coefficients to get measurement from raw temperature value @{ */
72 #define HTSEN_TEMP_SCALING (175.0f)
73 #define HTSEN_TEMP_OFFSET (-45.0f)
74 #define HTSEN_TEMP_DEG_TO_DDEG (10.0f)
75 /**@}*/
76 
77 /** Conversion coefficients to get measurement from raw humidity value @{ */
78 #define HTSEN_HUMIDITY_SCALING (100.0f)
79 #define HTSEN_FULL_SCALE (65535.0f)
80 /**@}*/
81 
82 /** Defines for byte positions for data handling @{ */
83 #define HTSEN_TEMPERATURE_LSB (1u)
84 #define HTSEN_TEMPERATURE_MSB (0u)
85 #define HTSEN_TEMPERATURE_BYTE_CRC (2u)
86 #define HTSEN_HUMIDITY_LSB (4u)
87 #define HTSEN_HUMIDITY_MSB (3u)
88 #define HTSEN_HUMIDITY_BYTE_CRC (5u)
89 #define HTSEN_BYTE_SHIFT (8u)
90 #define HTSEN_MEASUREMENT_LENGTH_IN_BYTES (2u)
91 #define HTSEN_TOTAL_DATA_LENGTH_IN_BYTES (6u)
92 /**@}*/
93 
94 /** Defines for sensor CRC computation @{ */
95 #define HTSEN_CRC_POLYNOMIAL (0x31u)
96 #define HTSEN_CRC_SEED (0xFF)
97 #define HTSEN_CRC_BYTE_SHIFT (0x8u)
98 #define HTSEN_CRC_MSB_MASK (0x80u)
99 #define HTSEN_CRC_8BIT_MASK (0xFFu)
100 /**@}*/
101 
102 /**
103  * Definition of single measurement command
104  * data sheet February 2019 - Version 6, table 9, page 10
105  *
106  * Clock stretching can be used to let sensor tell that the measurement
107  * is not finished by pulling the clock low
108  * Not recommended: if system is stopped during clock stretching,
109  * sensor could be blocked in this mode and render I2C bus unusable.
110  * !!!---WARNING---!!!: if clock stretching is used, the timeout in the
111  * receive loop of the function #I2C_ReadDirect() must be adapted,
112  * the current value is too small compared to the time the slave will
113  * make the master wait in the clock stretching mode.
114  *
115  * Depending on the clock stretching setting, the code for the instructions
116  * changes:
117  * -> With stretching
118  * - 1 MSB
119  * - 1 LSB for high repeatability
120  * - 1 LSB for medium repeatability
121  * - 1 LSB for low repeatability
122  * -> Without stretching
123  * - 1 MSB
124  * - 1 LSB for high repeatability
125  * - 1 LSB for medium repeatability
126  * - 1 LSB for low repeatability
127  * This results in 6 possible configurations
128  * Durability changes the measurement duration.
129  * @{
130  */
131 #define HTSEN_CLOCK_STRETCHING (false)
132 #if (HTSEN_CLOCK_STRETCHING == false)
133 #define HTSEN_SINGLE_MEAS_MSB (0x24u)
134 #define HTSEN_HIGH_REPEATABILITY (0x00u)
135 #define HTSEN_MEDIUM_REPEATABILITY (0x0Bu)
136 #define HTSEN_LOW_REPEATABILITY (0x16u)
137 #else
138 #define HTSEN_SINGLE_MEAS_MSB (0x2Cu)
139 #define HTSEN_HIGH_REPEATABILITY (0x06u)
140 #define HTSEN_MEDIUM_REPEATABILITY (0x0Du)
141 #define HTSEN_LOW_REPEATABILITY (0x10u)
142 #endif
143 
144 #define HTSEN_SINGLE_MEAS_LSB (HTSEN_HIGH_REPEATABILITY)
145 /**@}*/
146 
147 /*========== Static Constant and Variable Definitions =======================*/
148 
149 /**
150  * @brief describes the current state of the measurement
151  * @details This variable is used as a state-variable for switching through the
152  * steps of a conversion.
153  */
155 /** counter to wait before reading measurements after they were triggered */
156 static uint8_t htsen_counter = 0u;
157 /** timeout to restart measurement cycle if waiting too much to get results */
158 static uint8_t htsen_timeout_10ms = 0u;
159 
160 /** variable to store the measurement results */
162 
163 /*========== Extern Constant and Variable Definitions =======================*/
164 
165 /*========== Static Function Prototypes =====================================*/
166 
167 /**
168  * @brief computes CRC8.
169  * @param[in] data: data to use to compute CRC
170  * @param[in] length: length of data
171  * @return 8-bit CRC value
172  */
173 static uint8_t HTSENS_CalculateCrc8(const uint8_t *data, uint32_t length);
174 
175 /**
176  * @brief computes temperature measurement from raw value.
177  * @param[in] data: raw temperature value
178  * @return temperature measurement in deci °C
179  */
180 static int16_t HTSENS_ConvertRawTemperature(uint16_t data);
181 
182 /**
183  * @brief computes humidity measurement from raw value.
184  * @param[in] data: raw humidity value
185  * @return humidity measurement in %
186  */
187 static uint8_t HTSENS_ConvertRawHumidity(uint16_t data);
188 
189 /*========== Static Function Implementations ================================*/
190 
191 static uint8_t HTSENS_CalculateCrc8(const uint8_t *data, uint32_t length) {
192  FAS_ASSERT(data != NULL_PTR);
193  FAS_ASSERT(length <= UINT32_MAX);
194 
195  uint16_t crc = HTSEN_CRC_SEED;
196 
197  for (uint8_t i = 0u; i < length; i++) {
198  crc ^= data[i];
199  for (uint8_t j = 0u; j < HTSEN_CRC_BYTE_SHIFT; j++) {
200  if ((crc & HTSEN_CRC_MSB_MASK) != 0u) {
201  crc = ((crc << 1u) & HTSEN_CRC_8BIT_MASK) ^ HTSEN_CRC_POLYNOMIAL;
202  } else {
203  crc = (crc & HTSEN_CRC_8BIT_MASK) << 1u;
204  }
205  }
206  }
207  return (uint8_t)(crc & HTSEN_CRC_8BIT_MASK);
208 }
209 
210 static int16_t HTSENS_ConvertRawTemperature(uint16_t data) {
211  float temperature_ddeg = HTSEN_TEMP_DEG_TO_DDEG *
212  (HTSEN_TEMP_OFFSET + (HTSEN_TEMP_SCALING * (((float)data) / HTSEN_FULL_SCALE)));
213  return (int16_t)temperature_ddeg;
214 }
215 
216 static uint8_t HTSENS_ConvertRawHumidity(uint16_t data) {
217  float humidity_perc = (HTSEN_HUMIDITY_SCALING * (((float)data) / HTSEN_FULL_SCALE));
218  return (uint8_t)humidity_perc;
219 }
220 
221 /*========== Extern Function Implementations ================================*/
222 
223 extern void HTSEN_Trigger(void) {
224  uint8_t i2cWriteBuffer[2u] = {HTSEN_SINGLE_MEAS_MSB, HTSEN_SINGLE_MEAS_LSB};
225  uint8_t i2cReadBuffer[HTSEN_TOTAL_DATA_LENGTH_IN_BYTES] = {0u, 0u, 0u, 0u, 0u, 0u};
226  STD_RETURN_TYPE_e i2cReadReturn = STD_NOT_OK;
227 
228  switch (htsen_state) {
229  case HTSEN_START_MEAS:
230  /* Write to sensor to start measurement */
231  if (STD_OK == I2C_WriteDirect(HTSEN_I2C_ADDRESS, 2u, i2cWriteBuffer)) {
235  }
236  break;
237 
239  if (htsen_counter > 0u) {
240  htsen_counter--;
241  }
242  if (htsen_counter == 0u) {
244  break;
245  }
246  break;
247 
248  case HTSEN_READ_RESULTS:
249  i2cReadReturn = I2C_ReadDirect(HTSEN_I2C_ADDRESS, HTSEN_TOTAL_DATA_LENGTH_IN_BYTES, i2cReadBuffer);
250  if (i2cReadReturn != STD_OK) {
251  if (htsen_timeout_10ms > 0u) {
253  }
254  if (htsen_timeout_10ms == 0u) {
256  }
257  } else {
258  /* If measurement finished, retrieve values */
259  /* Only take temperature value if CRC valid */
260  if (i2cReadBuffer[HTSEN_TEMPERATURE_BYTE_CRC] ==
263  (((uint16_t)i2cReadBuffer[HTSEN_TEMPERATURE_MSB]) << HTSEN_BYTE_SHIFT) |
264  (uint16_t)i2cReadBuffer[HTSEN_TEMPERATURE_LSB]);
265  }
266  /* Only take humidity value if CRC valid */
267  if (i2cReadBuffer[HTSEN_HUMIDITY_BYTE_CRC] ==
270  (((uint16_t)i2cReadBuffer[HTSEN_HUMIDITY_MSB]) << HTSEN_BYTE_SHIFT) |
271  (uint16_t)i2cReadBuffer[HTSEN_HUMIDITY_LSB]);
272  }
275  }
276  break;
277 
278  default:
279  /* invalid state */
281  break;
282  }
283 }
284 
285 /*========== Getter for static Variables (Unit Test) ========================*/
286 
287 /*========== Externalized Static Function Implementations (Unit Test) =======*/
288 #ifdef UNITY_UNIT_TEST
289 extern uint8_t TEST_HTSEN_TestCalculateCrc8(uint8_t *data, uint32_t length) {
290  return HTSENS_CalculateCrc8(data, 2u);
291 }
292 #endif /* UNITY_UNIT_TEST */
Database module header.
#define DATA_WRITE_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_HTSEN
Definition: database_cfg.h:103
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:235
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:110
@ STD_NOT_OK
Definition: fstd_types.h:82
@ STD_OK
Definition: fstd_types.h:81
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:75
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
#define HTSEN_BYTE_SHIFT
Definition: htsensor.c:89
#define HTSEN_TEMPERATURE_BYTE_CRC
Definition: htsensor.c:85
#define HTSEN_CRC_MSB_MASK
Definition: htsensor.c:98
#define HTSEN_SINGLE_MEAS_LSB
Definition: htsensor.c:144
#define HTSEN_HUMIDITY_SCALING
Definition: htsensor.c:78
#define HTSEN_I2C_ADDRESS
Definition: htsensor.c:63
#define HTSEN_CRC_SEED
Definition: htsensor.c:96
#define HTSEN_HUMIDITY_LSB
Definition: htsensor.c:86
static uint8_t htsen_counter
Definition: htsensor.c:156
#define HTSEN_READ_TIMEOUT_10ms
Definition: htsensor.c:66
#define HTSEN_TEMP_OFFSET
Definition: htsensor.c:73
#define HTSEN_TOTAL_DATA_LENGTH_IN_BYTES
Definition: htsensor.c:91
#define HTSEN_TEMP_SCALING
Definition: htsensor.c:72
#define HTSEN_TEMPERATURE_MSB
Definition: htsensor.c:84
#define HTSEN_SINGLE_MEAS_MSB
Definition: htsensor.c:133
#define HTSEN_TEMPERATURE_LSB
Definition: htsensor.c:83
#define HTSEN_HUMIDITY_BYTE_CRC
Definition: htsensor.c:88
#define HTSEN_FULL_SCALE
Definition: htsensor.c:79
#define HTSEN_TEMP_DEG_TO_DDEG
Definition: htsensor.c:74
static int16_t HTSENS_ConvertRawTemperature(uint16_t data)
computes temperature measurement from raw value.
Definition: htsensor.c:210
static uint8_t HTSENS_CalculateCrc8(const uint8_t *data, uint32_t length)
computes CRC8.
Definition: htsensor.c:191
#define HTSEN_HUMIDITY_MSB
Definition: htsensor.c:87
#define HTSEN_MEASUREMENT_LENGTH_IN_BYTES
Definition: htsensor.c:90
static HTSEN_STATE_e htsen_state
describes the current state of the measurement
Definition: htsensor.c:154
static DATA_BLOCK_HTSEN_s htsen_data
Definition: htsensor.c:161
uint8_t TEST_HTSEN_TestCalculateCrc8(uint8_t *data, uint32_t length)
Definition: htsensor.c:289
#define HTSEN_TIME_MEAS_WAIT_10ms
Definition: htsensor.c:69
#define HTSEN_CRC_BYTE_SHIFT
Definition: htsensor.c:97
static uint8_t htsen_timeout_10ms
Definition: htsensor.c:158
#define HTSEN_CRC_POLYNOMIAL
Definition: htsensor.c:95
#define HTSEN_CRC_8BIT_MASK
Definition: htsensor.c:99
void HTSEN_Trigger(void)
triggers a measurement of the I2C humidity/temperature sensor.
Definition: htsensor.c:223
static uint8_t HTSENS_ConvertRawHumidity(uint16_t data)
computes humidity measurement from raw value.
Definition: htsensor.c:216
Header for the driver for the Sensirion SHT35-DIS I2C humidity/temperature sensor.
HTSEN_STATE_e
Definition: htsensor.h:65
@ HTSEN_READ_RESULTS
Definition: htsensor.h:68
@ HTSEN_START_MEAS
Definition: htsensor.h:66
@ HTSEN_WAIT_FOR_RESULTS
Definition: htsensor.h:67
STD_RETURN_TYPE_e I2C_WriteDirect(uint32_t slaveAddress, uint32_t nrBytes, uint8_t *writeData)
writes to an I2C slave, no register address written first, blocking.
Definition: i2c.c:356
STD_RETURN_TYPE_e I2C_ReadDirect(uint32_t slaveAddress, uint32_t nrBytes, uint8_t *readData)
reads from an I2C slave, no register address written first, blocking.
Definition: i2c.c:183
Header for the driver for the I2C module.
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:111
int16_t temperature_ddegC
Definition: database_cfg.h:557
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:556
uint8_t humidity_perc
Definition: database_cfg.h:558