foxBMS - Unit Tests  1.4.1
The foxBMS Unit Tests API Documentation
htsensor.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, 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 2022-10-27 (date of last update)
47  * @version v1.4.1
48  * @ingroup DRIVERS
49  * @prefix HTSEN
50  *
51  * @brief Driver for the Sensirion SHT35-DIS I2C humidity/temperature sensor
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "htsensor.h"
57 
58 #include "database.h"
59 #include "i2c.h"
60 
61 /*========== Macros and Definitions =========================================*/
62 
63 /** Sensor I2C address */
64 #define HTSEN_I2C_ADDRESS (0x44u)
65 
66 /** Timeout to avoid infinite loops when waiting for results */
67 #define HTSEN_READ_TIMEOUT_10ms (10u)
68 
69 /** Timeout to wait for measurement in 10ms */
70 #define HTSEN_TIME_MEAS_WAIT_10ms (2u)
71 
72 /** Conversion coefficients to get measurement from raw temperature value @{ */
73 #define HTSEN_TEMP_SCALING (175.0f)
74 #define HTSEN_TEMP_OFFSET (-45.0f)
75 #define HTSEN_TEMP_DEG_TO_DDEG (10.0f)
76 /**@}*/
77 
78 /** Conversion coefficients to get measurement from raw humidity value @{ */
79 #define HTSEN_HUMIDITY_SCALING (100.0f)
80 #define HTSEN_FULL_SCALE (65535.0f)
81 /**@}*/
82 
83 /** Defines for byte positions for data handling @{ */
84 #define HTSEN_TEMPERATURE_LSB (1u)
85 #define HTSEN_TEMPERATURE_MSB (0u)
86 #define HTSEN_TEMPERATURE_BYTE_CRC (2u)
87 #define HTSEN_HUMIDITY_LSB (4u)
88 #define HTSEN_HUMIDITY_MSB (3u)
89 #define HTSEN_HUMIDITY_BYTE_CRC (5u)
90 #define HTSEN_BYTE_SHIFT (8u)
91 #define HTSEN_MEASUREMENT_LENGTH_IN_BYTES (2u)
92 #define HTSEN_TOTAL_DATA_LENGTH_IN_BYTES (6u)
93 /**@}*/
94 
95 /** Defines for sensor CRC computation @{ */
96 #define HTSEN_CRC_POLYNOMIAL (0x31u)
97 #define HTSEN_CRC_SEED (0xFF)
98 #define HTSEN_CRC_BYTE_SHIFT (0x8u)
99 #define HTSEN_CRC_MSB_MASK (0x80u)
100 #define HTSEN_CRC_8BIT_MASK (0xFFu)
101 /**@}*/
102 
103 /**
104  * Definition of single measurement command
105  * data sheet February 2019 - Version 6, table 9, page 10
106  *
107  * Clock stretching can be used to let sensor tell that the measurement
108  * is not finished by pulling the clock low
109  * Not recommended: if system is stopped during clock stretching,
110  * sensor could be blocked in this mode and render I2C bus unusable.
111  * !!!---WARNING---!!!: if clock stretching is used, the timeout in the
112  * receive loop of the function #I2C_ReadDirect() must be adapted,
113  * the current value is too small compared to the time the slave will
114  * make the master wait in the clock stretching mode.
115  *
116  * Depending on the clock stretching setting, the code for the instructions
117  * changes:
118  * -> With stretching
119  * - 1 MSB
120  * - 1 LSB for high repeatability
121  * - 1 LSB for medium repeatability
122  * - 1 LSB for low repeatability
123  * -> Without stretching
124  * - 1 MSB
125  * - 1 LSB for high repeatability
126  * - 1 LSB for medium repeatability
127  * - 1 LSB for low repeatability
128  * This results in 6 possible configurations
129  * Durability changes the measurement duration.
130  * @{
131  */
132 #define HTSEN_CLOCK_STRETCHING (false)
133 #if (HTSEN_CLOCK_STRETCHING == false)
134 #define HTSEN_SINGLE_MEAS_MSB (0x24u)
135 #define HTSEN_HIGH_REPEATABILITY (0x00u)
136 #define HTSEN_MEDIUM_REPEATABILITY (0x0Bu)
137 #define HTSEN_LOW_REPEATABILITY (0x16u)
138 #else
139 #define HTSEN_SINGLE_MEAS_MSB (0x2Cu)
140 #define HTSEN_HIGH_REPEATABILITY (0x06u)
141 #define HTSEN_MEDIUM_REPEATABILITY (0x0Du)
142 #define HTSEN_LOW_REPEATABILITY (0x10u)
143 #endif
144 
145 #define HTSEN_SINGLE_MEAS_LSB (HTSEN_HIGH_REPEATABILITY)
146 /**@}*/
147 
148 /*========== Static Constant and Variable Definitions =======================*/
149 
150 /**
151  * @brief describes the current state of the measurement
152  * @details This variable is used as a state-variable for switching through the
153  * steps of a conversion.
154  */
156 /** counter to wait before reading measurements after they were triggered */
157 static uint8_t htsen_counter = 0u;
158 /** timeout to restart measurement cycle if waiting too much to get results */
159 static uint8_t htsen_timeout_10ms = 0u;
160 
161 /** variable to store the measurement results */
163 
164 /*========== Extern Constant and Variable Definitions =======================*/
165 
166 /*========== Static Function Prototypes =====================================*/
167 
168 /**
169  * @brief computes CRC8.
170  * @param[in] data: data to use to compute CRC
171  * @param[in] length: length of data
172  * @return 8-bit CRC value
173  */
174 static uint8_t HTSEN_CalculateCrc8(const uint8_t *data, uint32_t length);
175 
176 /**
177  * @brief computes temperature measurement from raw value.
178  * @param[in] data: raw temperature value
179  * @return temperature measurement in deci °C
180  */
181 static int16_t HTSEN_ConvertRawTemperature(uint16_t data);
182 
183 /**
184  * @brief computes humidity measurement from raw value.
185  * @param[in] data: raw humidity value
186  * @return humidity measurement in %
187  */
188 static uint8_t HTSEN_ConvertRawHumidity(uint16_t data);
189 
190 /*========== Static Function Implementations ================================*/
191 
192 static uint8_t HTSEN_CalculateCrc8(const uint8_t *data, uint32_t length) {
193  FAS_ASSERT(data != NULL_PTR);
194  FAS_ASSERT(length <= UINT32_MAX);
195 
196  uint16_t crc = HTSEN_CRC_SEED;
197 
198  for (uint8_t i = 0u; i < length; i++) {
199  crc ^= data[i];
200  for (uint8_t j = 0u; j < HTSEN_CRC_BYTE_SHIFT; j++) {
201  if ((crc & HTSEN_CRC_MSB_MASK) != 0u) {
202  crc = ((crc << 1u) & HTSEN_CRC_8BIT_MASK) ^ HTSEN_CRC_POLYNOMIAL;
203  } else {
204  crc = (crc & HTSEN_CRC_8BIT_MASK) << 1u;
205  }
206  }
207  }
208  return (uint8_t)(crc & HTSEN_CRC_8BIT_MASK);
209 }
210 
211 static int16_t HTSEN_ConvertRawTemperature(uint16_t data) {
212  /* AXIVION Routine Generic-MissingParameterAssert: data: parameter accepts whole range */
213  float temperature_ddeg = HTSEN_TEMP_DEG_TO_DDEG *
214  (HTSEN_TEMP_OFFSET + (HTSEN_TEMP_SCALING * (((float)data) / HTSEN_FULL_SCALE)));
215  return (int16_t)temperature_ddeg;
216 }
217 
218 static uint8_t HTSEN_ConvertRawHumidity(uint16_t data) {
219  float humidity_perc = (HTSEN_HUMIDITY_SCALING * (((float)data) / HTSEN_FULL_SCALE));
220  return (uint8_t)humidity_perc;
221 }
222 
223 /*========== Extern Function Implementations ================================*/
224 
225 extern void HTSEN_Trigger(void) {
226  uint8_t i2cWriteBuffer[2u] = {HTSEN_SINGLE_MEAS_MSB, HTSEN_SINGLE_MEAS_LSB};
227  uint8_t i2cReadBuffer[HTSEN_TOTAL_DATA_LENGTH_IN_BYTES] = {0u, 0u, 0u, 0u, 0u, 0u};
228  STD_RETURN_TYPE_e i2cReadReturn = STD_NOT_OK;
229 
230  switch (htsen_state) {
231  case HTSEN_START_MEAS:
232  /* Write to sensor to start measurement */
233  if (STD_OK == I2C_WriteDirect(HTSEN_I2C_ADDRESS, 2u, i2cWriteBuffer)) {
237  }
238  break;
239 
241  if (htsen_counter > 0u) {
242  htsen_counter--;
243  }
244  if (htsen_counter == 0u) {
246  break;
247  }
248  break;
249 
250  case HTSEN_READ_RESULTS:
251  i2cReadReturn = I2C_ReadDirect(HTSEN_I2C_ADDRESS, HTSEN_TOTAL_DATA_LENGTH_IN_BYTES, i2cReadBuffer);
252  if (i2cReadReturn != STD_OK) {
253  if (htsen_timeout_10ms > 0u) {
255  }
256  if (htsen_timeout_10ms == 0u) {
258  }
259  } else {
260  /* If measurement finished, retrieve values */
261  /* Only take temperature value if CRC valid */
262  if (i2cReadBuffer[HTSEN_TEMPERATURE_BYTE_CRC] ==
265  (((uint16_t)i2cReadBuffer[HTSEN_TEMPERATURE_MSB]) << HTSEN_BYTE_SHIFT) |
266  (uint16_t)i2cReadBuffer[HTSEN_TEMPERATURE_LSB]);
267  }
268  /* Only take humidity value if CRC valid */
269  if (i2cReadBuffer[HTSEN_HUMIDITY_BYTE_CRC] ==
272  (((uint16_t)i2cReadBuffer[HTSEN_HUMIDITY_MSB]) << HTSEN_BYTE_SHIFT) |
273  (uint16_t)i2cReadBuffer[HTSEN_HUMIDITY_LSB]);
274  }
277  }
278  break;
279 
280  default:
281  /* invalid state */
283  break;
284  }
285 }
286 
287 /*========== Getter for static Variables (Unit Test) ========================*/
288 
289 /*========== Externalized Static Function Implementations (Unit Test) =======*/
290 #ifdef UNITY_UNIT_TEST
291 extern uint8_t TEST_HTSEN_TestCalculateCrc8(uint8_t *data, uint32_t length) {
292  return HTSEN_CalculateCrc8(data, 2u);
293 }
294 #endif /* UNITY_UNIT_TEST */
Database module header.
#define DATA_WRITE_DATA(...)
Definition: database.h:93
@ DATA_BLOCK_ID_HTSEN
Definition: database_cfg.h:106
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:248
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:126
STD_RETURN_TYPE_e
Definition: fstd_types.h:81
@ STD_NOT_OK
Definition: fstd_types.h:83
@ STD_OK
Definition: fstd_types.h:82
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
#define HTSEN_BYTE_SHIFT
Definition: htsensor.c:90
#define HTSEN_TEMPERATURE_BYTE_CRC
Definition: htsensor.c:86
#define HTSEN_CRC_MSB_MASK
Definition: htsensor.c:99
#define HTSEN_SINGLE_MEAS_LSB
Definition: htsensor.c:145
static int16_t HTSEN_ConvertRawTemperature(uint16_t data)
computes temperature measurement from raw value.
Definition: htsensor.c:211
static uint8_t HTSEN_ConvertRawHumidity(uint16_t data)
computes humidity measurement from raw value.
Definition: htsensor.c:218
#define HTSEN_HUMIDITY_SCALING
Definition: htsensor.c:79
#define HTSEN_I2C_ADDRESS
Definition: htsensor.c:64
static uint8_t HTSEN_CalculateCrc8(const uint8_t *data, uint32_t length)
computes CRC8.
Definition: htsensor.c:192
#define HTSEN_CRC_SEED
Definition: htsensor.c:97
#define HTSEN_HUMIDITY_LSB
Definition: htsensor.c:87
static uint8_t htsen_counter
Definition: htsensor.c:157
#define HTSEN_READ_TIMEOUT_10ms
Definition: htsensor.c:67
#define HTSEN_TEMP_OFFSET
Definition: htsensor.c:74
#define HTSEN_TOTAL_DATA_LENGTH_IN_BYTES
Definition: htsensor.c:92
#define HTSEN_TEMP_SCALING
Definition: htsensor.c:73
#define HTSEN_TEMPERATURE_MSB
Definition: htsensor.c:85
#define HTSEN_SINGLE_MEAS_MSB
Definition: htsensor.c:134
#define HTSEN_TEMPERATURE_LSB
Definition: htsensor.c:84
#define HTSEN_HUMIDITY_BYTE_CRC
Definition: htsensor.c:89
#define HTSEN_FULL_SCALE
Definition: htsensor.c:80
#define HTSEN_TEMP_DEG_TO_DDEG
Definition: htsensor.c:75
#define HTSEN_HUMIDITY_MSB
Definition: htsensor.c:88
#define HTSEN_MEASUREMENT_LENGTH_IN_BYTES
Definition: htsensor.c:91
static HTSEN_STATE_e htsen_state
describes the current state of the measurement
Definition: htsensor.c:155
static DATA_BLOCK_HTSEN_s htsen_data
Definition: htsensor.c:162
uint8_t TEST_HTSEN_TestCalculateCrc8(uint8_t *data, uint32_t length)
Definition: htsensor.c:291
#define HTSEN_TIME_MEAS_WAIT_10ms
Definition: htsensor.c:70
#define HTSEN_CRC_BYTE_SHIFT
Definition: htsensor.c:98
static uint8_t htsen_timeout_10ms
Definition: htsensor.c:159
#define HTSEN_CRC_POLYNOMIAL
Definition: htsensor.c:96
#define HTSEN_CRC_8BIT_MASK
Definition: htsensor.c:100
void HTSEN_Trigger(void)
triggers a measurement of the I2C humidity/temperature sensor.
Definition: htsensor.c:225
Header for the driver for the Sensirion SHT35-DIS I2C humidity/temperature sensor.
HTSEN_STATE_e
Definition: htsensor.h:66
@ HTSEN_READ_RESULTS
Definition: htsensor.h:69
@ HTSEN_START_MEAS
Definition: htsensor.h:67
@ HTSEN_WAIT_FOR_RESULTS
Definition: htsensor.h:68
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:357
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:184
Header for the driver for the I2C module.
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:119
int16_t temperature_ddegC
Definition: database_cfg.h:576
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:575