42#define CHIP_NAME "Sensirion SEN5X"
43#define MANUFACTURER_NAME "Sensirion"
44#define SUPPLY_VOLTAGE_MIN 4.50f
45#define SUPPLY_VOLTAGE_MAX 5.50f
46#define MAX_CURRENT 100.0f
47#define TEMPERATURE_MIN -10.0f
48#define TEMPERATURE_MAX 60.0f
49#define DRIVER_VERSION 1000
54#define SEN5X_ADDRESS (0x69 << 1)
59#define SEN5X_IIC_COMMAND_START_MEASUREMENT 0x0021U
60#define SEN5X_IIC_COMMAND_START_MEASUREMENT_IN_RHT_GAS_ONLY 0x0037U
61#define SEN5X_IIC_COMMAND_STOP_MEASUREMENT 0x0104U
62#define SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG 0x0202U
63#define SEN5X_IIC_COMMAND_READ_MEASURED_VALUES 0x03C4U
64#define SEN5X_IIC_COMMAND_READ_WRITE_TEMPERATURE_COMPENSATION 0x60B2U
65#define SEN5X_IIC_COMMAND_READ_WRITE_WARM_START_PARAMS 0x60C6U
66#define SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_TUNING_PARAMS 0x60D0U
67#define SEN5X_IIC_COMMAND_READ_WRITE_NOX_ALG_TUNING_PARAMS 0x60E1U
68#define SEN5X_IIC_COMMAND_READ_WRITE_RHT_ACC_MODE 0x60F7U
69#define SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_STATE 0x6181U
70#define SEN5X_IIC_COMMAND_START_FAN_CLEANING 0x5607U
71#define SEN5X_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL 0x8004U
72#define SEN5X_IIC_COMMAND_READ_PRODUCT_NAME 0xD014U
73#define SEN5X_IIC_COMMAND_READ_SERIAL_NUMBER 0xD033U
74#define SEN5X_IIC_COMMAND_READ_VERSION 0xD100U
75#define SEN5X_IIC_COMMAND_READ_DEVICE_STATUS_REG 0xD206U
76#define SEN5X_IIC_COMMAND_CLEAR_DEVICE_STATUS_REG 0xD210U
77#define SEN5X_IIC_COMMAND_RESET 0xD304U
78#define SEN5X_IIC_COMMAND_READ_MEASURED_PM_VALUES 0x0413U
79#define SEN5X_IIC_COMMAND_READ_MEASURED_RAW_VALUES 0x03D2U
89static uint8_t a_sen5x_crc(
sen5x_handle_t *handle, uint8_t* data, uint8_t count)
95 for (current_byte = 0; current_byte < count; ++current_byte)
97 crc ^= (data[current_byte]);
98 for (crc_bit = 8; crc_bit > 0; --crc_bit)
100 if ((crc & 0x80) != 0)
102 crc = (crc << 1) ^ 0x31;
127static uint8_t a_sen5x_iic_read(
sen5x_handle_t *handle, uint8_t addr, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
131 buf[0] = (reg >> 8) & 0xFF;
132 buf[1] = (reg >> 0) & 0xFF;
138 if (handle->
iic_read_cmd(addr, (uint8_t *)data, len) != 0)
159static uint8_t a_sen5x_iic_write(
sen5x_handle_t *handle, uint8_t addr, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
167 buf[0] = (reg >> 8) & 0xFF;
168 buf[1] = (reg >> 0) & 0xFF;
169 memcpy((uint8_t *)&buf[2], data, len);
170 if (handle->
iic_write_cmd(addr, (uint8_t *)buf, len + 2) != 0)
205 handle->
debug_print(
"sen5x: start measurement failed.\n");
238 handle->
debug_print(
"sen5x: sen50 doesn't support this function.\n");
247 handle->
debug_print(
"sen5x: start measurement without pm failed.\n");
281 handle->
debug_print(
"sen5x: stop measurement failed.\n");
314 memset(buf, 0,
sizeof(uint8_t) * 3);
318 handle->
debug_print(
"sen5x: read data ready flag failed.\n");
322 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)buf, 2))
352 if ((handle == NULL) || (output == NULL))
362 handle->
debug_print(
"sen5x: only sen55 can use this function.\n");
367 memset(check, 0,
sizeof(uint8_t) * 3);
371 handle->
debug_print(
"sen5x: read data ready flag failed.\n");
375 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2))
381 if ((check[1] & 0x01) == 0)
388 memset(buf, 0,
sizeof(uint8_t) * 24);
392 handle->
debug_print(
"sen5x: read measured values failed.\n");
396 for (i = 0; i < 8; i++)
398 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
405 output->
pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
406 output->
pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
407 output->
pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
408 output->
pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
411 output->
voc_raw = (int16_t)(((uint16_t)(buf[18]) << 8) | ((uint16_t)(buf[19]) << 0));
412 output->
nox_raw = (int16_t)(((uint16_t)(buf[21]) << 8) | ((uint16_t)(buf[22]) << 0));
485 if ((handle == NULL) || (output == NULL))
495 handle->
debug_print(
"sen5x: only sen54 can use this function.\n");
500 memset(check, 0,
sizeof(uint8_t) * 3);
504 handle->
debug_print(
"sen5x: read data ready flag failed.\n");
508 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2))
514 if ((check[1] & 0x01) == 0)
521 memset(buf, 0,
sizeof(uint8_t) * 24);
525 handle->
debug_print(
"sen5x: read measured values failed.\n");
529 for (i = 0; i < 8; i++)
531 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
538 output->
pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
539 output->
pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
540 output->
pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
541 output->
pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
544 output->
voc_raw = (int16_t)(((uint16_t)(buf[18]) << 8) | ((uint16_t)(buf[19]) << 0));
609 if ((handle == NULL) || (output == NULL))
619 handle->
debug_print(
"sen5x: only sen50 can use this function.\n");
624 memset(check, 0,
sizeof(uint8_t) * 3);
628 handle->
debug_print(
"sen5x: read data ready flag failed.\n");
632 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2))
638 if ((check[1] & 0x01) == 0)
645 memset(buf, 0,
sizeof(uint8_t) * 24);
649 handle->
debug_print(
"sen5x: read measured values failed.\n");
653 for (i = 0; i < 8; i++)
655 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
662 output->
pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
663 output->
pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
664 output->
pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
665 output->
pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
704 if ((handle == NULL) || (pm == NULL))
713 memset(check, 0,
sizeof(uint8_t) * 3);
717 handle->
debug_print(
"sen5x: read data ready flag failed.\n");
721 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2))
727 if ((check[1] & 0x01) == 0)
734 memset(buf, 0,
sizeof(uint8_t) * 30);
738 handle->
debug_print(
"sen5x: read pm values failed.\n");
742 for (i = 0; i < 10; i++)
744 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
816 if ((handle == NULL) || (raw == NULL))
826 handle->
debug_print(
"sen5x: sen50 doesn't support this function.\n");
831 memset(check, 0,
sizeof(uint8_t) * 3);
835 handle->
debug_print(
"sen5x: read data ready flag failed.\n");
839 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2))
845 if ((check[1] & 0x01) == 0)
852 memset(buf, 0,
sizeof(uint8_t) * 12);
856 handle->
debug_print(
"sen5x: read raw values failed.\n");
860 for (i = 0; i < 4; i++)
862 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
869 raw->
humidity_raw = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
870 raw->
temperature_raw = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
871 raw->
voc_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
872 raw->
nox_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
923 int16_t normalized_temperature_offset_slope,
924 uint16_t time_constant)
938 buf[0] = ((uint16_t)temperature_offset >> 8) & 0xFF;
939 buf[1] = ((uint16_t)temperature_offset >> 0) & 0xFF;
940 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
941 buf[3] = ((uint16_t)normalized_temperature_offset_slope >> 8) & 0xFF;
942 buf[4] = ((uint16_t)normalized_temperature_offset_slope >> 0) & 0xFF;
943 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2);
944 buf[6] = ((uint16_t)time_constant >> 8) & 0xFF;
945 buf[7] = ((uint16_t)time_constant >> 0) & 0xFF;
946 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2);
948 (uint8_t *)buf, 9, 20);
951 handle->
debug_print(
"sen5x: set temperature compensation failed.\n");
973 int16_t *normalized_temperature_offset_slope,
974 uint16_t *time_constant)
989 (uint8_t *)buf, 9, 20);
992 handle->
debug_print(
"sen5x: get temperature compensation failed.\n");
996 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1002 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2))
1004 handle->
debug_print(
"sen5x: crc check failed.\n");
1008 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2))
1010 handle->
debug_print(
"sen5x: crc check failed.\n");
1014 *temperature_offset = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
1015 *normalized_temperature_offset_slope = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
1016 *time_constant = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
1037 float temperature_offset_degree,
1038 float normalized_temperature_offset_slope_factor,
1039 float time_constant_second,
1040 int16_t *temperature_offset_reg,
1041 int16_t *normalized_temperature_offset_slope_reg,
1042 uint16_t *time_constant_reg)
1053 *temperature_offset_reg = (int16_t)(temperature_offset_degree * 200.0f);
1054 *normalized_temperature_offset_slope_reg = (int16_t)(normalized_temperature_offset_slope_factor * 10000.0f);
1055 *time_constant_reg = (uint16_t)(time_constant_second);
1076 int16_t temperature_offset_reg,
1077 int16_t normalized_temperature_offset_slope_reg,
1078 uint16_t time_constant_reg,
1079 float *temperature_offset_degree,
1080 float *normalized_temperature_offset_slope_factor,
1081 float *time_constant_second)
1092 *temperature_offset_degree = (float)(temperature_offset_reg) / 200.0f;
1093 *normalized_temperature_offset_slope_factor = (float)(normalized_temperature_offset_slope_reg) / 10000.0f;
1094 *time_constant_second = (float)(time_constant_reg);
1124 buf[0] = ((uint16_t)param >> 8) & 0xFF;
1125 buf[1] = ((uint16_t)param >> 0) & 0xFF;
1126 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1128 (uint8_t *)buf, 3, 20);
1131 handle->
debug_print(
"sen5x: set warm start failed.\n");
1165 (uint8_t *)buf, 3, 20);
1168 handle->
debug_print(
"sen5x: get warm start failed.\n");
1172 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1174 handle->
debug_print(
"sen5x: crc check failed.\n");
1178 *param = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
1206 int16_t learning_time_offset_hour,
1207 int16_t learning_time_gain_hour,
1208 int16_t gating_max_duration_minute,
1209 int16_t std_initial,
1210 int16_t gain_factor)
1223 if ((index_offset > 250) || (index_offset < 1))
1225 handle->
debug_print(
"sen5x: index_offset > 250 or index_offset < 1.\n");
1229 if ((learning_time_offset_hour > 1000) || (learning_time_offset_hour < 1))
1231 handle->
debug_print(
"sen5x: learning time offset hour > 1000 or learning time offset hour < 1.\n");
1235 if ((learning_time_gain_hour > 1000) || (learning_time_gain_hour < 1))
1237 handle->
debug_print(
"sen5x: learning time gain hour > 1000 or learning time gain hour < 1.\n");
1241 if ((gating_max_duration_minute > 3000) || (gating_max_duration_minute < 0))
1243 handle->
debug_print(
"sen5x: gating max duration minute > 3000 or gating max duration minute < 0.\n");
1247 if ((std_initial > 5000) || (std_initial < 10))
1249 handle->
debug_print(
"sen5x: std initial > 5000 or std initial < 10.\n");
1253 if ((gain_factor > 1000) || (gain_factor < 1))
1255 handle->
debug_print(
"sen5x: gain factor > 1000 or gain factor < 1.\n");
1260 buf[0] = ((uint16_t)index_offset >> 8) & 0xFF;
1261 buf[1] = ((uint16_t)index_offset >> 0) & 0xFF;
1262 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1263 buf[3] = ((uint16_t)learning_time_offset_hour >> 8) & 0xFF;
1264 buf[4] = ((uint16_t)learning_time_offset_hour >> 0) & 0xFF;
1265 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2);
1266 buf[6] = ((uint16_t)learning_time_gain_hour >> 8) & 0xFF;
1267 buf[7] = ((uint16_t)learning_time_gain_hour >> 0) & 0xFF;
1268 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2);
1269 buf[9] = ((uint16_t)gating_max_duration_minute >> 8) & 0xFF;
1270 buf[10] = ((uint16_t)gating_max_duration_minute >> 0) & 0xFF;
1271 buf[11] = a_sen5x_crc(handle, (uint8_t *)&buf[9], 2);
1272 buf[12] = ((uint16_t)std_initial >> 8) & 0xFF;
1273 buf[13] = ((uint16_t)std_initial >> 0) & 0xFF;
1274 buf[14] = a_sen5x_crc(handle, (uint8_t *)&buf[12], 2);
1275 buf[15] = ((uint16_t)gain_factor >> 8) & 0xFF;
1276 buf[16] = ((uint16_t)gain_factor >> 0) & 0xFF;
1277 buf[17] = a_sen5x_crc(handle, (uint8_t *)&buf[15], 2);
1279 (uint8_t *)buf, 18, 20);
1282 handle->
debug_print(
"sen5x: set voc algorithm tuning failed.\n");
1307 int16_t *learning_time_offset_hour,
1308 int16_t *learning_time_gain_hour,
1309 int16_t *gating_max_duration_minute,
1310 int16_t *std_initial,
1311 int16_t *gain_factor)
1326 (uint8_t *)buf, 18, 20);
1329 handle->
debug_print(
"sen5x: get voc algorithm tuning failed.\n");
1333 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1335 handle->
debug_print(
"sen5x: crc check failed.\n");
1339 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2))
1341 handle->
debug_print(
"sen5x: crc check failed.\n");
1345 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2))
1347 handle->
debug_print(
"sen5x: crc check failed.\n");
1351 if (buf[11] != a_sen5x_crc(handle, (uint8_t *)&buf[9], 2))
1353 handle->
debug_print(
"sen5x: crc check failed.\n");
1357 if (buf[14] != a_sen5x_crc(handle, (uint8_t *)&buf[12], 2))
1359 handle->
debug_print(
"sen5x: crc check failed.\n");
1363 if (buf[17] != a_sen5x_crc(handle, (uint8_t *)&buf[15], 2))
1365 handle->
debug_print(
"sen5x: crc check failed.\n");
1369 *index_offset = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
1370 *learning_time_offset_hour = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
1371 *learning_time_gain_hour = (int16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
1372 *gating_max_duration_minute = (int16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
1373 *std_initial = (int16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0));
1374 *gain_factor = (int16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0));
1402 int16_t learning_time_offset_hour,
1403 int16_t learning_time_gain_hour,
1404 int16_t gating_max_duration_minute,
1405 int16_t std_initial,
1406 int16_t gain_factor)
1419 if ((index_offset > 250) || (index_offset < 1))
1421 handle->
debug_print(
"sen5x: index_offset > 250 or index_offset < 1.\n");
1425 if ((learning_time_offset_hour > 1000) || (learning_time_offset_hour < 1))
1427 handle->
debug_print(
"sen5x: learning time offset hour > 1000 or learning time offset hour < 1.\n");
1431 if (learning_time_gain_hour != 12)
1433 handle->
debug_print(
"sen5x: learning time gain hour must be 12.\n");
1437 if ((gating_max_duration_minute > 3000) || (gating_max_duration_minute < 0))
1439 handle->
debug_print(
"sen5x: gating max duration minute > 3000 or gating max duration minute < 0.\n");
1443 if (std_initial != 50)
1445 handle->
debug_print(
"sen5x: std initial must be 50.\n");
1449 if ((gain_factor > 1000) || (gain_factor < 1))
1451 handle->
debug_print(
"sen5x: gain factor > 1000 or gain factor < 1.\n");
1456 buf[0] = ((uint16_t)index_offset >> 8) & 0xFF;
1457 buf[1] = ((uint16_t)index_offset >> 0) & 0xFF;
1458 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1459 buf[3] = ((uint16_t)learning_time_offset_hour >> 8) & 0xFF;
1460 buf[4] = ((uint16_t)learning_time_offset_hour >> 0) & 0xFF;
1461 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2);
1462 buf[6] = ((uint16_t)learning_time_gain_hour >> 8) & 0xFF;
1463 buf[7] = ((uint16_t)learning_time_gain_hour >> 0) & 0xFF;
1464 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2);
1465 buf[9] = ((uint16_t)gating_max_duration_minute >> 8) & 0xFF;
1466 buf[10] = ((uint16_t)gating_max_duration_minute >> 0) & 0xFF;
1467 buf[11] = a_sen5x_crc(handle, (uint8_t *)&buf[9], 2);
1468 buf[12] = ((uint16_t)std_initial >> 8) & 0xFF;
1469 buf[13] = ((uint16_t)std_initial >> 0) & 0xFF;
1470 buf[14] = a_sen5x_crc(handle, (uint8_t *)&buf[12], 2);
1471 buf[15] = ((uint16_t)gain_factor >> 8) & 0xFF;
1472 buf[16] = ((uint16_t)gain_factor >> 0) & 0xFF;
1473 buf[17] = a_sen5x_crc(handle, (uint8_t *)&buf[15], 2);
1475 (uint8_t *)buf, 18, 20);
1478 handle->
debug_print(
"sen5x: set nox algorithm tuning failed.\n");
1503 int16_t *learning_time_offset_hour,
1504 int16_t *learning_time_gain_hour,
1505 int16_t *gating_max_duration_minute,
1506 int16_t *std_initial,
1507 int16_t *gain_factor)
1522 (uint8_t *)buf, 18, 20);
1525 handle->
debug_print(
"sen5x: get nox algorithm tuning failed.\n");
1529 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1531 handle->
debug_print(
"sen5x: crc check failed.\n");
1535 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2))
1537 handle->
debug_print(
"sen5x: crc check failed.\n");
1541 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2))
1543 handle->
debug_print(
"sen5x: crc check failed.\n");
1547 if (buf[11] != a_sen5x_crc(handle, (uint8_t *)&buf[9], 2))
1549 handle->
debug_print(
"sen5x: crc check failed.\n");
1553 if (buf[14] != a_sen5x_crc(handle, (uint8_t *)&buf[12], 2))
1555 handle->
debug_print(
"sen5x: crc check failed.\n");
1559 if (buf[17] != a_sen5x_crc(handle, (uint8_t *)&buf[15], 2))
1561 handle->
debug_print(
"sen5x: crc check failed.\n");
1565 *index_offset = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
1566 *learning_time_offset_hour = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
1567 *learning_time_gain_hour = (int16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
1568 *gating_max_duration_minute = (int16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
1569 *std_initial = (int16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0));
1570 *gain_factor = (int16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0));
1600 buf[0] = ((uint16_t)mode >> 8) & 0xFF;
1601 buf[1] = ((uint16_t)mode >> 0) & 0xFF;
1602 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1604 (uint8_t *)buf, 3, 20);
1607 handle->
debug_print(
"sen5x: set rht acceleration mode failed.\n");
1641 (uint8_t *)buf, 3, 20);
1644 handle->
debug_print(
"sen5x: get rht acceleration mode failed.\n");
1648 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1650 handle->
debug_print(
"sen5x: crc check failed.\n");
1684 buf[0] = ((uint16_t)state[0] >> 8) & 0xFF;
1685 buf[1] = ((uint16_t)state[0] >> 0) & 0xFF;
1686 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1687 buf[3] = ((uint16_t)state[1] >> 8) & 0xFF;
1688 buf[4] = ((uint16_t)state[1] >> 0) & 0xFF;
1689 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2);
1690 buf[6] = ((uint16_t)state[2] >> 8) & 0xFF;
1691 buf[7] = ((uint16_t)state[2] >> 0) & 0xFF;
1692 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2);
1693 buf[9] = ((uint16_t)state[3] >> 8) & 0xFF;
1694 buf[10] = ((uint16_t)state[3] >> 0) & 0xFF;
1695 buf[11] = a_sen5x_crc(handle, (uint8_t *)&buf[9], 2);
1697 (uint8_t *)buf, 12, 20);
1700 handle->
debug_print(
"sen5x: set voc algorithm state failed.\n");
1734 (uint8_t *)buf, 12, 20);
1737 handle->
debug_print(
"sen5x: get voc algorithm state failed.\n");
1741 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1743 handle->
debug_print(
"sen5x: crc check failed.\n");
1747 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2))
1749 handle->
debug_print(
"sen5x: crc check failed.\n");
1753 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2))
1755 handle->
debug_print(
"sen5x: crc check failed.\n");
1759 if (buf[11] != a_sen5x_crc(handle, (uint8_t *)&buf[9], 2))
1761 handle->
debug_print(
"sen5x: crc check failed.\n");
1765 state[0] = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0));
1766 state[1] = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0));
1767 state[2] = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0));
1768 state[3] = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0));
1799 handle->
debug_print(
"sen5x: start the fan cleaning failed.\n");
1832 if ((second < 10) || (second > 604800))
1834 handle->
debug_print(
"sen5x: second is invalid.\n");
1839 buf[0] = (second >> 24) & 0xFF;
1840 buf[1] = (second >> 16) & 0xFF;
1841 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1842 buf[3] = (second >> 8) & 0xFF;
1843 buf[4] = (second >> 0) & 0xFF;
1844 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2);
1846 (uint8_t *)buf, 6, 20);
1849 handle->
debug_print(
"sen5x: set auto cleaning interval failed.\n");
1882 memset(buf, 0,
sizeof(uint8_t) * 6);
1884 (uint8_t *)buf, 6, 20);
1887 handle->
debug_print(
"sen5x: get auto cleaning interval failed.\n");
1891 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
1897 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2))
1903 *second = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
1904 ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0);
1935 buf[0] = (second >> 24) & 0xFF;
1936 buf[1] = (second >> 16) & 0xFF;
1937 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2);
1938 buf[3] = (second >> 8) & 0xFF;
1939 buf[4] = (second >> 0) & 0xFF;
1940 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2);
1942 (uint8_t *)buf, 6, 20);
1945 handle->
debug_print(
"sen5x: set auto cleaning interval failed.\n");
1978 memset(buf, 0,
sizeof(uint8_t) * 48);
1982 handle->
debug_print(
"sen5x: read product name failed.\n");
1986 for (i = 0; i < 16; i++)
1988 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
1996 for (i = 0; i < 16; i++)
1998 name[j] = buf[i * 3 + 0];
2000 name[j] = buf[i * 3 + 1];
2032 memset(buf, 0,
sizeof(uint8_t) * 48);
2036 handle->
debug_print(
"sen5x: read serial number failed.\n");
2040 for (i = 0; i < 16; i++)
2042 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2))
2050 for (i = 0; i < 16; i++)
2052 sn[j] = buf[i * 3 + 0];
2054 sn[j] = buf[i * 3 + 1];
2086 memset(buf, 0,
sizeof(uint8_t) * 3);
2090 handle->
debug_print(
"sen5x: read version failed.\n");
2094 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
2130 memset(buf, 0,
sizeof(uint8_t) * 6);
2132 (uint8_t *)buf, 6, 20);
2135 handle->
debug_print(
"sen5x: get device status failed.\n");
2139 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2))
2145 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2))
2151 *status = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
2152 ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0);
2183 handle->
debug_print(
"sen5x: clear device status failed.\n");
2241 handle->
type = (uint8_t)type;
2292 handle->
debug_print(
"sen5x: iic_init is null.\n");
2298 handle->
debug_print(
"sen5x: iic_deinit is null.\n");
2304 handle->
debug_print(
"sen5x: iic_write_cmd is null.\n");
2310 handle->
debug_print(
"sen5x: iic_read_cmd is null.\n");
2316 handle->
debug_print(
"sen5x: delay_ms is null.\n");
2374 handle->
debug_print(
"sen5x: iic deinit failed.\n");
2407 return a_sen5x_iic_write(handle,
SEN5X_ADDRESS, reg, buf, len, 20);
2434 return a_sen5x_iic_read(handle,
SEN5X_ADDRESS, reg, buf, len, 20);
#define SEN5X_IIC_COMMAND_READ_PRODUCT_NAME
#define SEN5X_IIC_COMMAND_READ_WRITE_RHT_ACC_MODE
#define SEN5X_IIC_COMMAND_READ_DEVICE_STATUS_REG
#define SEN5X_IIC_COMMAND_READ_MEASURED_RAW_VALUES
#define SEN5X_IIC_COMMAND_READ_SERIAL_NUMBER
#define SEN5X_IIC_COMMAND_READ_VERSION
#define SEN5X_IIC_COMMAND_START_MEASUREMENT_IN_RHT_GAS_ONLY
#define SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_TUNING_PARAMS
#define SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG
#define SEN5X_IIC_COMMAND_RESET
#define SUPPLY_VOLTAGE_MAX
#define SEN5X_IIC_COMMAND_READ_MEASURED_PM_VALUES
#define SEN5X_IIC_COMMAND_READ_MEASURED_VALUES
#define SEN5X_ADDRESS
chip address definition
#define SEN5X_IIC_COMMAND_READ_WRITE_TEMPERATURE_COMPENSATION
#define SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_STATE
#define SEN5X_IIC_COMMAND_READ_WRITE_NOX_ALG_TUNING_PARAMS
#define MANUFACTURER_NAME
#define SEN5X_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL
#define SUPPLY_VOLTAGE_MIN
#define SEN5X_IIC_COMMAND_CLEAR_DEVICE_STATUS_REG
#define SEN5X_IIC_COMMAND_READ_WRITE_WARM_START_PARAMS
#define SEN5X_IIC_COMMAND_STOP_MEASUREMENT
#define CHIP_NAME
chip information definition
#define SEN5X_IIC_COMMAND_START_FAN_CLEANING
#define SEN5X_IIC_COMMAND_START_MEASUREMENT
chip command definition
uint8_t sen5x_set_nox_algorithm_tuning(sen5x_handle_t *handle, int16_t index_offset, int16_t learning_time_offset_hour, int16_t learning_time_gain_hour, int16_t gating_max_duration_minute, int16_t std_initial, int16_t gain_factor)
set nox algorithm tuning
uint8_t sen5x_temperature_compensation_convert_to_register(sen5x_handle_t *handle, float temperature_offset_degree, float normalized_temperature_offset_slope_factor, float time_constant_second, int16_t *temperature_offset_reg, int16_t *normalized_temperature_offset_slope_reg, uint16_t *time_constant_reg)
convert the temperature compensation to the register raw data
struct sen50_data_s sen50_data_t
sen50 data structure definition
uint8_t sen5x_info(sen5x_info_t *info)
get chip information
uint8_t sen5x_set_voc_algorithm_state(sen5x_handle_t *handle, uint16_t state[4])
set voc algorithm state
uint8_t sen5x_get_temperature_compensation(sen5x_handle_t *handle, int16_t *temperature_offset, int16_t *normalized_temperature_offset_slope, uint16_t *time_constant)
get temperature compensation
uint8_t sen5x_read_pm_value(sen5x_handle_t *handle, sen5x_pm_t *pm)
read the pm value
uint8_t sen5x_set_temperature_compensation(sen5x_handle_t *handle, int16_t temperature_offset, int16_t normalized_temperature_offset_slope, uint16_t time_constant)
set temperature compensation
uint8_t sen5x_get_warm_start(sen5x_handle_t *handle, uint16_t *param)
get warm start
uint8_t sen5x_read_raw_value(sen5x_handle_t *handle, sen5x_raw_t *raw)
read raw value
uint8_t sen55_read(sen5x_handle_t *handle, sen55_data_t *output)
read the result
uint8_t sen5x_set_type(sen5x_handle_t *handle, sen5x_type_t type)
set the chip type
uint8_t sen54_read(sen5x_handle_t *handle, sen54_data_t *output)
read the result
uint8_t sen5x_read_data_flag(sen5x_handle_t *handle, sen5x_data_ready_flag_t *flag)
read the data flag
uint8_t sen5x_start_measurement_without_pm(sen5x_handle_t *handle)
start the measurement without pm
uint8_t sen5x_get_device_status(sen5x_handle_t *handle, uint32_t *status)
get the device status
uint8_t sen5x_start_fan_cleaning(sen5x_handle_t *handle)
start the fan cleaning
uint8_t sen5x_get_version(sen5x_handle_t *handle, uint8_t *version)
get the version
uint8_t sen5x_start_measurement(sen5x_handle_t *handle)
start the measurement
uint8_t sen5x_get_nox_algorithm_tuning(sen5x_handle_t *handle, int16_t *index_offset, int16_t *learning_time_offset_hour, int16_t *learning_time_gain_hour, int16_t *gating_max_duration_minute, int16_t *std_initial, int16_t *gain_factor)
get nox algorithm tuning
uint8_t sen5x_get_type(sen5x_handle_t *handle, sen5x_type_t *type)
get the chip type
uint8_t sen50_read(sen5x_handle_t *handle, sen50_data_t *output)
read the result
sen5x_data_ready_flag_t
sen5x data ready flag enumeration definition
uint8_t sen5x_reset(sen5x_handle_t *handle)
reset the chip
uint8_t sen5x_get_rht_acceleration_mode(sen5x_handle_t *handle, sen5x_rht_acceleration_mode_t *mode)
get rht acceleration mode
sen5x_type_t
sen5x type enumeration definition
uint8_t sen5x_deinit(sen5x_handle_t *handle)
close the chip
uint8_t sen5x_get_serial_number(sen5x_handle_t *handle, char sn[32])
get the serial number
struct sen5x_handle_s sen5x_handle_t
sen5x handle structure definition
uint8_t sen5x_get_product_name(sen5x_handle_t *handle, char name[32])
get the product name
uint8_t sen5x_get_voc_algorithm_tuning(sen5x_handle_t *handle, int16_t *index_offset, int16_t *learning_time_offset_hour, int16_t *learning_time_gain_hour, int16_t *gating_max_duration_minute, int16_t *std_initial, int16_t *gain_factor)
get voc algorithm tuning
uint8_t sen5x_clear_device_status(sen5x_handle_t *handle)
clear the device status
uint8_t sen5x_set_voc_algorithm_tuning(sen5x_handle_t *handle, int16_t index_offset, int16_t learning_time_offset_hour, int16_t learning_time_gain_hour, int16_t gating_max_duration_minute, int16_t std_initial, int16_t gain_factor)
set voc algorithm tuning
uint8_t sen5x_get_auto_cleaning_interval(sen5x_handle_t *handle, uint32_t *second)
get the auto cleaning interval
struct sen55_data_s sen55_data_t
sen55 data structure definition
struct sen5x_raw_s sen5x_raw_t
sen5x raw structure definition
struct sen54_data_s sen54_data_t
sen54 data structure definition
struct sen5x_pm_s sen5x_pm_t
sen5x pm structure definition
uint8_t sen5x_temperature_compensation_convert_to_data(sen5x_handle_t *handle, int16_t temperature_offset_reg, int16_t normalized_temperature_offset_slope_reg, uint16_t time_constant_reg, float *temperature_offset_degree, float *normalized_temperature_offset_slope_factor, float *time_constant_second)
convert the temperature compensation to the real data
uint8_t sen5x_disable_auto_cleaning_interval(sen5x_handle_t *handle)
disable the auto cleaning interval
uint8_t sen5x_set_rht_acceleration_mode(sen5x_handle_t *handle, sen5x_rht_acceleration_mode_t mode)
set rht acceleration mode
struct sen5x_info_s sen5x_info_t
sen5x information structure definition
uint8_t sen5x_init(sen5x_handle_t *handle)
initialize the chip
uint8_t sen5x_set_warm_start(sen5x_handle_t *handle, uint16_t param)
set warm start
uint8_t sen5x_set_auto_cleaning_interval(sen5x_handle_t *handle, uint32_t second)
set the auto cleaning interval
uint8_t sen5x_stop_measurement(sen5x_handle_t *handle)
stop the measurement
sen5x_rht_acceleration_mode_t
sen5x rht acceleration mode enumeration definition
uint8_t sen5x_get_voc_algorithm_state(sen5x_handle_t *handle, uint16_t state[4])
get voc algorithm state
uint8_t sen5x_set_reg(sen5x_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
set the chip register
uint8_t sen5x_get_reg(sen5x_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
get the chip register
float compensated_ambient_temperature_degree
int16_t compensated_ambient_temperature_raw
int16_t compensated_ambient_humidity_raw
float compensated_ambient_humidity_percentage
float compensated_ambient_temperature_degree
int16_t compensated_ambient_temperature_raw
int16_t compensated_ambient_humidity_raw
float compensated_ambient_humidity_percentage
void(* delay_ms)(uint32_t ms)
void(* debug_print)(const char *const fmt,...)
uint8_t(* iic_init)(void)
uint8_t(* iic_read_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
uint8_t(* iic_deinit)(void)
uint8_t(* iic_write_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
float supply_voltage_max_v
char manufacturer_name[32]
float supply_voltage_min_v
uint16_t mass_concentration_pm4p0_raw
uint16_t number_concentration_pm10_raw
float typical_particle_um
uint16_t number_concentration_pm0p5_raw
uint16_t number_concentration_pm1p0_raw
uint16_t mass_concentration_pm2p5_raw
uint16_t mass_concentration_pm1p0_raw
uint16_t number_concentration_pm4p0_raw
uint16_t number_concentration_pm2p5_raw
uint16_t mass_concentration_pm10_raw
uint16_t typical_particle_raw
float humidity_percentage