42#define CHIP_NAME "Sensirion SCD30"
43#define MANUFACTURER_NAME "Sensirion"
44#define SUPPLY_VOLTAGE_MIN 3.3f
45#define SUPPLY_VOLTAGE_MAX 5.5f
46#define MAX_CURRENT 75.0f
47#define TEMPERATURE_MIN -40.0f
48#define TEMPERATURE_MAX 70.0f
49#define DRIVER_VERSION 1000
54#define SCD30_ADDRESS 0xC2
59#define SCD30_IIC_COMMAND_START_PERIODIC_MEASUREMENT 0x0010U
60#define SCD30_IIC_COMMAND_STOP_PERIODIC_MEASUREMENT 0x0104U
61#define SCD30_IIC_COMMAND_SET_MEASUREMENT_INTERVAL 0x4600U
62#define SCD30_IIC_COMMAND_GET_DATA_READY_STATUS 0x0202U
63#define SCD30_IIC_COMMAND_READ_MEASUREMENT 0x0300U
64#define SCD30_IIC_COMMAND_AUTO_SELF_CALIBRATION 0x5306U
65#define SCD30_IIC_COMMAND_SET_FORCED_RECALIBRATION 0x5204U
66#define SCD30_IIC_COMMAND_SET_TEMPERATURE_OFFSET 0x5403U
67#define SCD30_IIC_COMMAND_SET_ALTITUDE 0x5102U
68#define SCD30_IIC_COMMAND_READ_FIRMWARE_VERSION 0xD100U
69#define SCD30_IIC_COMMAND_SOFT_RESET 0xD304U
70#define SCD30_UART_ADDRESS_START_PERIODIC_MEASUREMENT 0x0036U
71#define SCD30_UART_ADDRESS_STOP_PERIODIC_MEASUREMENT 0x0037U
72#define SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL 0x0025U
73#define SCD30_UART_ADDRESS_GET_DATA_READY_STATUS 0x0027U
74#define SCD30_UART_ADDRESS_READ_MEASUREMENT 0x0028U
75#define SCD30_UART_ADDRESS_AUTO_SELF_CALIBRATION 0x003AU
76#define SCD30_UART_ADDRESS_SET_FORCED_RECALIBRATION 0x0039U
77#define SCD30_UART_ADDRESS_SET_TEMPERATURE_OFFSET 0x003BU
78#define SCD30_UART_ADDRESS_SET_ALTITUDE 0x0038U
79#define SCD30_UART_ADDRESS_READ_FIRMWARE_VERSION 0x0020U
80#define SCD30_UART_ADDRESS_SOFT_RESET 0x0034U
85static const uint8_t gs_crc_table_hi[] =
87 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
88 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
89 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
90 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
91 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
92 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
93 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
94 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
95 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
96 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
97 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
98 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
99 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
100 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
101 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
102 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
103 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
104 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
105 0x00, 0xC1, 0x81, 0x40
111static const uint8_t gs_crc_table_lo[] =
113 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5,
114 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B,
115 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
116 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
117 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
118 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
119 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8,
120 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
121 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21,
122 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
123 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A,
124 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
125 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7,
126 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51,
127 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
128 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
129 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D,
130 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
131 0x41, 0x81, 0x80, 0x40
141static uint16_t a_scd30_generate_crc16(uint8_t *data, uint16_t count)
143 uint8_t crc_hi = 0xFF;
144 uint8_t crc_lo = 0xFF;
149 i = crc_lo ^ *data++;
150 crc_lo = crc_hi ^ gs_crc_table_hi[i];
151 crc_hi = gs_crc_table_lo[i];
154 return ((uint16_t)crc_hi << 8 | crc_lo);
164static uint8_t a_scd30_generate_crc8(uint8_t *data, uint8_t count)
166 uint8_t current_byte;
170 for (current_byte = 0; current_byte < count; ++current_byte)
172 crc ^= (data[current_byte]);
173 for (crc_bit = 8; crc_bit > 0; --crc_bit)
175 if ((crc & 0x80) != 0)
177 crc = (crc << 1) ^ 0x31;
201static uint8_t a_scd30_iic_read(
scd30_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
205 buf[0] = (reg >> 8) & 0xFF;
206 buf[1] = (reg >> 0) & 0xFF;
232static uint8_t a_scd30_iic_write(
scd30_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
240 buf[0] = (reg >> 8) & 0xFF;
241 buf[1] = (reg >> 0) & 0xFF;
242 memcpy((uint8_t *)&buf[2], data, len);
265static uint8_t a_scd30_uart_write_read(
scd30_handle_t *handle, uint8_t *input, uint16_t in_len,
266 uint16_t delay_ms, uint8_t *output, uint16_t out_len)
279 len = handle->
uart_read(output, out_len);
297static uint8_t a_scd30_get_data_ready_status(
scd30_handle_t *handle, uint16_t *status)
303 uint8_t input_buf[6 + 2];
313 crc16 = a_scd30_generate_crc16(input_buf, 6);
314 input_buf[6] = (crc16 >> 0) & 0xFF;
315 input_buf[7] = (crc16 >> 8) & 0xFF;
316 memset(out_buf, 0,
sizeof(uint8_t) * 7);
317 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
320 handle->
debug_print(
"scd30: write read failed.\n");
324 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
325 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
331 if (out_buf[0] != 0x61)
333 handle->
debug_print(
"scd30: header is invalid.\n");
337 if (out_buf[1] != 0x03)
343 if (out_buf[2] != 0x02)
345 handle->
debug_print(
"scd30: number is invalid.\n");
349 *status = ((uint16_t)out_buf[3] << 8) | out_buf[4];
358 handle->
debug_print(
"scd30: get data ready status failed.\n");
362 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
368 *status = ((uint16_t)buf[0] << 8) | buf[1];
390 handle->
iic_uart = (uint8_t)interface;
440 if ((mbar < 700) || (mbar > 1400))
449 uint8_t input_buf[6 + 2];
450 uint8_t out_buf[6 + 2];
457 input_buf[4] = (mbar >> 8) & 0xFF;
458 input_buf[5] = (mbar >> 0) & 0xFF;
459 crc16 = a_scd30_generate_crc16(input_buf, 6);
460 input_buf[6] = (crc16 >> 0) & 0xFF;
461 input_buf[7] = (crc16 >> 8) & 0xFF;
462 memset(out_buf, 0,
sizeof(uint8_t) * 8);
463 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
466 handle->
debug_print(
"scd30: write read failed.\n");
470 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
471 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
477 if (memcmp(input_buf, out_buf, 8) != 0)
479 handle->
debug_print(
"scd30: response check error.\n");
488 buf[0] = (mbar >> 8) & 0xFF;
489 buf[1] = (mbar >> 0) & 0xFF;
490 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
494 handle->
debug_print(
"scd30: start measurement failed.\n");
528 uint8_t input_buf[6 + 2];
529 uint8_t out_buf[6 + 2];
538 crc16 = a_scd30_generate_crc16(input_buf, 6);
539 input_buf[6] = (crc16 >> 0) & 0xFF;
540 input_buf[7] = (crc16 >> 8) & 0xFF;
541 memset(out_buf, 0,
sizeof(uint8_t) * 8);
542 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
545 handle->
debug_print(
"scd30: write read failed.\n");
549 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
550 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
556 if (memcmp(input_buf, out_buf, 8) != 0)
558 handle->
debug_print(
"scd30: response check error.\n");
569 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
573 handle->
debug_print(
"scd30: start measurement failed.\n");
607 uint8_t input_buf[6 + 2];
608 uint8_t out_buf[6 + 2];
617 crc16 = a_scd30_generate_crc16(input_buf, 6);
618 input_buf[6] = (crc16 >> 0) & 0xFF;
619 input_buf[7] = (crc16 >> 8) & 0xFF;
620 memset(out_buf, 0,
sizeof(uint8_t) * 8);
621 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
624 handle->
debug_print(
"scd30: write read failed.\n");
628 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
629 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
635 if (memcmp(input_buf, out_buf, 8) != 0)
637 handle->
debug_print(
"scd30: response check error.\n");
647 handle->
debug_print(
"scd30: stop measurement failed.\n");
680 if ((second < 2) || (second > 1800))
682 handle->
debug_print(
"scd30: second is invalid.\n");
689 uint8_t input_buf[6 + 2];
690 uint8_t out_buf[6 + 2];
697 input_buf[4] = (second >> 8) & 0xFF;
698 input_buf[5] = (second >> 0) & 0xFF;
699 crc16 = a_scd30_generate_crc16(input_buf, 6);
700 input_buf[6] = (crc16 >> 0) & 0xFF;
701 input_buf[7] = (crc16 >> 8) & 0xFF;
702 memset(out_buf, 0,
sizeof(uint8_t) * 8);
703 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
706 handle->
debug_print(
"scd30: write read failed.\n");
710 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
711 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
717 if (memcmp(input_buf, out_buf, 8) != 0)
719 handle->
debug_print(
"scd30: response check error.\n");
728 buf[0] = (second >> 8) & 0xFF;
729 buf[1] = (second >> 0) & 0xFF;
730 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
734 handle->
debug_print(
"scd30: set measurement interval failed.\n");
769 uint8_t input_buf[6 + 2];
779 crc16 = a_scd30_generate_crc16(input_buf, 6);
780 input_buf[6] = (crc16 >> 0) & 0xFF;
781 input_buf[7] = (crc16 >> 8) & 0xFF;
782 memset(out_buf, 0,
sizeof(uint8_t) * 7);
783 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
786 handle->
debug_print(
"scd30: write read failed.\n");
790 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
791 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
797 if (out_buf[0] != 0x61)
799 handle->
debug_print(
"scd30: header is invalid.\n");
803 if (out_buf[1] != 0x03)
809 if (out_buf[2] != 0x02)
811 handle->
debug_print(
"scd30: number is invalid.\n");
815 *second = ((uint16_t)out_buf[3] << 8) | out_buf[4];
824 handle->
debug_print(
"scd30: get measurement interval failed.\n");
828 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
834 *second = ((uint16_t)buf[0] << 8) | buf[1];
866 uint8_t input_buf[6 + 2];
876 crc16 = a_scd30_generate_crc16(input_buf, 6);
877 input_buf[6] = (crc16 >> 0) & 0xFF;
878 input_buf[7] = (crc16 >> 8) & 0xFF;
879 memset(out_buf, 0,
sizeof(uint8_t) * 7);
880 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
883 handle->
debug_print(
"scd30: write read failed.\n");
887 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
888 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
894 if (out_buf[0] != 0x61)
896 handle->
debug_print(
"scd30: header is invalid.\n");
900 if (out_buf[1] != 0x03)
906 if (out_buf[2] != 0x02)
908 handle->
debug_print(
"scd30: number is invalid.\n");
912 *status = ((uint16_t)out_buf[3] << 8) | out_buf[4];
921 handle->
debug_print(
"scd30: get data ready status failed.\n");
925 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
931 *status = ((uint16_t)buf[0] << 8) | buf[1];
963 uint8_t input_buf[6 + 2];
964 uint8_t out_buf[6 + 2];
971 input_buf[4] = ((uint16_t)enable >> 8) & 0xFF;
972 input_buf[5] = ((uint16_t)enable >> 0) & 0xFF;
973 crc16 = a_scd30_generate_crc16(input_buf, 6);
974 input_buf[6] = (crc16 >> 0) & 0xFF;
975 input_buf[7] = (crc16 >> 8) & 0xFF;
976 memset(out_buf, 0,
sizeof(uint8_t) * 8);
977 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
980 handle->
debug_print(
"scd30: write read failed.\n");
984 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
985 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
991 if (memcmp(input_buf, out_buf, 8) != 0)
993 handle->
debug_print(
"scd30: response check error.\n");
1002 buf[0] = ((uint16_t)enable >> 8) & 0xFF;
1003 buf[1] = ((uint16_t)enable >> 0) & 0xFF;
1004 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
1008 handle->
debug_print(
"scd30: set auto self calibration failed.\n");
1043 uint8_t input_buf[6 + 2];
1047 input_buf[0] = 0x61;
1048 input_buf[1] = 0x03;
1051 input_buf[4] = 0x00;
1052 input_buf[5] = 0x01;
1053 crc16 = a_scd30_generate_crc16(input_buf, 6);
1054 input_buf[6] = (crc16 >> 0) & 0xFF;
1055 input_buf[7] = (crc16 >> 8) & 0xFF;
1056 memset(out_buf, 0,
sizeof(uint8_t) * 7);
1057 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
1060 handle->
debug_print(
"scd30: write read failed.\n");
1064 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
1065 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
1071 if (out_buf[0] != 0x61)
1073 handle->
debug_print(
"scd30: header is invalid.\n");
1077 if (out_buf[1] != 0x03)
1083 if (out_buf[2] != 0x02)
1085 handle->
debug_print(
"scd30: number is invalid.\n");
1089 *enable = (
scd30_bool_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]);
1098 handle->
debug_print(
"scd30: get auto self calibration failed.\n");
1102 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
1104 handle->
debug_print(
"scd30: crc check failed.\n");
1108 *enable = (
scd30_bool_t)(((uint16_t)buf[0] << 8) | buf[1]);
1138 if ((co2_ppm < 400) || (co2_ppm > 2000))
1140 handle->
debug_print(
"scd30: co2_ppm is invalid.\n");
1147 uint8_t input_buf[6 + 2];
1148 uint8_t out_buf[6 + 2];
1151 input_buf[0] = 0x61;
1152 input_buf[1] = 0x06;
1155 input_buf[4] = (co2_ppm >> 8) & 0xFF;
1156 input_buf[5] = (co2_ppm >> 0) & 0xFF;
1157 crc16 = a_scd30_generate_crc16(input_buf, 6);
1158 input_buf[6] = (crc16 >> 0) & 0xFF;
1159 input_buf[7] = (crc16 >> 8) & 0xFF;
1160 memset(out_buf, 0,
sizeof(uint8_t) * 8);
1161 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
1164 handle->
debug_print(
"scd30: write read failed.\n");
1168 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
1169 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
1175 if (memcmp(input_buf, out_buf, 8) != 0)
1177 handle->
debug_print(
"scd30: response check error.\n");
1186 buf[0] = (co2_ppm >> 8) & 0xFF;
1187 buf[1] = (co2_ppm >> 0) & 0xFF;
1188 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
1192 handle->
debug_print(
"scd30: set forced recalibration failed.\n");
1227 uint8_t input_buf[6 + 2];
1231 input_buf[0] = 0x61;
1232 input_buf[1] = 0x03;
1235 input_buf[4] = 0x00;
1236 input_buf[5] = 0x01;
1237 crc16 = a_scd30_generate_crc16(input_buf, 6);
1238 input_buf[6] = (crc16 >> 0) & 0xFF;
1239 input_buf[7] = (crc16 >> 8) & 0xFF;
1240 memset(out_buf, 0,
sizeof(uint8_t) * 7);
1241 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
1244 handle->
debug_print(
"scd30: write read failed.\n");
1248 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
1249 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
1255 if (out_buf[0] != 0x61)
1257 handle->
debug_print(
"scd30: header is invalid.\n");
1261 if (out_buf[1] != 0x03)
1267 if (out_buf[2] != 0x02)
1269 handle->
debug_print(
"scd30: number is invalid.\n");
1273 *co2_ppm = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]);
1282 handle->
debug_print(
"scd30: set forced recalibration failed.\n");
1286 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
1288 handle->
debug_print(
"scd30: crc check failed.\n");
1292 *co2_ppm = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]);
1324 uint8_t input_buf[6 + 2];
1325 uint8_t out_buf[6 + 2];
1328 input_buf[0] = 0x61;
1329 input_buf[1] = 0x06;
1332 input_buf[4] = (deg >> 8) & 0xFF;
1333 input_buf[5] = (deg >> 0) & 0xFF;
1334 crc16 = a_scd30_generate_crc16(input_buf, 6);
1335 input_buf[6] = (crc16 >> 0) & 0xFF;
1336 input_buf[7] = (crc16 >> 8) & 0xFF;
1337 memset(out_buf, 0,
sizeof(uint8_t) * 8);
1338 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
1341 handle->
debug_print(
"scd30: write read failed.\n");
1345 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
1346 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
1352 if (memcmp(input_buf, out_buf, 8) != 0)
1354 handle->
debug_print(
"scd30: response check error.\n");
1363 buf[0] = (deg >> 8) & 0xFF;
1364 buf[1] = (deg >> 0) & 0xFF;
1365 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
1369 handle->
debug_print(
"scd30: set temperature offset failed.\n");
1404 uint8_t input_buf[6 + 2];
1408 input_buf[0] = 0x61;
1409 input_buf[1] = 0x03;
1412 input_buf[4] = 0x00;
1413 input_buf[5] = 0x01;
1414 crc16 = a_scd30_generate_crc16(input_buf, 6);
1415 input_buf[6] = (crc16 >> 0) & 0xFF;
1416 input_buf[7] = (crc16 >> 8) & 0xFF;
1417 memset(out_buf, 0,
sizeof(uint8_t) * 7);
1418 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
1421 handle->
debug_print(
"scd30: write read failed.\n");
1425 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
1426 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
1432 if (out_buf[0] != 0x61)
1434 handle->
debug_print(
"scd30: header is invalid.\n");
1438 if (out_buf[1] != 0x03)
1444 if (out_buf[2] != 0x02)
1446 handle->
debug_print(
"scd30: number is invalid.\n");
1450 *deg = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]);
1459 handle->
debug_print(
"scd30: set temperature offset failed.\n");
1463 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
1465 handle->
debug_print(
"scd30: crc check failed.\n");
1469 *deg = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]);
1497 *reg = (uint8_t)(deg * 100.0f);
1524 *deg = (float)(reg) / 100.0f;
1555 uint8_t input_buf[6 + 2];
1556 uint8_t out_buf[6 + 2];
1559 input_buf[0] = 0x61;
1560 input_buf[1] = 0x06;
1563 input_buf[4] = (m >> 8) & 0xFF;
1564 input_buf[5] = (m >> 0) & 0xFF;
1565 crc16 = a_scd30_generate_crc16(input_buf, 6);
1566 input_buf[6] = (crc16 >> 0) & 0xFF;
1567 input_buf[7] = (crc16 >> 8) & 0xFF;
1568 memset(out_buf, 0,
sizeof(uint8_t) * 8);
1569 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
1572 handle->
debug_print(
"scd30: write read failed.\n");
1576 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
1577 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
1583 if (memcmp(input_buf, out_buf, 8) != 0)
1585 handle->
debug_print(
"scd30: response check error.\n");
1594 buf[0] = (m >> 8) & 0xFF;
1595 buf[1] = (m >> 0) & 0xFF;
1596 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2);
1600 handle->
debug_print(
"scd30: set altitude failed.\n");
1635 uint8_t input_buf[6 + 2];
1639 input_buf[0] = 0x61;
1640 input_buf[1] = 0x03;
1643 input_buf[4] = 0x00;
1644 input_buf[5] = 0x01;
1645 crc16 = a_scd30_generate_crc16(input_buf, 6);
1646 input_buf[6] = (crc16 >> 0) & 0xFF;
1647 input_buf[7] = (crc16 >> 8) & 0xFF;
1648 memset(out_buf, 0,
sizeof(uint8_t) * 7);
1649 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
1652 handle->
debug_print(
"scd30: write read failed.\n");
1656 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
1657 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
1663 if (out_buf[0] != 0x61)
1665 handle->
debug_print(
"scd30: header is invalid.\n");
1669 if (out_buf[1] != 0x03)
1675 if (out_buf[2] != 0x02)
1677 handle->
debug_print(
"scd30: number is invalid.\n");
1681 *m = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]);
1690 handle->
debug_print(
"scd30: set altitude failed.\n");
1694 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
1696 handle->
debug_print(
"scd30: crc check failed.\n");
1700 *m = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]);
1732 uint8_t input_buf[6 + 2];
1736 input_buf[0] = 0x61;
1737 input_buf[1] = 0x03;
1740 input_buf[4] = 0x00;
1741 input_buf[5] = 0x01;
1742 crc16 = a_scd30_generate_crc16(input_buf, 6);
1743 input_buf[6] = (crc16 >> 0) & 0xFF;
1744 input_buf[7] = (crc16 >> 8) & 0xFF;
1745 memset(out_buf, 0,
sizeof(uint8_t) * 7);
1746 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7);
1749 handle->
debug_print(
"scd30: write read failed.\n");
1753 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]);
1754 if (crc16 != a_scd30_generate_crc16(out_buf, 5))
1760 if (out_buf[0] != 0x61)
1762 handle->
debug_print(
"scd30: header is invalid.\n");
1766 if (out_buf[1] != 0x03)
1772 if (out_buf[2] != 0x02)
1774 handle->
debug_print(
"scd30: number is invalid.\n");
1778 *version = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]);
1787 handle->
debug_print(
"scd30: read firmware version failed.\n");
1791 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2))
1793 handle->
debug_print(
"scd30: crc check failed.\n");
1797 *version = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]);
1828 uint8_t input_buf[6 + 2];
1829 uint8_t out_buf[6 + 2];
1832 input_buf[0] = 0x61;
1833 input_buf[1] = 0x06;
1836 input_buf[4] = 0x00;
1837 input_buf[5] = 0x01;
1838 crc16 = a_scd30_generate_crc16(input_buf, 6);
1839 input_buf[6] = (crc16 >> 0) & 0xFF;
1840 input_buf[7] = (crc16 >> 8) & 0xFF;
1841 memset(out_buf, 0,
sizeof(uint8_t) * 8);
1842 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
1845 handle->
debug_print(
"scd30: write read failed.\n");
1849 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
1850 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
1856 if (memcmp(input_buf, out_buf, 8) != 0)
1858 handle->
debug_print(
"scd30: response check error.\n");
1868 handle->
debug_print(
"scd30: soft reset failed.\n");
1900 uint32_t timeout = 5000;
1902 if ((handle == NULL) || (data == NULL))
1911 while (timeout != 0)
1913 res = a_scd30_get_data_ready_status(handle, &status);
1916 handle->
debug_print(
"scd30: get data ready status failed.\n");
1936 uint8_t input_buf[6 + 2];
1937 uint8_t out_buf[17];
1940 input_buf[0] = 0x61;
1941 input_buf[1] = 0x03;
1944 input_buf[4] = 0x00;
1945 input_buf[5] = 0x06;
1946 crc16 = a_scd30_generate_crc16(input_buf, 6);
1947 input_buf[6] = (crc16 >> 0) & 0xFF;
1948 input_buf[7] = (crc16 >> 8) & 0xFF;
1949 memset(out_buf, 0,
sizeof(uint8_t) * 17);
1950 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 17);
1953 handle->
debug_print(
"scd30: write read failed.\n");
1957 crc16 = ((uint16_t)out_buf[16] << 8 | (uint16_t)out_buf[15]);
1958 if (crc16 != a_scd30_generate_crc16(out_buf, 15))
1964 if (out_buf[0] != 0x61)
1966 handle->
debug_print(
"scd30: header is invalid.\n");
1970 if (out_buf[1] != 0x03)
1976 if (out_buf[2] != 0x0C)
1978 handle->
debug_print(
"scd30: number is invalid.\n");
1982 prev.i = ((uint32_t)out_buf[3] << 24) | ((uint32_t)out_buf[4] << 16) |
1983 ((uint32_t)out_buf[5] << 8) | ((uint32_t)out_buf[6] << 0);
1986 prev.i = ((uint32_t)out_buf[7] << 24) | ((uint32_t)out_buf[8] << 16) |
1987 ((uint32_t)out_buf[9] << 8) | ((uint32_t)out_buf[10] << 0);
1990 prev.i = ((uint32_t)out_buf[11] << 24) | ((uint32_t)out_buf[12] << 16) |
1991 ((uint32_t)out_buf[13] << 8) | ((uint32_t)out_buf[14] << 0);
2002 handle->
debug_print(
"scd30: read measurement failed.\n");
2006 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf + 0, 2))
2008 handle->
debug_print(
"scd30: crc check failed.\n");
2012 if (buf[5] != a_scd30_generate_crc8((uint8_t *)buf + 3, 2))
2014 handle->
debug_print(
"scd30: crc check failed.\n");
2018 if (buf[8] != a_scd30_generate_crc8((uint8_t *)buf + 6, 2))
2020 handle->
debug_print(
"scd30: crc check failed.\n");
2024 if (buf[11] != a_scd30_generate_crc8((uint8_t *)buf + 9, 2))
2026 handle->
debug_print(
"scd30: crc check failed.\n");
2030 if (buf[14] != a_scd30_generate_crc8((uint8_t *)buf + 12, 2))
2032 handle->
debug_print(
"scd30: crc check failed.\n");
2036 if (buf[17] != a_scd30_generate_crc8((uint8_t *)buf + 15, 2))
2038 handle->
debug_print(
"scd30: crc check failed.\n");
2042 prev.i = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
2043 ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0);
2046 prev.i = ((uint32_t)buf[6] << 24) | ((uint32_t)buf[7] << 16) |
2047 ((uint32_t)buf[9] << 8) | ((uint32_t)buf[10] << 0);
2050 prev.i = ((uint32_t)buf[12] << 24) | ((uint32_t)buf[13] << 16) |
2051 ((uint32_t)buf[15] << 8) | ((uint32_t)buf[16] << 0);
2084 handle->
debug_print(
"scd30: iic_init is null.\n");
2090 handle->
debug_print(
"scd30: iic_deinit is null.\n");
2096 handle->
debug_print(
"scd30: iic_write_cmd is null.\n");
2102 handle->
debug_print(
"scd30: iic_read_cmd is null.\n");
2108 handle->
debug_print(
"scd30: uart_init is null.\n");
2114 handle->
debug_print(
"scd30: uart_deinit is null.\n");
2120 handle->
debug_print(
"scd30: uart_read is null.\n");
2126 handle->
debug_print(
"scd30: uart_write is null.\n");
2132 handle->
debug_print(
"scd30: uart_flush is null.\n");
2138 handle->
debug_print(
"scd30: delay_ms is null.\n");
2145 uint8_t input_buf[6 + 2];
2146 uint8_t out_buf[6 + 2];
2151 handle->
debug_print(
"scd30: uart init failed.\n");
2156 input_buf[0] = 0x61;
2157 input_buf[1] = 0x06;
2160 input_buf[4] = 0x00;
2161 input_buf[5] = 0x01;
2162 crc16 = a_scd30_generate_crc16(input_buf, 6);
2163 input_buf[6] = (crc16 >> 0) & 0xFF;
2164 input_buf[7] = (crc16 >> 8) & 0xFF;
2165 memset(out_buf, 0,
sizeof(uint8_t) * 8);
2166 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
2169 handle->
debug_print(
"scd30: write read failed.\n");
2173 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
2174 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
2180 if (memcmp(input_buf, out_buf, 8) != 0)
2182 handle->
debug_print(
"scd30: response check error.\n");
2198 handle->
debug_print(
"scd30: soft reset failed.\n");
2235 uint8_t input_buf[6 + 2];
2236 uint8_t out_buf[6 + 2];
2239 input_buf[0] = 0x61;
2240 input_buf[1] = 0x06;
2243 input_buf[4] = 0x00;
2244 input_buf[5] = 0x01;
2245 crc16 = a_scd30_generate_crc16(input_buf, 6);
2246 input_buf[6] = (crc16 >> 0) & 0xFF;
2247 input_buf[7] = (crc16 >> 8) & 0xFF;
2248 memset(out_buf, 0,
sizeof(uint8_t) * 8);
2249 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8);
2252 handle->
debug_print(
"scd30: write read failed.\n");
2256 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]);
2257 if (crc16 != a_scd30_generate_crc16(out_buf, 6))
2263 if (memcmp(input_buf, out_buf, 8) != 0)
2265 handle->
debug_print(
"scd30: response check error.\n");
2271 handle->
debug_print(
"scd30: uart deinit failed.\n");
2281 handle->
debug_print(
"scd30: soft reset failed.\n");
2288 handle->
debug_print(
"scd30: iic deinit failed.\n");
2324 return a_scd30_uart_write_read(handle, input, in_len, 50, output, out_len);
2328 handle->
debug_print(
"scd30: iic interface is invalid.\n");
2360 handle->
debug_print(
"scd30: uart interface is invalid.\n");
2366 return a_scd30_iic_write(handle, reg, buf, len, 20);
2396 handle->
debug_print(
"scd30: uart interface is invalid.\n");
2402 return a_scd30_iic_read(handle, reg, buf, len, 20);
2424 strncpy(info->
interface,
"UART IIC", 16);
#define SCD30_IIC_COMMAND_START_PERIODIC_MEASUREMENT
chip command definition
#define SCD30_UART_ADDRESS_SET_FORCED_RECALIBRATION
#define SCD30_UART_ADDRESS_GET_DATA_READY_STATUS
#define SCD30_IIC_COMMAND_SOFT_RESET
#define SCD30_UART_ADDRESS_SET_ALTITUDE
#define SCD30_ADDRESS
chip address definition
#define SCD30_UART_ADDRESS_START_PERIODIC_MEASUREMENT
#define SCD30_UART_ADDRESS_STOP_PERIODIC_MEASUREMENT
#define SCD30_IIC_COMMAND_SET_TEMPERATURE_OFFSET
#define SCD30_IIC_COMMAND_READ_MEASUREMENT
#define SCD30_IIC_COMMAND_GET_DATA_READY_STATUS
#define SUPPLY_VOLTAGE_MAX
#define SCD30_IIC_COMMAND_SET_MEASUREMENT_INTERVAL
#define SCD30_IIC_COMMAND_AUTO_SELF_CALIBRATION
#define SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL
#define SCD30_UART_ADDRESS_READ_FIRMWARE_VERSION
#define SCD30_UART_ADDRESS_SOFT_RESET
#define MANUFACTURER_NAME
#define SUPPLY_VOLTAGE_MIN
#define SCD30_UART_ADDRESS_AUTO_SELF_CALIBRATION
#define SCD30_IIC_COMMAND_SET_ALTITUDE
#define SCD30_IIC_COMMAND_STOP_PERIODIC_MEASUREMENT
#define SCD30_UART_ADDRESS_READ_MEASUREMENT
#define SCD30_UART_ADDRESS_SET_TEMPERATURE_OFFSET
#define CHIP_NAME
chip information definition
#define SCD30_IIC_COMMAND_SET_FORCED_RECALIBRATION
#define SCD30_IIC_COMMAND_READ_FIRMWARE_VERSION
uint8_t scd30_init(scd30_handle_t *handle)
initialize the chip
struct scd30_info_s scd30_info_t
scd30 information structure definition
uint8_t scd30_deinit(scd30_handle_t *handle)
close the chip
struct scd30_data_s scd30_data_t
scd30 data structure definition
uint8_t scd30_temperature_offset_convert_to_data(scd30_handle_t *handle, uint16_t reg, float *deg)
convert the register raw data to the temperature offset
uint8_t scd30_stop_measurement(scd30_handle_t *handle)
stop the measurement
uint8_t scd30_set_altitude_compensation(scd30_handle_t *handle, uint16_t m)
set altitude compensation
uint8_t scd30_soft_reset(scd30_handle_t *handle)
soft reset
uint8_t scd30_get_forced_recalibration(scd30_handle_t *handle, uint16_t *co2_ppm)
get forced recalibration
uint8_t scd30_get_data_ready_status(scd30_handle_t *handle, uint16_t *status)
get data ready status
uint8_t scd30_read(scd30_handle_t *handle, scd30_data_t *data)
read the result
uint8_t scd30_get_temperature_offset(scd30_handle_t *handle, uint16_t *deg)
get temperature offset
uint8_t scd30_temperature_offset_convert_to_register(scd30_handle_t *handle, float deg, uint16_t *reg)
convert the temperature offset to the register raw data
scd30_interface_t
scd30 interface enumeration definition
uint8_t scd30_get_firmware_version(scd30_handle_t *handle, uint16_t *version)
get firmware version
uint8_t scd30_get_automatic_self_calibration(scd30_handle_t *handle, scd30_bool_t *enable)
get automatic self calibration
uint8_t scd30_set_interface(scd30_handle_t *handle, scd30_interface_t interface)
set the chip interface
uint8_t scd30_set_automatic_self_calibration(scd30_handle_t *handle, scd30_bool_t enable)
set automatic self calibration
uint8_t scd30_start_measurement(scd30_handle_t *handle)
start the measurement
uint8_t scd30_info(scd30_info_t *info)
get chip information
uint8_t scd30_set_temperature_offset(scd30_handle_t *handle, uint16_t deg)
set temperature offset
uint8_t scd30_get_interface(scd30_handle_t *handle, scd30_interface_t *interface)
get the chip interface
struct scd30_handle_s scd30_handle_t
scd30 handle structure definition
uint8_t scd30_set_forced_recalibration(scd30_handle_t *handle, uint16_t co2_ppm)
set forced recalibration
uint8_t scd30_set_measurement_interval(scd30_handle_t *handle, uint16_t second)
set the measurement interval
uint8_t scd30_get_measurement_interval(scd30_handle_t *handle, uint16_t *second)
get the measurement interval
uint8_t scd30_start_measurement_with_pressure_compensation(scd30_handle_t *handle, uint16_t mbar)
start the measurement with pressure compensation
uint8_t scd30_get_altitude_compensation(scd30_handle_t *handle, uint16_t *m)
get altitude compensation
scd30_bool_t
scd30 bool enumeration definition
uint8_t scd30_set_get_reg_uart(scd30_handle_t *handle, uint8_t *input, uint16_t in_len, uint8_t *output, uint16_t out_len)
set and get the chip register with uart interface
uint8_t scd30_get_reg_iic(scd30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
get the chip register with iic interface
uint8_t scd30_set_reg_iic(scd30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
set the chip register with iic interface
uint8_t(* uart_flush)(void)
uint8_t(* uart_write)(uint8_t *buf, uint16_t len)
void(* delay_ms)(uint32_t ms)
uint8_t(* uart_deinit)(void)
void(* debug_print)(const char *const fmt,...)
uint8_t(* iic_init)(void)
uint16_t(* uart_read)(uint8_t *buf, uint16_t len)
uint8_t(* iic_read_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
uint8_t(* uart_init)(void)
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