LibDriver SEN5X
Loading...
Searching...
No Matches
driver_sen5x.c
Go to the documentation of this file.
1
36
37#include "driver_sen5x.h"
38
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
50
54#define SEN5X_ADDRESS (0x69 << 1)
55
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
80
89static uint8_t a_sen5x_crc(sen5x_handle_t *handle, uint8_t* data, uint8_t count)
90{
91 uint8_t current_byte;
92 uint8_t crc = 0xFF;
93 uint8_t crc_bit;
94
95 for (current_byte = 0; current_byte < count; ++current_byte) /* calculate crc */
96 {
97 crc ^= (data[current_byte]); /* xor data */
98 for (crc_bit = 8; crc_bit > 0; --crc_bit) /* 8 bit */
99 {
100 if ((crc & 0x80) != 0) /* if 7th bit is 1 */
101 {
102 crc = (crc << 1) ^ 0x31; /* xor */
103 }
104 else
105 {
106 crc = crc << 1; /* left shift 1 */
107 }
108 }
109 }
110
111 return crc; /* return crc */
112}
113
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)
128{
129 uint8_t buf[2];
130
131 buf[0] = (reg >> 8) & 0xFF; /* set msb */
132 buf[1] = (reg >> 0) & 0xFF; /* set lsb */
133 if (handle->iic_write_cmd(addr, (uint8_t *)buf, 2) != 0) /* write data */
134 {
135 return 1; /* return error */
136 }
137 handle->delay_ms(delay_ms); /* delay ms */
138 if (handle->iic_read_cmd(addr, (uint8_t *)data, len) != 0) /* read data */
139 {
140 return 1; /* return error */
141 }
142
143 return 0; /* success return 0 */
144}
145
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)
160{
161 uint8_t buf[32];
162
163 if (len > 30) /* check length */
164 {
165 return 1; /* return error */
166 }
167 buf[0] = (reg >> 8) & 0xFF; /* set msb */
168 buf[1] = (reg >> 0) & 0xFF; /* set lsb */
169 memcpy((uint8_t *)&buf[2], data, len); /* copy data */
170 if (handle->iic_write_cmd(addr, (uint8_t *)buf, len + 2) != 0) /* write data */
171 {
172 return 1; /* return error */
173 }
174 handle->delay_ms(delay_ms); /* delay ms */
175
176 return 0; /* success return 0 */
177}
178
190{
191 uint8_t res;
192
193 if (handle == NULL) /* check handle */
194 {
195 return 2; /* return error */
196 }
197 if (handle->inited != 1) /* check handle initialization */
198 {
199 return 3; /* return error */
200 }
201
202 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_START_MEASUREMENT, NULL, 0, 50); /* start measurement command */
203 if (res != 0) /* check result */
204 {
205 handle->debug_print("sen5x: start measurement failed.\n"); /* start measurement failed */
206
207 return 1; /* return error */
208 }
209
210 return 0; /* success return 0 */
211}
212
225{
226 uint8_t res;
227
228 if (handle == NULL) /* check handle */
229 {
230 return 2; /* return error */
231 }
232 if (handle->inited != 1) /* check handle initialization */
233 {
234 return 3; /* return error */
235 }
236 if (handle->type == (uint8_t)(SEN50)) /* check result */
237 {
238 handle->debug_print("sen5x: sen50 doesn't support this function.\n"); /* sen50 doesn't support this function */
239
240 return 4; /* return error */
241 }
242
243 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS,
244 SEN5X_IIC_COMMAND_START_MEASUREMENT_IN_RHT_GAS_ONLY, NULL, 0, 50); /* start measurement command */
245 if (res != 0) /* check result */
246 {
247 handle->debug_print("sen5x: start measurement without pm failed.\n"); /* start measurement failed */
248
249 return 1; /* return error */
250 }
251
252 return 0; /* success return 0 */
253}
254
266{
267 uint8_t res;
268
269 if (handle == NULL) /* check handle */
270 {
271 return 2; /* return error */
272 }
273 if (handle->inited != 1) /* check handle initialization */
274 {
275 return 3; /* return error */
276 }
277
278 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_STOP_MEASUREMENT, NULL, 0, 200); /* stop measurement command */
279 if (res != 0) /* check result */
280 {
281 handle->debug_print("sen5x: stop measurement failed.\n"); /* stop measurement failed */
282
283 return 1; /* return error */
284 }
285
286 return 0; /* success return 0 */
287}
288
301{
302 uint8_t res;
303 uint8_t buf[3];
304
305 if (handle == NULL) /* check handle */
306 {
307 return 2; /* return error */
308 }
309 if (handle->inited != 1) /* check handle initialization */
310 {
311 return 3; /* return error */
312 }
313
314 memset(buf, 0, sizeof(uint8_t) * 3); /* clear the buffer */
315 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)buf, 3, 20); /* read data ready flag command */
316 if (res != 0) /* check result */
317 {
318 handle->debug_print("sen5x: read data ready flag failed.\n"); /* read data ready flag failed */
319
320 return 1; /* return error */
321 }
322 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)buf, 2)) /* check crc */
323 {
324 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
325
326 return 1; /* return error */
327 }
328 *flag = (sen5x_data_ready_flag_t)(buf[1] & 0x01); /* get the data ready flag */
329
330 return 0; /* success return 0 */
331}
332
345uint8_t sen55_read(sen5x_handle_t *handle, sen55_data_t *output)
346{
347 uint8_t res;
348 uint8_t i;
349 uint8_t check[3];
350 uint8_t buf[24];
351
352 if ((handle == NULL) || (output == NULL)) /* check handle */
353 {
354 return 2; /* return error */
355 }
356 if (handle->inited != 1) /* check handle initialization */
357 {
358 return 3; /* return error */
359 }
360 if (handle->type != (uint8_t)(SEN55)) /* check type */
361 {
362 handle->debug_print("sen5x: only sen55 can use this function.\n"); /* only sen55 can use this function */
363
364 return 4; /* return error */
365 }
366
367 memset(check, 0, sizeof(uint8_t) * 3); /* clear the buffer */
368 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)check, 3, 20); /* read data ready flag command */
369 if (res != 0) /* check result */
370 {
371 handle->debug_print("sen5x: read data ready flag failed.\n"); /* read data ready flag failed */
372
373 return 1; /* return error */
374 }
375 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2)) /* check crc */
376 {
377 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
378
379 return 1; /* return error */
380 }
381 if ((check[1] & 0x01) == 0) /* check flag */
382 {
383 handle->debug_print("sen5x: data not ready.\n"); /* data not ready */
384
385 return 1; /* return error */
386 }
387
388 memset(buf, 0, sizeof(uint8_t) * 24); /* clear the buffer */
389 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_MEASURED_VALUES, (uint8_t *)buf, 24, 20); /* read measured values command */
390 if (res != 0) /* check result */
391 {
392 handle->debug_print("sen5x: read measured values failed.\n"); /* read measured values failed */
393
394 return 1; /* return error */
395 }
396 for (i = 0; i < 8; i++) /* check crc */
397 {
398 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
399 {
400 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
401
402 return 1; /* return error */
403 }
404 }
405 output->pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* copy pm1.0 */
406 output->pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* copy pm2.5 */
407 output->pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* copy pm4.0 */
408 output->pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* copy pm10 */
409 output->compensated_ambient_humidity_raw = (int16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0)); /* humidity raw */
410 output->compensated_ambient_temperature_raw = (int16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0)); /* temperature raw */
411 output->voc_raw = (int16_t)(((uint16_t)(buf[18]) << 8) | ((uint16_t)(buf[19]) << 0)); /* voc raw */
412 output->nox_raw = (int16_t)(((uint16_t)(buf[21]) << 8) | ((uint16_t)(buf[22]) << 0)); /* nox raw */
413 if ((output->pm1p0_raw == 0xFFFFU) || (output->pm2p5_raw == 0xFFFFU) ||
414 (output->pm4p0_raw == 0xFFFFU) || (output->pm10_raw == 0xFFFFU)) /* check invalid */
415 {
416 output->pm1p0_ug_m3 = FP_NAN; /* set nan */
417 output->pm2p5_ug_m3 = FP_NAN; /* set nan */
418 output->pm4p0_ug_m3 = FP_NAN; /* set nan */
419 output->pm10_ug_m3 = FP_NAN; /* set nan */
420 output->pm_valid = 0; /* set invalid */
421 }
422 else
423 {
424 output->pm1p0_ug_m3 = (float)(output->pm1p0_raw) / 10.0f; /* convert pm1.0 */
425 output->pm2p5_ug_m3 = (float)(output->pm2p5_raw) / 10.0f; /* convert pm2.5 */
426 output->pm4p0_ug_m3 = (float)(output->pm4p0_raw) / 10.0f; /* convert pm4.0 */
427 output->pm10_ug_m3 = (float)(output->pm10_raw) / 10.0f; /* convert pm10 */
428 output->pm_valid = 1; /* set valid */
429 }
430 if (output->compensated_ambient_humidity_raw == 0x7FFF) /* check humidity raw */
431 {
432 output->compensated_ambient_humidity_percentage = FP_NAN; /* set nan */
433 }
434 else /* convert */
435 {
436 output->compensated_ambient_humidity_percentage = (float)(output->compensated_ambient_humidity_raw) / 100.0f; /* convert humidity */
437 }
438 if (output->compensated_ambient_temperature_raw == 0x7FFF) /* check temperature raw */
439 {
440 output->compensated_ambient_temperature_degree = FP_NAN; /* set nan */
441 }
442 else
443 {
444 output->compensated_ambient_temperature_degree = (float)(output->compensated_ambient_temperature_raw) / 200.0f; /* convert temperature */
445 }
446 if (output->voc_raw == 0x7FFF) /* check voc raw */
447 {
448 output->voc_index = FP_NAN; /* set nan */
449 }
450 else
451 {
452 output->voc_index = (float)(output->voc_raw) / 10.0f; /* convert voc */
453 }
454 if (output->nox_raw == 0x7FFF) /* check nox raw */
455 {
456 output->nox_index = FP_NAN; /* set nan */
457 }
458 else
459 {
460 output->nox_index = (float)(output->nox_raw) / 10.0f; /* convert nox */
461 }
462
463 return 0; /* success return 0 */
464}
465
478uint8_t sen54_read(sen5x_handle_t *handle, sen54_data_t *output)
479{
480 uint8_t res;
481 uint8_t i;
482 uint8_t check[3];
483 uint8_t buf[24];
484
485 if ((handle == NULL) || (output == NULL)) /* check handle */
486 {
487 return 2; /* return error */
488 }
489 if (handle->inited != 1) /* check handle initialization */
490 {
491 return 3; /* return error */
492 }
493 if (handle->type != (uint8_t)(SEN54)) /* check type */
494 {
495 handle->debug_print("sen5x: only sen54 can use this function.\n"); /* only sen54 can use this function */
496
497 return 4; /* return error */
498 }
499
500 memset(check, 0, sizeof(uint8_t) * 3); /* clear the buffer */
501 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)check, 3, 20); /* read data ready flag command */
502 if (res != 0) /* check result */
503 {
504 handle->debug_print("sen5x: read data ready flag failed.\n"); /* read data ready flag failed */
505
506 return 1; /* return error */
507 }
508 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2)) /* check crc */
509 {
510 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
511
512 return 1; /* return error */
513 }
514 if ((check[1] & 0x01) == 0) /* check flag */
515 {
516 handle->debug_print("sen5x: data not ready.\n"); /* data not ready */
517
518 return 1; /* return error */
519 }
520
521 memset(buf, 0, sizeof(uint8_t) * 24); /* clear the buffer */
522 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_MEASURED_VALUES, (uint8_t *)buf, 24, 20); /* read measured values command */
523 if (res != 0) /* check result */
524 {
525 handle->debug_print("sen5x: read measured values failed.\n"); /* read measured values failed */
526
527 return 1; /* return error */
528 }
529 for (i = 0; i < 8; i++) /* check crc */
530 {
531 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
532 {
533 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
534
535 return 1; /* return error */
536 }
537 }
538 output->pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* copy pm1.0 */
539 output->pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* copy pm2.5 */
540 output->pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* copy pm4.0 */
541 output->pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* copy pm10 */
542 output->compensated_ambient_humidity_raw = (int16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0)); /* humidity raw */
543 output->compensated_ambient_temperature_raw = (int16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0)); /* temperature raw */
544 output->voc_raw = (int16_t)(((uint16_t)(buf[18]) << 8) | ((uint16_t)(buf[19]) << 0)); /* voc raw */
545 if ((output->pm1p0_raw == 0xFFFFU) || (output->pm2p5_raw == 0xFFFFU) ||
546 (output->pm4p0_raw == 0xFFFFU) || (output->pm10_raw == 0xFFFFU)) /* check invalid */
547 {
548 output->pm1p0_ug_m3 = FP_NAN; /* set nan */
549 output->pm2p5_ug_m3 = FP_NAN; /* set nan */
550 output->pm4p0_ug_m3 = FP_NAN; /* set nan */
551 output->pm10_ug_m3 = FP_NAN; /* set nan */
552 output->pm_valid = 0; /* set invalid */
553 }
554 else
555 {
556 output->pm1p0_ug_m3 = (float)(output->pm1p0_raw) / 10.0f; /* convert pm1.0 */
557 output->pm2p5_ug_m3 = (float)(output->pm2p5_raw) / 10.0f; /* convert pm2.5 */
558 output->pm4p0_ug_m3 = (float)(output->pm4p0_raw) / 10.0f; /* convert pm4.0 */
559 output->pm10_ug_m3 = (float)(output->pm10_raw) / 10.0f; /* convert pm10 */
560 output->pm_valid = 1; /* set valid */
561 }
562 if (output->compensated_ambient_humidity_raw == 0x7FFF) /* check humidity raw */
563 {
564 output->compensated_ambient_humidity_percentage = FP_NAN; /* set nan */
565 }
566 else /* convert */
567 {
568 output->compensated_ambient_humidity_percentage = (float)(output->compensated_ambient_humidity_raw) / 100.0f; /* convert humidity */
569 }
570 if (output->compensated_ambient_temperature_raw == 0x7FFF) /* check temperature raw */
571 {
572 output->compensated_ambient_temperature_degree = FP_NAN; /* set nan */
573 }
574 else
575 {
576 output->compensated_ambient_temperature_degree = (float)(output->compensated_ambient_temperature_raw) / 200.0f; /* convert temperature */
577 }
578 if (output->voc_raw == 0x7FFF) /* check voc raw */
579 {
580 output->voc_index = FP_NAN; /* set nan */
581 }
582 else
583 {
584 output->voc_index = (float)(output->voc_raw) / 10.0f; /* convert voc */
585 }
586
587 return 0; /* success return 0 */
588}
589
602uint8_t sen50_read(sen5x_handle_t *handle, sen50_data_t *output)
603{
604 uint8_t res;
605 uint8_t i;
606 uint8_t check[3];
607 uint8_t buf[24];
608
609 if ((handle == NULL) || (output == NULL)) /* check handle */
610 {
611 return 2; /* return error */
612 }
613 if (handle->inited != 1) /* check handle initialization */
614 {
615 return 3; /* return error */
616 }
617 if (handle->type != (uint8_t)(SEN50)) /* check type */
618 {
619 handle->debug_print("sen5x: only sen50 can use this function.\n"); /* only sen50 can use this function */
620
621 return 4; /* return error */
622 }
623
624 memset(check, 0, sizeof(uint8_t) * 3); /* clear the buffer */
625 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)check, 3, 20); /* read data ready flag command */
626 if (res != 0) /* check result */
627 {
628 handle->debug_print("sen5x: read data ready flag failed.\n"); /* read data ready flag failed */
629
630 return 1; /* return error */
631 }
632 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2)) /* check crc */
633 {
634 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
635
636 return 1; /* return error */
637 }
638 if ((check[1] & 0x01) == 0) /* check flag */
639 {
640 handle->debug_print("sen5x: data not ready.\n"); /* data not ready */
641
642 return 1; /* return error */
643 }
644
645 memset(buf, 0, sizeof(uint8_t) * 24); /* clear the buffer */
646 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_MEASURED_VALUES, (uint8_t *)buf, 24, 20); /* read measured values command */
647 if (res != 0) /* check result */
648 {
649 handle->debug_print("sen5x: read measured values failed.\n"); /* read measured values failed */
650
651 return 1; /* return error */
652 }
653 for (i = 0; i < 8; i++) /* check crc */
654 {
655 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
656 {
657 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
658
659 return 1; /* return error */
660 }
661 }
662 output->pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* copy pm1.0 */
663 output->pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* copy pm2.5 */
664 output->pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* copy pm4.0 */
665 output->pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* copy pm10 */
666 if ((output->pm1p0_raw == 0xFFFFU) || (output->pm2p5_raw == 0xFFFFU) ||
667 (output->pm4p0_raw == 0xFFFFU) || (output->pm10_raw == 0xFFFFU)) /* check invalid */
668 {
669 output->pm1p0_ug_m3 = FP_NAN; /* set nan */
670 output->pm2p5_ug_m3 = FP_NAN; /* set nan */
671 output->pm4p0_ug_m3 = FP_NAN; /* set nan */
672 output->pm10_ug_m3 = FP_NAN; /* set nan */
673 output->pm_valid = 0; /* set invalid */
674 }
675 else
676 {
677 output->pm1p0_ug_m3 = (float)(output->pm1p0_raw) / 10.0f; /* convert pm1.0 */
678 output->pm2p5_ug_m3 = (float)(output->pm2p5_raw) / 10.0f; /* convert pm2.5 */
679 output->pm4p0_ug_m3 = (float)(output->pm4p0_raw) / 10.0f; /* convert pm4.0 */
680 output->pm10_ug_m3 = (float)(output->pm10_raw) / 10.0f; /* convert pm10 */
681 output->pm_valid = 1; /* set valid */
682 }
683
684 return 0; /* success return 0 */
685}
686
699{
700 uint8_t res, i;
701 uint8_t check[3];
702 uint8_t buf[30];
703
704 if ((handle == NULL) || (pm == NULL)) /* check handle */
705 {
706 return 2; /* return error */
707 }
708 if (handle->inited != 1) /* check handle initialization */
709 {
710 return 3; /* return error */
711 }
712
713 memset(check, 0, sizeof(uint8_t) * 3); /* clear the buffer */
714 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)check, 3, 20); /* read data ready flag command */
715 if (res != 0) /* check result */
716 {
717 handle->debug_print("sen5x: read data ready flag failed.\n"); /* read data ready flag failed */
718
719 return 1; /* return error */
720 }
721 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2)) /* check crc */
722 {
723 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
724
725 return 1; /* return error */
726 }
727 if ((check[1] & 0x01) == 0) /* check flag */
728 {
729 handle->debug_print("sen5x: data not ready.\n"); /* data not ready */
730
731 return 1; /* return error */
732 }
733
734 memset(buf, 0, sizeof(uint8_t) * 30); /* clear the buffer */
735 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_MEASURED_PM_VALUES, (uint8_t *)buf, 30, 20); /* read measured values command */
736 if (res != 0) /* check result */
737 {
738 handle->debug_print("sen5x: read pm values failed.\n"); /* read pm values failed */
739
740 return 1; /* return error */
741 }
742 for (i = 0; i < 10; i++) /* check crc */
743 {
744 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
745 {
746 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
747
748 return 1; /* return error */
749 }
750 }
751 pm->mass_concentration_pm1p0_raw = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* copy pm1.0 raw */
752 pm->mass_concentration_pm2p5_raw = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* copy pm2.5 raw */
753 pm->mass_concentration_pm4p0_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* copy pm4.0 raw */
754 pm->mass_concentration_pm10_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* copy pm10 raw */
755 pm->number_concentration_pm0p5_raw = (uint16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0)); /* copy pm0.5 raw */
756 pm->number_concentration_pm1p0_raw = (uint16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0)); /* copy pm1.0 raw */
757 pm->number_concentration_pm2p5_raw = (uint16_t)(((uint16_t)(buf[18]) << 8) | ((uint16_t)(buf[19]) << 0)); /* copy pm2.5 raw */
758 pm->number_concentration_pm4p0_raw = (uint16_t)(((uint16_t)(buf[21]) << 8) | ((uint16_t)(buf[22]) << 0)); /* copy pm4.0 raw */
759 pm->number_concentration_pm10_raw = (uint16_t)(((uint16_t)(buf[24]) << 8) | ((uint16_t)(buf[25]) << 0)); /* copy pm10 raw */
760 pm->typical_particle_raw = (uint16_t)(((uint16_t)(buf[27]) << 8) | ((uint16_t)(buf[28]) << 0)); /* copy typical particle raw */
761 if ((pm->mass_concentration_pm1p0_raw == 0xFFFFU) || (pm->mass_concentration_pm2p5_raw == 0xFFFFU) ||
762 (pm->mass_concentration_pm4p0_raw == 0xFFFFU) || (pm->mass_concentration_pm10_raw == 0xFFFFU) ||
763 (pm->number_concentration_pm0p5_raw == 0xFFFFU) || (pm->number_concentration_pm1p0_raw == 0xFFFFU) ||
764 (pm->number_concentration_pm2p5_raw == 0xFFFFU) || (pm->number_concentration_pm4p0_raw == 0xFFFFU) ||
765 (pm->number_concentration_pm10_raw == 0xFFFFU) || (pm->typical_particle_raw == 0xFFFFU)
766 )
767 {
768 pm->pm1p0_ug_m3 = FP_NAN; /* set nan */
769 pm->pm2p5_ug_m3 = FP_NAN; /* set nan */
770 pm->pm4p0_ug_m3 = FP_NAN; /* set nan */
771 pm->pm10_ug_m3 = FP_NAN; /* set nan */
772 pm->pm0p5_cm3 = FP_NAN; /* set nan */
773 pm->pm1p0_cm3 = FP_NAN; /* set nan */
774 pm->pm2p5_cm3 = FP_NAN; /* set nan */
775 pm->pm4p0_cm3 = FP_NAN; /* set nan */
776 pm->pm10_cm3 = FP_NAN; /* set nan */
777 pm->typical_particle_um = FP_NAN; /* set nan */
778 pm->pm_valid = 0; /* set invalid */
779 }
780 else
781 {
782 pm->pm1p0_ug_m3 = (float)(pm->mass_concentration_pm1p0_raw) / 10.0f; /* convert data */
783 pm->pm2p5_ug_m3 = (float)(pm->mass_concentration_pm2p5_raw) / 10.0f; /* convert data */
784 pm->pm4p0_ug_m3 = (float)(pm->mass_concentration_pm4p0_raw) / 10.0f; /* convert data */
785 pm->pm10_ug_m3 = (float)(pm->mass_concentration_pm10_raw) / 10.0f; /* convert data */
786 pm->pm0p5_cm3 = (float)(pm->number_concentration_pm0p5_raw) / 10.0f; /* convert data */
787 pm->pm1p0_cm3 = (float)(pm->number_concentration_pm1p0_raw) / 10.0f; /* convert data */
788 pm->pm2p5_cm3 = (float)(pm->number_concentration_pm2p5_raw) / 10.0f; /* convert data */
789 pm->pm4p0_cm3 = (float)(pm->number_concentration_pm4p0_raw) / 10.0f; /* convert data */
790 pm->pm10_cm3 = (float)(pm->number_concentration_pm10_raw) / 10.0f; /* convert data */
791 pm->typical_particle_um = (float)(pm->typical_particle_raw) / 1000.0f; /* convert data */
792 pm->pm_valid = 1; /* set valid */
793 }
794
795 return 0; /* success return 0 */
796}
797
811{
812 uint8_t res, i;
813 uint8_t check[3];
814 uint8_t buf[12];
815
816 if ((handle == NULL) || (raw == NULL)) /* check handle */
817 {
818 return 2; /* return error */
819 }
820 if (handle->inited != 1) /* check handle initialization */
821 {
822 return 3; /* return error */
823 }
824 if (handle->type == (uint8_t)(SEN50)) /* check result */
825 {
826 handle->debug_print("sen5x: sen50 doesn't support this function.\n"); /* sen50 doesn't support this function */
827
828 return 4; /* return error */
829 }
830
831 memset(check, 0, sizeof(uint8_t) * 3); /* clear the buffer */
832 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)check, 3, 20); /* read data ready flag command */
833 if (res != 0) /* check result */
834 {
835 handle->debug_print("sen5x: read data ready flag failed.\n"); /* read data ready flag failed */
836
837 return 1; /* return error */
838 }
839 if (check[2] != a_sen5x_crc(handle, (uint8_t *)check, 2)) /* check crc */
840 {
841 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
842
843 return 1; /* return error */
844 }
845 if ((check[1] & 0x01) == 0) /* check flag */
846 {
847 handle->debug_print("sen5x: data not ready.\n"); /* data not ready */
848
849 return 1; /* return error */
850 }
851
852 memset(buf, 0, sizeof(uint8_t) * 12); /* clear the buffer */
853 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_MEASURED_RAW_VALUES, (uint8_t *)buf, 12, 20); /* read raw values command */
854 if (res != 0) /* check result */
855 {
856 handle->debug_print("sen5x: read raw values failed.\n"); /* read raw values failed */
857
858 return 1; /* return error */
859 }
860 for (i = 0; i < 4; i++) /* check crc */
861 {
862 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
863 {
864 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
865
866 return 1; /* return error */
867 }
868 }
869 raw->humidity_raw = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set humidity raw */
870 raw->temperature_raw = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* set temperature raw */
871 raw->voc_raw = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* set voc raw */
872 raw->nox_raw = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* set nox raw */
873 if (raw->humidity_raw != 0x7FFF) /* check valid */
874 {
875 raw->humidity_percentage = (float)(raw->humidity_raw) / 100.0f; /* set humidity percentage */
876 }
877 else
878 {
879 raw->humidity_percentage = FP_NAN; /* set nan */
880 }
881 if (raw->temperature_raw != 0x7FFF) /* check valid */
882 {
883 raw->temperature_degree = (float)(raw->temperature_raw) / 200.0f; /* set temperature raw */
884 }
885 else
886 {
887 raw->temperature_degree = FP_NAN; /* set nan */
888 }
889 if (raw->voc_raw != 0xFFFFU) /* check valid */
890 {
891 raw->voc = (float)(raw->voc_raw); /* set voc */
892 }
893 else
894 {
895 raw->voc = FP_NAN; /* set nan */
896 }
897 if (raw->nox_raw != 0xFFFFU) /* check valid */
898 {
899 raw->nox = (float)(raw->nox_raw); /* set nox */
900 }
901 else
902 {
903 raw->nox = FP_NAN; /* set nan */
904 }
905
906 return 0; /* success return 0 */
907}
908
922uint8_t sen5x_set_temperature_compensation(sen5x_handle_t *handle, int16_t temperature_offset,
923 int16_t normalized_temperature_offset_slope,
924 uint16_t time_constant)
925{
926 uint8_t res;
927 uint8_t buf[9];
928
929 if (handle == NULL) /* check handle */
930 {
931 return 2; /* return error */
932 }
933 if (handle->inited != 1) /* check handle initialization */
934 {
935 return 3; /* return error */
936 }
937
938 buf[0] = ((uint16_t)temperature_offset >> 8) & 0xFF; /* set temperature offset msb */
939 buf[1] = ((uint16_t)temperature_offset >> 0) & 0xFF; /* set temperature offset lsb */
940 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
941 buf[3] = ((uint16_t)normalized_temperature_offset_slope >> 8) & 0xFF; /* set normalized temperature offset slope msb */
942 buf[4] = ((uint16_t)normalized_temperature_offset_slope >> 0) & 0xFF; /* set normalized temperature offset slope lsb */
943 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
944 buf[6] = ((uint16_t)time_constant >> 8) & 0xFF; /* set time constant msb */
945 buf[7] = ((uint16_t)time_constant >> 0) & 0xFF; /* set time constant lsb */
946 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2); /* set crc */
948 (uint8_t *)buf, 9, 20); /* set temperature compensation command */
949 if (res != 0) /* check result */
950 {
951 handle->debug_print("sen5x: set temperature compensation failed.\n"); /* set temperature compensation failed */
952
953 return 1; /* return error */
954 }
955
956 return 0; /* success return 0 */
957}
958
972uint8_t sen5x_get_temperature_compensation(sen5x_handle_t *handle, int16_t *temperature_offset,
973 int16_t *normalized_temperature_offset_slope,
974 uint16_t *time_constant)
975{
976 uint8_t res;
977 uint8_t buf[9];
978
979 if (handle == NULL) /* check handle */
980 {
981 return 2; /* return error */
982 }
983 if (handle->inited != 1) /* check handle initialization */
984 {
985 return 3; /* return error */
986 }
987
989 (uint8_t *)buf, 9, 20); /* get temperature compensation command */
990 if (res != 0) /* check result */
991 {
992 handle->debug_print("sen5x: get temperature compensation failed.\n"); /* get temperature compensation failed */
993
994 return 1; /* return error */
995 }
996 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
997 {
998 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
999
1000 return 1; /* return error */
1001 }
1002 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1003 {
1004 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1005
1006 return 1; /* return error */
1007 }
1008 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2)) /* check crc */
1009 {
1010 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1011
1012 return 1; /* return error */
1013 }
1014 *temperature_offset = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set temperature offset */
1015 *normalized_temperature_offset_slope = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* set normalized temperature offset slope */
1016 *time_constant = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* set time constant */
1017
1018 return 0; /* success return 0 */
1019}
1020
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)
1043{
1044 if (handle == NULL) /* check handle */
1045 {
1046 return 2; /* return error */
1047 }
1048 if (handle->inited != 1) /* check handle initialization */
1049 {
1050 return 3; /* return error */
1051 }
1052
1053 *temperature_offset_reg = (int16_t)(temperature_offset_degree * 200.0f); /* convert real data to register data */
1054 *normalized_temperature_offset_slope_reg = (int16_t)(normalized_temperature_offset_slope_factor * 10000.0f); /* convert real data to register data */
1055 *time_constant_reg = (uint16_t)(time_constant_second); /* convert real data to register data */
1056
1057 return 0; /* success return 0 */
1058}
1059
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)
1082{
1083 if (handle == NULL) /* check handle */
1084 {
1085 return 2; /* return error */
1086 }
1087 if (handle->inited != 1) /* check handle initialization */
1088 {
1089 return 3; /* return error */
1090 }
1091
1092 *temperature_offset_degree = (float)(temperature_offset_reg) / 200.0f; /* convert raw data to real data */
1093 *normalized_temperature_offset_slope_factor = (float)(normalized_temperature_offset_slope_reg) / 10000.0f; /* convert raw data to real data */
1094 *time_constant_second = (float)(time_constant_reg); /* convert raw data to real data */
1095
1096 return 0; /* success return 0 */
1097}
1098
1110uint8_t sen5x_set_warm_start(sen5x_handle_t *handle, uint16_t param)
1111{
1112 uint8_t res;
1113 uint8_t buf[3];
1114
1115 if (handle == NULL) /* check handle */
1116 {
1117 return 2; /* return error */
1118 }
1119 if (handle->inited != 1) /* check handle initialization */
1120 {
1121 return 3; /* return error */
1122 }
1123
1124 buf[0] = ((uint16_t)param >> 8) & 0xFF; /* set param msb */
1125 buf[1] = ((uint16_t)param >> 0) & 0xFF; /* set param lsb */
1126 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1127 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_WARM_START_PARAMS,
1128 (uint8_t *)buf, 3, 20); /* set warm start command */
1129 if (res != 0) /* check result */
1130 {
1131 handle->debug_print("sen5x: set warm start failed.\n"); /* set warm start failed */
1132
1133 return 1; /* return error */
1134 }
1135
1136 return 0; /* success return 0 */
1137}
1138
1150uint8_t sen5x_get_warm_start(sen5x_handle_t *handle, uint16_t *param)
1151{
1152 uint8_t res;
1153 uint8_t buf[3];
1154
1155 if (handle == NULL) /* check handle */
1156 {
1157 return 2; /* return error */
1158 }
1159 if (handle->inited != 1) /* check handle initialization */
1160 {
1161 return 3; /* return error */
1162 }
1163
1164 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_WARM_START_PARAMS,
1165 (uint8_t *)buf, 3, 20); /* get warm start command */
1166 if (res != 0) /* check result */
1167 {
1168 handle->debug_print("sen5x: get warm start failed.\n"); /* get warm start failed */
1169
1170 return 1; /* return error */
1171 }
1172 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1173 {
1174 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1175
1176 return 1; /* return error */
1177 }
1178 *param = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set param */
1179
1180 return 0; /* success return 0 */
1181}
1182
1205uint8_t sen5x_set_voc_algorithm_tuning(sen5x_handle_t *handle, int16_t index_offset,
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)
1211{
1212 uint8_t res;
1213 uint8_t buf[18];
1214
1215 if (handle == NULL) /* check handle */
1216 {
1217 return 2; /* return error */
1218 }
1219 if (handle->inited != 1) /* check handle initialization */
1220 {
1221 return 3; /* return error */
1222 }
1223 if ((index_offset > 250) || (index_offset < 1)) /* check index offset */
1224 {
1225 handle->debug_print("sen5x: index_offset > 250 or index_offset < 1.\n"); /* index_offset > 250 or index_offset < 1 */
1226
1227 return 4; /* return error */
1228 }
1229 if ((learning_time_offset_hour > 1000) || (learning_time_offset_hour < 1)) /* check learning time offset hour */
1230 {
1231 handle->debug_print("sen5x: learning time offset hour > 1000 or learning time offset hour < 1.\n"); /* learning time offset hour > 1000 or learning time offset hour < 1 */
1232
1233 return 4; /* return error */
1234 }
1235 if ((learning_time_gain_hour > 1000) || (learning_time_gain_hour < 1)) /* check learning time gain hour */
1236 {
1237 handle->debug_print("sen5x: learning time gain hour > 1000 or learning time gain hour < 1.\n"); /* learning time gain hour > 1000 or learning time gain hour < 1 */
1238
1239 return 4; /* return error */
1240 }
1241 if ((gating_max_duration_minute > 3000) || (gating_max_duration_minute < 0)) /* check gating max duration minute */
1242 {
1243 handle->debug_print("sen5x: gating max duration minute > 3000 or gating max duration minute < 0.\n"); /* gating max duration minute > 3000 or gating max duration minute < 0 */
1244
1245 return 4; /* return error */
1246 }
1247 if ((std_initial > 5000) || (std_initial < 10)) /* check std initial */
1248 {
1249 handle->debug_print("sen5x: std initial > 5000 or std initial < 10.\n"); /* std initial > 5000 or std initial < 10 */
1250
1251 return 4; /* return error */
1252 }
1253 if ((gain_factor > 1000) || (gain_factor < 1)) /* check index offset */
1254 {
1255 handle->debug_print("sen5x: gain factor > 1000 or gain factor < 1.\n"); /* gain factor > 1000 or gain factor < 1 */
1256
1257 return 4; /* return error */
1258 }
1259
1260 buf[0] = ((uint16_t)index_offset >> 8) & 0xFF; /* set index offset msb */
1261 buf[1] = ((uint16_t)index_offset >> 0) & 0xFF; /* set index offset lsb */
1262 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1263 buf[3] = ((uint16_t)learning_time_offset_hour >> 8) & 0xFF; /* set learning time offset hour msb */
1264 buf[4] = ((uint16_t)learning_time_offset_hour >> 0) & 0xFF; /* set learning time offset hour lsb */
1265 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
1266 buf[6] = ((uint16_t)learning_time_gain_hour >> 8) & 0xFF; /* set learning time gain hour msb */
1267 buf[7] = ((uint16_t)learning_time_gain_hour >> 0) & 0xFF; /* set learning time gain hour lsb */
1268 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2); /* set crc */
1269 buf[9] = ((uint16_t)gating_max_duration_minute >> 8) & 0xFF; /* set gating max duration minute msb */
1270 buf[10] = ((uint16_t)gating_max_duration_minute >> 0) & 0xFF; /* set gating max duration minute lsb */
1271 buf[11] = a_sen5x_crc(handle, (uint8_t *)&buf[9], 2); /* set crc */
1272 buf[12] = ((uint16_t)std_initial >> 8) & 0xFF; /* set std initial msb */
1273 buf[13] = ((uint16_t)std_initial >> 0) & 0xFF; /* set std initial lsb */
1274 buf[14] = a_sen5x_crc(handle, (uint8_t *)&buf[12], 2); /* set crc */
1275 buf[15] = ((uint16_t)gain_factor >> 8) & 0xFF; /* set gain factor msb */
1276 buf[16] = ((uint16_t)gain_factor >> 0) & 0xFF; /* set gain factor lsb */
1277 buf[17] = a_sen5x_crc(handle, (uint8_t *)&buf[15], 2); /* set crc */
1278 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_TUNING_PARAMS,
1279 (uint8_t *)buf, 18, 20); /* set voc algorithm tuning command */
1280 if (res != 0) /* check result */
1281 {
1282 handle->debug_print("sen5x: set voc algorithm tuning failed.\n"); /* set voc algorithm tuning failed */
1283
1284 return 1; /* return error */
1285 }
1286
1287 return 0; /* success return 0 */
1288}
1289
1306uint8_t sen5x_get_voc_algorithm_tuning(sen5x_handle_t *handle, int16_t *index_offset,
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)
1312{
1313 uint8_t res;
1314 uint8_t buf[18];
1315
1316 if (handle == NULL) /* check handle */
1317 {
1318 return 2; /* return error */
1319 }
1320 if (handle->inited != 1) /* check handle initialization */
1321 {
1322 return 3; /* return error */
1323 }
1324
1326 (uint8_t *)buf, 18, 20); /* get voc algorithm tuning command */
1327 if (res != 0) /* check result */
1328 {
1329 handle->debug_print("sen5x: get voc algorithm tuning failed.\n"); /* get voc algorithm tuning failed */
1330
1331 return 1; /* return error */
1332 }
1333 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1334 {
1335 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1336
1337 return 1; /* return error */
1338 }
1339 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1340 {
1341 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1342
1343 return 1; /* return error */
1344 }
1345 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2)) /* check crc */
1346 {
1347 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1348
1349 return 1; /* return error */
1350 }
1351 if (buf[11] != a_sen5x_crc(handle, (uint8_t *)&buf[9], 2)) /* check crc */
1352 {
1353 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1354
1355 return 1; /* return error */
1356 }
1357 if (buf[14] != a_sen5x_crc(handle, (uint8_t *)&buf[12], 2)) /* check crc */
1358 {
1359 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1360
1361 return 1; /* return error */
1362 }
1363 if (buf[17] != a_sen5x_crc(handle, (uint8_t *)&buf[15], 2)) /* check crc */
1364 {
1365 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1366
1367 return 1; /* return error */
1368 }
1369 *index_offset = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set index offset */
1370 *learning_time_offset_hour = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* set learning time offset hour */
1371 *learning_time_gain_hour = (int16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* set learning time gain hour */
1372 *gating_max_duration_minute = (int16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* set gating max duration minute */
1373 *std_initial = (int16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0)); /* set std initial */
1374 *gain_factor = (int16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0)); /* set gain factor */
1375
1376 return 0; /* success return 0 */
1377}
1378
1401uint8_t sen5x_set_nox_algorithm_tuning(sen5x_handle_t *handle, int16_t index_offset,
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)
1407{
1408 uint8_t res;
1409 uint8_t buf[18];
1410
1411 if (handle == NULL) /* check handle */
1412 {
1413 return 2; /* return error */
1414 }
1415 if (handle->inited != 1) /* check handle initialization */
1416 {
1417 return 3; /* return error */
1418 }
1419 if ((index_offset > 250) || (index_offset < 1)) /* check index offset */
1420 {
1421 handle->debug_print("sen5x: index_offset > 250 or index_offset < 1.\n"); /* index_offset > 250 or index_offset < 1 */
1422
1423 return 4; /* return error */
1424 }
1425 if ((learning_time_offset_hour > 1000) || (learning_time_offset_hour < 1)) /* check learning time offset hour */
1426 {
1427 handle->debug_print("sen5x: learning time offset hour > 1000 or learning time offset hour < 1.\n"); /* learning time offset hour > 1000 or learning time offset hour < 1 */
1428
1429 return 4; /* return error */
1430 }
1431 if (learning_time_gain_hour != 12) /* check learning time gain hour */
1432 {
1433 handle->debug_print("sen5x: learning time gain hour must be 12.\n"); /* learning time gain hour must be 12 */
1434
1435 return 4; /* return error */
1436 }
1437 if ((gating_max_duration_minute > 3000) || (gating_max_duration_minute < 0)) /* check gating max duration minute */
1438 {
1439 handle->debug_print("sen5x: gating max duration minute > 3000 or gating max duration minute < 0.\n"); /* gating max duration minute > 3000 or gating max duration minute < 0 */
1440
1441 return 4; /* return error */
1442 }
1443 if (std_initial != 50) /* check std initial */
1444 {
1445 handle->debug_print("sen5x: std initial must be 50.\n"); /* std initial must be 50 */
1446
1447 return 4; /* return error */
1448 }
1449 if ((gain_factor > 1000) || (gain_factor < 1)) /* check index offset */
1450 {
1451 handle->debug_print("sen5x: gain factor > 1000 or gain factor < 1.\n"); /* gain factor > 1000 or gain factor < 1 */
1452
1453 return 4; /* return error */
1454 }
1455
1456 buf[0] = ((uint16_t)index_offset >> 8) & 0xFF; /* set index offset msb */
1457 buf[1] = ((uint16_t)index_offset >> 0) & 0xFF; /* set index offset lsb */
1458 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1459 buf[3] = ((uint16_t)learning_time_offset_hour >> 8) & 0xFF; /* set learning time offset hour msb */
1460 buf[4] = ((uint16_t)learning_time_offset_hour >> 0) & 0xFF; /* set learning time offset hour lsb */
1461 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
1462 buf[6] = ((uint16_t)learning_time_gain_hour >> 8) & 0xFF; /* set learning time gain hour msb */
1463 buf[7] = ((uint16_t)learning_time_gain_hour >> 0) & 0xFF; /* set learning time gain hour lsb */
1464 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2); /* set crc */
1465 buf[9] = ((uint16_t)gating_max_duration_minute >> 8) & 0xFF; /* set gating max duration minute msb */
1466 buf[10] = ((uint16_t)gating_max_duration_minute >> 0) & 0xFF; /* set gating max duration minute lsb */
1467 buf[11] = a_sen5x_crc(handle, (uint8_t *)&buf[9], 2); /* set crc */
1468 buf[12] = ((uint16_t)std_initial >> 8) & 0xFF; /* set std initial msb */
1469 buf[13] = ((uint16_t)std_initial >> 0) & 0xFF; /* set std initial lsb */
1470 buf[14] = a_sen5x_crc(handle, (uint8_t *)&buf[12], 2); /* set crc */
1471 buf[15] = ((uint16_t)gain_factor >> 8) & 0xFF; /* set gain factor msb */
1472 buf[16] = ((uint16_t)gain_factor >> 0) & 0xFF; /* set gain factor lsb */
1473 buf[17] = a_sen5x_crc(handle, (uint8_t *)&buf[15], 2); /* set crc */
1474 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_NOX_ALG_TUNING_PARAMS,
1475 (uint8_t *)buf, 18, 20); /* set nox algorithm tuning command */
1476 if (res != 0) /* check result */
1477 {
1478 handle->debug_print("sen5x: set nox algorithm tuning failed.\n"); /* set nox algorithm tuning failed */
1479
1480 return 1; /* return error */
1481 }
1482
1483 return 0; /* success return 0 */
1484}
1485
1502uint8_t sen5x_get_nox_algorithm_tuning(sen5x_handle_t *handle, int16_t *index_offset,
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)
1508{
1509 uint8_t res;
1510 uint8_t buf[18];
1511
1512 if (handle == NULL) /* check handle */
1513 {
1514 return 2; /* return error */
1515 }
1516 if (handle->inited != 1) /* check handle initialization */
1517 {
1518 return 3; /* return error */
1519 }
1520
1522 (uint8_t *)buf, 18, 20); /* get nox algorithm tuning command */
1523 if (res != 0) /* check result */
1524 {
1525 handle->debug_print("sen5x: get nox algorithm tuning failed.\n"); /* get nox algorithm tuning failed */
1526
1527 return 1; /* return error */
1528 }
1529 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1530 {
1531 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1532
1533 return 1; /* return error */
1534 }
1535 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1536 {
1537 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1538
1539 return 1; /* return error */
1540 }
1541 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2)) /* check crc */
1542 {
1543 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1544
1545 return 1; /* return error */
1546 }
1547 if (buf[11] != a_sen5x_crc(handle, (uint8_t *)&buf[9], 2)) /* check crc */
1548 {
1549 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1550
1551 return 1; /* return error */
1552 }
1553 if (buf[14] != a_sen5x_crc(handle, (uint8_t *)&buf[12], 2)) /* check crc */
1554 {
1555 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1556
1557 return 1; /* return error */
1558 }
1559 if (buf[17] != a_sen5x_crc(handle, (uint8_t *)&buf[15], 2)) /* check crc */
1560 {
1561 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1562
1563 return 1; /* return error */
1564 }
1565 *index_offset = (int16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set index offset */
1566 *learning_time_offset_hour = (int16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* set learning time offset hour */
1567 *learning_time_gain_hour = (int16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* set learning time gain hour */
1568 *gating_max_duration_minute = (int16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* set gating max duration minute */
1569 *std_initial = (int16_t)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0)); /* set std initial */
1570 *gain_factor = (int16_t)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0)); /* set gain factor */
1571
1572 return 0; /* success return 0 */
1573}
1574
1587{
1588 uint8_t res;
1589 uint8_t buf[3];
1590
1591 if (handle == NULL) /* check handle */
1592 {
1593 return 2; /* return error */
1594 }
1595 if (handle->inited != 1) /* check handle initialization */
1596 {
1597 return 3; /* return error */
1598 }
1599
1600 buf[0] = ((uint16_t)mode >> 8) & 0xFF; /* set rht acceleration mode msb */
1601 buf[1] = ((uint16_t)mode >> 0) & 0xFF; /* set rht acceleration mode lsb */
1602 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1603 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_RHT_ACC_MODE,
1604 (uint8_t *)buf, 3, 20); /* set rht acceleration mode command */
1605 if (res != 0) /* check result */
1606 {
1607 handle->debug_print("sen5x: set rht acceleration mode failed.\n"); /* set rht acceleration mode failed */
1608
1609 return 1; /* return error */
1610 }
1611
1612 return 0; /* success return 0 */
1613}
1614
1627{
1628 uint8_t res;
1629 uint8_t buf[3];
1630
1631 if (handle == NULL) /* check handle */
1632 {
1633 return 2; /* return error */
1634 }
1635 if (handle->inited != 1) /* check handle initialization */
1636 {
1637 return 3; /* return error */
1638 }
1639
1640 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_RHT_ACC_MODE,
1641 (uint8_t *)buf, 3, 20); /* get rht acceleration mode command */
1642 if (res != 0) /* check result */
1643 {
1644 handle->debug_print("sen5x: get rht acceleration mode failed.\n"); /* get rht acceleration mode failed */
1645
1646 return 1; /* return error */
1647 }
1648 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1649 {
1650 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1651
1652 return 1; /* return error */
1653 }
1654 *mode = (sen5x_rht_acceleration_mode_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set rht acceleration mode */
1655
1656 return 0; /* success return 0 */
1657}
1658
1670uint8_t sen5x_set_voc_algorithm_state(sen5x_handle_t *handle, uint16_t state[4])
1671{
1672 uint8_t res;
1673 uint8_t buf[12];
1674
1675 if (handle == NULL) /* check handle */
1676 {
1677 return 2; /* return error */
1678 }
1679 if (handle->inited != 1) /* check handle initialization */
1680 {
1681 return 3; /* return error */
1682 }
1683
1684 buf[0] = ((uint16_t)state[0] >> 8) & 0xFF; /* set state0 msb */
1685 buf[1] = ((uint16_t)state[0] >> 0) & 0xFF; /* set state0 lsb */
1686 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1687 buf[3] = ((uint16_t)state[1] >> 8) & 0xFF; /* set state1 msb */
1688 buf[4] = ((uint16_t)state[1] >> 0) & 0xFF; /* set state1 lsb */
1689 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
1690 buf[6] = ((uint16_t)state[2] >> 8) & 0xFF; /* set state2 msb */
1691 buf[7] = ((uint16_t)state[2] >> 0) & 0xFF; /* set state2 lsb */
1692 buf[8] = a_sen5x_crc(handle, (uint8_t *)&buf[6], 2); /* set crc */
1693 buf[9] = ((uint16_t)state[3] >> 8) & 0xFF; /* set state3 msb */
1694 buf[10] = ((uint16_t)state[3] >> 0) & 0xFF; /* set state3 lsb */
1695 buf[11] = a_sen5x_crc(handle, (uint8_t *)&buf[9], 2); /* set crc */
1696 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_STATE,
1697 (uint8_t *)buf, 12, 20); /* set voc algorithm state command */
1698 if (res != 0) /* check result */
1699 {
1700 handle->debug_print("sen5x: set voc algorithm state failed.\n"); /* set voc algorithm state failed */
1701
1702 return 1; /* return error */
1703 }
1704
1705 return 0; /* success return 0 */
1706}
1707
1719uint8_t sen5x_get_voc_algorithm_state(sen5x_handle_t *handle, uint16_t state[4])
1720{
1721 uint8_t res;
1722 uint8_t buf[12];
1723
1724 if (handle == NULL) /* check handle */
1725 {
1726 return 2; /* return error */
1727 }
1728 if (handle->inited != 1) /* check handle initialization */
1729 {
1730 return 3; /* return error */
1731 }
1732
1733 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_WRITE_VOC_ALG_STATE,
1734 (uint8_t *)buf, 12, 20); /* get voc algorithm state command */
1735 if (res != 0) /* check result */
1736 {
1737 handle->debug_print("sen5x: get voc algorithm state failed.\n"); /* get voc algorithm state failed */
1738
1739 return 1; /* return error */
1740 }
1741 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1742 {
1743 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1744
1745 return 1; /* return error */
1746 }
1747 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1748 {
1749 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1750
1751 return 1; /* return error */
1752 }
1753 if (buf[8] != a_sen5x_crc(handle, (uint8_t *)&buf[6], 2)) /* check crc */
1754 {
1755 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1756
1757 return 1; /* return error */
1758 }
1759 if (buf[11] != a_sen5x_crc(handle, (uint8_t *)&buf[9], 2)) /* check crc */
1760 {
1761 handle->debug_print("sen5x: crc check failed.\n"); /* crc check failed */
1762
1763 return 1; /* return error */
1764 }
1765 state[0] = (uint16_t)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* set voc algorithm state */
1766 state[1] = (uint16_t)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* set voc algorithm state */
1767 state[2] = (uint16_t)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* set voc algorithm state */
1768 state[3] = (uint16_t)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* set voc algorithm state */
1769
1770 return 0; /* success return 0 */
1771}
1772
1784{
1785 uint8_t res;
1786
1787 if (handle == NULL) /* check handle */
1788 {
1789 return 2; /* return error */
1790 }
1791 if (handle->inited != 1) /* check handle initialization */
1792 {
1793 return 3; /* return error */
1794 }
1795
1796 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_START_FAN_CLEANING, NULL, 0, 20); /* start the fan cleaning command */
1797 if (res != 0) /* check result */
1798 {
1799 handle->debug_print("sen5x: start the fan cleaning failed.\n"); /* start the fan cleaning failed */
1800
1801 return 1; /* return error */
1802 }
1803
1804 return 0; /* success return 0 */
1805}
1806
1819uint8_t sen5x_set_auto_cleaning_interval(sen5x_handle_t *handle, uint32_t second)
1820{
1821 uint8_t res;
1822 uint8_t buf[6];
1823
1824 if (handle == NULL) /* check handle */
1825 {
1826 return 2; /* return error */
1827 }
1828 if (handle->inited != 1) /* check handle initialization */
1829 {
1830 return 3; /* return error */
1831 }
1832 if ((second < 10) || (second > 604800)) /* check second */
1833 {
1834 handle->debug_print("sen5x: second is invalid.\n"); /* second is invalid */
1835
1836 return 4; /* return error */
1837 }
1838
1839 buf[0] = (second >> 24) & 0xFF; /* set byte 4 */
1840 buf[1] = (second >> 16) & 0xFF; /* set byte 3 */
1841 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1842 buf[3] = (second >> 8) & 0xFF; /* set byte 2 */
1843 buf[4] = (second >> 0) & 0xFF; /* set byte 1 */
1844 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
1846 (uint8_t *)buf, 6, 20); /* set auto cleaning interval command */
1847 if (res != 0) /* check result */
1848 {
1849 handle->debug_print("sen5x: set auto cleaning interval failed.\n"); /* set auto cleaning interval failed */
1850
1851 return 1; /* return error */
1852 }
1853
1854 return 0; /* success return 0 */
1855}
1856
1868uint8_t sen5x_get_auto_cleaning_interval(sen5x_handle_t *handle, uint32_t *second)
1869{
1870 uint8_t res;
1871 uint8_t buf[6];
1872
1873 if (handle == NULL) /* check handle */
1874 {
1875 return 2; /* return error */
1876 }
1877 if (handle->inited != 1) /* check handle initialization */
1878 {
1879 return 3; /* return error */
1880 }
1881
1882 memset(buf, 0, sizeof(uint8_t) * 6); /* clear the buffer */
1884 (uint8_t *)buf, 6, 20); /* get auto cleaning interval command */
1885 if (res != 0) /* check result */
1886 {
1887 handle->debug_print("sen5x: get auto cleaning interval failed.\n"); /* get auto cleaning interval failed */
1888
1889 return 1; /* return error */
1890 }
1891 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1892 {
1893 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
1894
1895 return 1; /* return error */
1896 }
1897 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1898 {
1899 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
1900
1901 return 1; /* return error */
1902 }
1903 *second = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
1904 ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0); /* get second */
1905
1906 return 0; /* success return 0 */
1907}
1908
1920{
1921 uint8_t res;
1922 uint32_t second;
1923 uint8_t buf[6];
1924
1925 if (handle == NULL) /* check handle */
1926 {
1927 return 2; /* return error */
1928 }
1929 if (handle->inited != 1) /* check handle initialization */
1930 {
1931 return 3; /* return error */
1932 }
1933
1934 second = 0; /* disable second */
1935 buf[0] = (second >> 24) & 0xFF; /* set byte 4 */
1936 buf[1] = (second >> 16) & 0xFF; /* set byte 3 */
1937 buf[2] = a_sen5x_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1938 buf[3] = (second >> 8) & 0xFF; /* set byte 2 */
1939 buf[4] = (second >> 0) & 0xFF; /* set byte 1 */
1940 buf[5] = a_sen5x_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
1942 (uint8_t *)buf, 6, 20); /* set auto cleaning interval command */
1943 if (res != 0) /* check result */
1944 {
1945 handle->debug_print("sen5x: set auto cleaning interval failed.\n"); /* set auto cleaning interval failed */
1946
1947 return 1; /* return error */
1948 }
1949
1950 return 0; /* success return 0 */
1951}
1952
1964uint8_t sen5x_get_product_name(sen5x_handle_t *handle, char name[32])
1965{
1966 uint8_t res, i, j;
1967 uint8_t buf[48];
1968
1969 if (handle == NULL) /* check handle */
1970 {
1971 return 2; /* return error */
1972 }
1973 if (handle->inited != 1) /* check handle initialization */
1974 {
1975 return 3; /* return error */
1976 }
1977
1978 memset(buf, 0, sizeof(uint8_t) * 48); /* clear the buffer */
1979 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_PRODUCT_NAME, (uint8_t *)buf, 48, 20); /* read product name command */
1980 if (res != 0) /* check result */
1981 {
1982 handle->debug_print("sen5x: read product name failed.\n"); /* read product name failed */
1983
1984 return 1; /* return error */
1985 }
1986 for (i = 0; i < 16; i++) /* check crc */
1987 {
1988 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
1989 {
1990 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
1991
1992 return 1; /* return error */
1993 }
1994 }
1995 j = 0; /* set zero */
1996 for (i = 0; i < 16; i++) /* copy name */
1997 {
1998 name[j] = buf[i * 3 + 0]; /* set name */
1999 j++; /* j++ */
2000 name[j] = buf[i * 3 + 1]; /* set name */
2001 j++; /* j++ */
2002 }
2003
2004 return 0; /* success return 0 */
2005}
2006
2018uint8_t sen5x_get_serial_number(sen5x_handle_t *handle, char sn[32])
2019{
2020 uint8_t res, i, j;
2021 uint8_t buf[48];
2022
2023 if (handle == NULL) /* check handle */
2024 {
2025 return 2; /* return error */
2026 }
2027 if (handle->inited != 1) /* check handle initialization */
2028 {
2029 return 3; /* return error */
2030 }
2031
2032 memset(buf, 0, sizeof(uint8_t) * 48); /* clear the buffer */
2033 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_SERIAL_NUMBER, (uint8_t *)buf, 48, 20); /* read serial number command */
2034 if (res != 0) /* check result */
2035 {
2036 handle->debug_print("sen5x: read serial number failed.\n"); /* read serial number failed */
2037
2038 return 1; /* return error */
2039 }
2040 for (i = 0; i < 16; i++) /* check crc */
2041 {
2042 if (buf[i * 3 + 2] != a_sen5x_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
2043 {
2044 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
2045
2046 return 1; /* return error */
2047 }
2048 }
2049 j = 0; /* set zero */
2050 for (i = 0; i < 16; i++) /* copy serial number */
2051 {
2052 sn[j] = buf[i * 3 + 0]; /* set serial number */
2053 j++; /* j++ */
2054 sn[j] = buf[i * 3 + 1]; /* set serial number */
2055 j++; /* j++ */
2056 }
2057
2058 return 0; /* success return 0 */
2059}
2060
2072uint8_t sen5x_get_version(sen5x_handle_t *handle, uint8_t *version)
2073{
2074 uint8_t res;
2075 uint8_t buf[3];
2076
2077 if (handle == NULL) /* check handle */
2078 {
2079 return 2; /* return error */
2080 }
2081 if (handle->inited != 1) /* check handle initialization */
2082 {
2083 return 3; /* return error */
2084 }
2085
2086 memset(buf, 0, sizeof(uint8_t) * 3); /* clear the buffer */
2087 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_VERSION, (uint8_t *)buf, 3, 20); /* read version command */
2088 if (res != 0) /* check result */
2089 {
2090 handle->debug_print("sen5x: read version failed.\n"); /* read version failed */
2091
2092 return 1; /* return error */
2093 }
2094 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
2095 {
2096 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
2097
2098 return 1; /* return error */
2099 }
2100 *version = buf[0]; /* set version */
2101
2102 return 0; /* success return 0 */
2103}
2104
2116uint8_t sen5x_get_device_status(sen5x_handle_t *handle, uint32_t *status)
2117{
2118 uint8_t res;
2119 uint8_t buf[6];
2120
2121 if (handle == NULL) /* check handle */
2122 {
2123 return 2; /* return error */
2124 }
2125 if (handle->inited != 1) /* check handle initialization */
2126 {
2127 return 3; /* return error */
2128 }
2129
2130 memset(buf, 0, sizeof(uint8_t) * 6); /* clear the buffer */
2131 res = a_sen5x_iic_read(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_READ_DEVICE_STATUS_REG,
2132 (uint8_t *)buf, 6, 20); /* get device status command */
2133 if (res != 0) /* check result */
2134 {
2135 handle->debug_print("sen5x: get device status failed.\n"); /* get device status failed */
2136
2137 return 1; /* return error */
2138 }
2139 if (buf[2] != a_sen5x_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
2140 {
2141 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
2142
2143 return 1; /* return error */
2144 }
2145 if (buf[5] != a_sen5x_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
2146 {
2147 handle->debug_print("sen5x: crc is error.\n"); /* crc is error */
2148
2149 return 1; /* return error */
2150 }
2151 *status = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
2152 ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0); /* get status */
2153
2154 return 0; /* success return 0 */
2155}
2156
2168{
2169 uint8_t res;
2170
2171 if (handle == NULL) /* check handle */
2172 {
2173 return 2; /* return error */
2174 }
2175 if (handle->inited != 1) /* check handle initialization */
2176 {
2177 return 3; /* return error */
2178 }
2179
2180 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_CLEAR_DEVICE_STATUS_REG, NULL, 0, 20); /* clear device status command */
2181 if (res != 0) /* check result */
2182 {
2183 handle->debug_print("sen5x: clear device status failed.\n"); /* clear device status failed */
2184
2185 return 1; /* return error */
2186 }
2187
2188 return 0; /* success return 0 */
2189}
2190
2202{
2203 uint8_t res;
2204
2205 if (handle == NULL) /* check handle */
2206 {
2207 return 2; /* return error */
2208 }
2209 if (handle->inited != 1) /* check handle initialization */
2210 {
2211 return 3; /* return error */
2212 }
2213
2214 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_RESET, NULL, 0, 200); /* reset command */
2215 if (res != 0) /* check result */
2216 {
2217 handle->debug_print("sen5x: reset failed.\n"); /* reset failed */
2218
2219 return 1; /* return error */
2220 }
2221
2222 return 0; /* success return 0 */
2223}
2224
2235{
2236 if (handle == NULL) /* check handle */
2237 {
2238 return 2; /* return error */
2239 }
2240
2241 handle->type = (uint8_t)type; /* set type */
2242
2243 return 0; /* success return 0 */
2244}
2245
2256{
2257 if (handle == NULL) /* check handle */
2258 {
2259 return 2; /* return error */
2260 }
2261
2262 *type = (sen5x_type_t)(handle->type); /* set type */
2263
2264 return 0; /* success return 0 */
2265}
2266
2279{
2280 uint8_t res;
2281
2282 if (handle == NULL) /* check handle */
2283 {
2284 return 2; /* return error */
2285 }
2286 if (handle->debug_print == NULL) /* check debug_print */
2287 {
2288 return 3; /* return error */
2289 }
2290 if (handle->iic_init == NULL) /* check iic_init */
2291 {
2292 handle->debug_print("sen5x: iic_init is null.\n"); /* iic_init is null */
2293
2294 return 3; /* return error */
2295 }
2296 if (handle->iic_deinit == NULL) /* check iic_deinit */
2297 {
2298 handle->debug_print("sen5x: iic_deinit is null.\n"); /* iic_deinit is null */
2299
2300 return 3; /* return error */
2301 }
2302 if (handle->iic_write_cmd == NULL) /* check iic_write_cmd */
2303 {
2304 handle->debug_print("sen5x: iic_write_cmd is null.\n"); /* iic_write_cmd is null */
2305
2306 return 3; /* return error */
2307 }
2308 if (handle->iic_read_cmd == NULL) /* check iic_read_cmd */
2309 {
2310 handle->debug_print("sen5x: iic_read_cmd is null.\n"); /* iic_read_cmd is null */
2311
2312 return 3; /* return error */
2313 }
2314 if (handle->delay_ms == NULL) /* check delay_ms */
2315 {
2316 handle->debug_print("sen5x: delay_ms is null.\n"); /* delay_ms is null */
2317
2318 return 3; /* return error */
2319 }
2320
2321 if (handle->iic_init() != 0) /* iic init */
2322 {
2323 handle->debug_print("sen5x: iic init failed.\n"); /* iic init failed */
2324
2325 return 1; /* return error */
2326 }
2327 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_RESET, NULL, 0, 200); /* reset command */
2328 if (res != 0) /* check result */
2329 {
2330 handle->debug_print("sen5x: reset failed.\n"); /* reset failed */
2331 (void)handle->iic_deinit(); /* iic deinit */
2332
2333 return 4; /* return error */
2334 }
2335 handle->inited = 1; /* flag finish initialization */
2336
2337 return 0; /* success return 0 */
2338}
2339
2352{
2353 uint8_t res;
2354
2355 if (handle == NULL) /* check handle */
2356 {
2357 return 2; /* return error */
2358 }
2359 if (handle->inited != 1) /* check handle initialization */
2360 {
2361 return 3; /* return error */
2362 }
2363
2364 res = a_sen5x_iic_write(handle, SEN5X_ADDRESS, SEN5X_IIC_COMMAND_RESET, NULL, 0, 200); /* reset command */
2365 if (res != 0) /* check result */
2366 {
2367 handle->debug_print("sen5x: reset failed.\n"); /* reset failed */
2368
2369 return 4; /* return error */
2370 }
2371 res = handle->iic_deinit(); /* iic deinit */
2372 if (res != 0) /* check result */
2373 {
2374 handle->debug_print("sen5x: iic deinit failed.\n"); /* iic deinit */
2375
2376 return 1; /* return error */
2377 }
2378 handle->inited = 0; /* flag close initialization */
2379
2380 return 0; /* success return 0 */
2381}
2382
2396uint8_t sen5x_set_reg(sen5x_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
2397{
2398 if (handle == NULL) /* check handle */
2399 {
2400 return 2; /* return error */
2401 }
2402 if (handle->inited != 1) /* check handle initialization */
2403 {
2404 return 3; /* return error */
2405 }
2406
2407 return a_sen5x_iic_write(handle, SEN5X_ADDRESS, reg, buf, len, 20); /* write the data */
2408}
2409
2423uint8_t sen5x_get_reg(sen5x_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
2424{
2425 if (handle == NULL) /* check handle */
2426 {
2427 return 2; /* return error */
2428 }
2429 if (handle->inited != 1) /* check handle initialization */
2430 {
2431 return 3; /* return error */
2432 }
2433
2434 return a_sen5x_iic_read(handle, SEN5X_ADDRESS, reg, buf, len, 20); /* read the data */
2435}
2436
2446{
2447 if (info == NULL) /* check handle */
2448 {
2449 return 2; /* return error */
2450 }
2451
2452 memset(info, 0, sizeof(sen5x_info_t)); /* initialize sen5x info structure */
2453 strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */
2454 strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */
2455 strncpy(info->interface, "IIC", 8); /* copy interface name */
2456 info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */
2457 info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */
2458 info->max_current_ma = MAX_CURRENT; /* set maximum current */
2459 info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */
2460 info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */
2461 info->driver_version = DRIVER_VERSION; /* set driver version */
2462
2463 return 0; /* success return 0 */
2464}
#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 MAX_CURRENT
#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 TEMPERATURE_MAX
#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 TEMPERATURE_MIN
#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 DRIVER_VERSION
#define SEN5X_IIC_COMMAND_START_FAN_CLEANING
#define SEN5X_IIC_COMMAND_START_MEASUREMENT
chip command definition
driver sen5x header file
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
@ SEN50
@ SEN54
@ SEN55
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
uint16_t pm10_raw
uint16_t pm1p0_raw
uint16_t pm2p5_raw
uint16_t pm4p0_raw
uint8_t pm_valid
float compensated_ambient_temperature_degree
int16_t compensated_ambient_temperature_raw
int16_t compensated_ambient_humidity_raw
uint16_t pm10_raw
uint16_t pm1p0_raw
float compensated_ambient_humidity_percentage
uint16_t pm2p5_raw
uint16_t pm4p0_raw
uint8_t pm_valid
int16_t voc_raw
float compensated_ambient_temperature_degree
int16_t compensated_ambient_temperature_raw
int16_t compensated_ambient_humidity_raw
uint16_t pm10_raw
uint16_t pm1p0_raw
float compensated_ambient_humidity_percentage
uint16_t pm2p5_raw
int16_t nox_raw
uint16_t pm4p0_raw
uint8_t pm_valid
int16_t voc_raw
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 temperature_max
float supply_voltage_max_v
uint32_t driver_version
float temperature_min
float max_current_ma
char manufacturer_name[32]
float supply_voltage_min_v
char interface[8]
char chip_name[32]
uint16_t mass_concentration_pm4p0_raw
float pm1p0_cm3
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
float pm4p0_cm3
uint16_t mass_concentration_pm1p0_raw
uint16_t number_concentration_pm4p0_raw
uint16_t number_concentration_pm2p5_raw
float pm1p0_ug_m3
uint16_t mass_concentration_pm10_raw
float pm0p5_cm3
float pm4p0_ug_m3
float pm10_ug_m3
uint8_t pm_valid
float pm2p5_cm3
float pm2p5_ug_m3
uint16_t typical_particle_raw
uint16_t nox_raw
float humidity_percentage
int16_t temperature_raw
float temperature_degree
uint16_t voc_raw
int16_t humidity_raw