LibDriver SCD30
Loading...
Searching...
No Matches
driver_scd30.c
Go to the documentation of this file.
1
36
37#include "driver_scd30.h"
38
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
50
54#define SCD30_ADDRESS 0xC2
55
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
81
85static const uint8_t gs_crc_table_hi[] =
86{
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
106};
107
111static const uint8_t gs_crc_table_lo[] =
112{
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
132};
133
141static uint16_t a_scd30_generate_crc16(uint8_t *data, uint16_t count)
142{
143 uint8_t crc_hi = 0xFF;
144 uint8_t crc_lo = 0xFF;
145 uint8_t i;
146
147 while (count--) /* count-- */
148 {
149 i = crc_lo ^ *data++; /* get index */
150 crc_lo = crc_hi ^ gs_crc_table_hi[i]; /* get crc lo */
151 crc_hi = gs_crc_table_lo[i]; /* get crc hi */
152 }
153
154 return ((uint16_t)crc_hi << 8 | crc_lo); /* return crc16 */
155}
156
164static uint8_t a_scd30_generate_crc8(uint8_t *data, uint8_t count)
165{
166 uint8_t current_byte;
167 uint8_t crc = 0xFF;
168 uint8_t crc_bit;
169
170 for (current_byte = 0; current_byte < count; ++current_byte) /* calculate crc */
171 {
172 crc ^= (data[current_byte]); /* xor data */
173 for (crc_bit = 8; crc_bit > 0; --crc_bit) /* 8 bit */
174 {
175 if ((crc & 0x80) != 0) /* if 7th bit is 1 */
176 {
177 crc = (crc << 1) ^ 0x31; /* xor */
178 }
179 else
180 {
181 crc = crc << 1; /* left shift 1 */
182 }
183 }
184 }
185
186 return crc; /* return crc */
187}
188
201static uint8_t a_scd30_iic_read(scd30_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
202{
203 uint8_t buf[2];
204
205 buf[0] = (reg >> 8) & 0xFF; /* set msb */
206 buf[1] = (reg >> 0) & 0xFF; /* set lsb */
207 if (handle->iic_write_cmd(SCD30_ADDRESS, (uint8_t *)buf, 2) != 0) /* write data */
208 {
209 return 1; /* return error */
210 }
211 handle->delay_ms(delay_ms); /* delay ms */
212 if (handle->iic_read_cmd(SCD30_ADDRESS, (uint8_t *)data, len) != 0) /* read data */
213 {
214 return 1; /* return error */
215 }
216
217 return 0; /* success return 0 */
218}
219
232static uint8_t a_scd30_iic_write(scd30_handle_t *handle, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
233{
234 uint8_t buf[16];
235
236 if (len > 14) /* check length */
237 {
238 return 1; /* return error */
239 }
240 buf[0] = (reg >> 8) & 0xFF; /* set msb */
241 buf[1] = (reg >> 0) & 0xFF; /* set lsb */
242 memcpy((uint8_t *)&buf[2], data, len); /* copy data */
243 if (handle->iic_write_cmd(SCD30_ADDRESS, (uint8_t *)buf, len + 2) != 0) /* write data */
244 {
245 return 1; /* return error */
246 }
247 handle->delay_ms(delay_ms); /* delay ms */
248
249 return 0; /* success return 0 */
250}
251
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)
267{
268 uint16_t len;
269
270 if (handle->uart_flush() != 0) /* uart flush */
271 {
272 return 1; /* return error */
273 }
274 if (handle->uart_write(input, in_len) != 0) /* write data */
275 {
276 return 1; /* return error */
277 }
278 handle->delay_ms(delay_ms); /* delay ms */
279 len = handle->uart_read(output, out_len); /* read data */
280 if (len != out_len) /* check the result */
281 {
282 return 1; /* return error */
283 }
284
285 return 0; /* success return 0 */
286}
287
297static uint8_t a_scd30_get_data_ready_status(scd30_handle_t *handle, uint16_t *status)
298{
299 uint8_t res;
300
301 if (handle->iic_uart != 0) /* uart */
302 {
303 uint8_t input_buf[6 + 2];
304 uint8_t out_buf[7];
305 uint16_t crc16;
306
307 input_buf[0] = 0x61; /* set slave address */
308 input_buf[1] = 0x03; /* set function code */
309 input_buf[2] = (SCD30_UART_ADDRESS_GET_DATA_READY_STATUS >> 8) & 0xFF; /* set addr msb */
310 input_buf[3] = (SCD30_UART_ADDRESS_GET_DATA_READY_STATUS >> 0) & 0xFF; /* set addr lsb */
311 input_buf[4] = 0x00; /* set 0x00 */
312 input_buf[5] = 0x01; /* set 0x01 */
313 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
314 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
315 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
316 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
317 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
318 if (res != 0) /* check result */
319 {
320 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
321
322 return 1; /* return error */
323 }
324 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
325 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
326 {
327 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
328
329 return 1; /* return error */
330 }
331 if (out_buf[0] != 0x61) /* check header */
332 {
333 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
334
335 return 1; /* return error */
336 }
337 if (out_buf[1] != 0x03) /* check code */
338 {
339 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
340
341 return 1; /* return error */
342 }
343 if (out_buf[2] != 0x02) /* check number */
344 {
345 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
346
347 return 1; /* return error */
348 }
349 *status = ((uint16_t)out_buf[3] << 8) | out_buf[4]; /* get status */
350 }
351 else /* iic */
352 {
353 uint8_t buf[3];
354
355 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_GET_DATA_READY_STATUS, (uint8_t *)buf, 3, 20); /* get data ready status command */
356 if (res != 0) /* check result */
357 {
358 handle->debug_print("scd30: get data ready status failed.\n"); /* get data ready status failed */
359
360 return 1; /* return error */
361 }
362 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
363 {
364 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
365
366 return 1; /* return error */
367 }
368 *status = ((uint16_t)buf[0] << 8) | buf[1]; /* get status */
369 }
370
371 return 0; /* success return 0 */
372}
373
384{
385 if (handle == NULL) /* check handle */
386 {
387 return 2; /* return error */
388 }
389
390 handle->iic_uart = (uint8_t)interface; /* set interface */
391
392 return 0; /* success return 0 */
393}
394
405{
406 if (handle == NULL) /* check handle */
407 {
408 return 2; /* return error */
409 }
410
411 *interface = (scd30_interface_t)(handle->iic_uart); /* get interface */
412
413 return 0; /* success return 0 */
414}
415
429{
430 uint8_t res;
431
432 if (handle == NULL) /* check handle */
433 {
434 return 2; /* return error */
435 }
436 if (handle->inited != 1) /* check handle initialization */
437 {
438 return 3; /* return error */
439 }
440 if ((mbar < 700) || (mbar > 1400)) /* check mbar range */
441 {
442 handle->debug_print("scd30: mbar is invalid.\n"); /* mbar is invalid */
443
444 return 4; /* return error */
445 }
446
447 if (handle->iic_uart != 0) /* uart */
448 {
449 uint8_t input_buf[6 + 2];
450 uint8_t out_buf[6 + 2];
451 uint16_t crc16;
452
453 input_buf[0] = 0x61; /* set slave address */
454 input_buf[1] = 0x06; /* set function code */
455 input_buf[2] = (SCD30_UART_ADDRESS_START_PERIODIC_MEASUREMENT >> 8) & 0xFF; /* set addr msb */
456 input_buf[3] = (SCD30_UART_ADDRESS_START_PERIODIC_MEASUREMENT >> 0) & 0xFF; /* set addr lsb */
457 input_buf[4] = (mbar >> 8) & 0xFF; /* set mbar msb */
458 input_buf[5] = (mbar >> 0) & 0xFF; /* set mbar lsb */
459 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
460 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
461 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
462 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
463 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
464 if (res != 0) /* check result */
465 {
466 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
467
468 return 1; /* return error */
469 }
470 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
471 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
472 {
473 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
474
475 return 1; /* return error */
476 }
477 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
478 {
479 handle->debug_print("scd30: response check error.\n"); /* response check error */
480
481 return 1; /* return error */
482 }
483 }
484 else /* iic */
485 {
486 uint8_t buf[3];
487
488 buf[0] = (mbar >> 8) & 0xFF; /* set mbar msb */
489 buf[1] = (mbar >> 0) & 0xFF; /* set mbar lsb */
490 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
491 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_START_PERIODIC_MEASUREMENT, (uint8_t *)buf, 3, 20); /* start measurement command */
492 if (res != 0) /* check result */
493 {
494 handle->debug_print("scd30: start measurement failed.\n"); /* start measurement failed */
495
496 return 1; /* return error */
497 }
498 }
499
500 return 0; /* success return 0 */
501}
502
514{
515 uint8_t res;
516
517 if (handle == NULL) /* check handle */
518 {
519 return 2; /* return error */
520 }
521 if (handle->inited != 1) /* check handle initialization */
522 {
523 return 3; /* return error */
524 }
525
526 if (handle->iic_uart != 0) /* uart */
527 {
528 uint8_t input_buf[6 + 2];
529 uint8_t out_buf[6 + 2];
530 uint16_t crc16;
531
532 input_buf[0] = 0x61; /* set slave address */
533 input_buf[1] = 0x06; /* set function code */
534 input_buf[2] = (SCD30_UART_ADDRESS_START_PERIODIC_MEASUREMENT >> 8) & 0xFF; /* set addr msb */
535 input_buf[3] = (SCD30_UART_ADDRESS_START_PERIODIC_MEASUREMENT >> 0) & 0xFF; /* set addr lsb */
536 input_buf[4] = 0x00; /* set 0x00 */
537 input_buf[5] = 0x00; /* set 0x00 */
538 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
539 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
540 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
541 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
542 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
543 if (res != 0) /* check result */
544 {
545 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
546
547 return 1; /* return error */
548 }
549 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
550 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
551 {
552 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
553
554 return 1; /* return error */
555 }
556 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
557 {
558 handle->debug_print("scd30: response check error.\n"); /* response check error */
559
560 return 1; /* return error */
561 }
562 }
563 else /* iic */
564 {
565 uint8_t buf[3];
566
567 buf[0] = 0x00; /* set 0x00 */
568 buf[1] = 0x00; /* set 0x00 */
569 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
570 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_START_PERIODIC_MEASUREMENT, (uint8_t *)buf, 3, 20); /* start measurement command */
571 if (res != 0) /* check result */
572 {
573 handle->debug_print("scd30: start measurement failed.\n"); /* start measurement failed */
574
575 return 1; /* return error */
576 }
577 }
578
579 return 0; /* success return 0 */
580}
581
593{
594 uint8_t res;
595
596 if (handle == NULL) /* check handle */
597 {
598 return 2; /* return error */
599 }
600 if (handle->inited != 1) /* check handle initialization */
601 {
602 return 3; /* return error */
603 }
604
605 if (handle->iic_uart != 0) /* uart */
606 {
607 uint8_t input_buf[6 + 2];
608 uint8_t out_buf[6 + 2];
609 uint16_t crc16;
610
611 input_buf[0] = 0x61; /* set slave address */
612 input_buf[1] = 0x06; /* set function code */
613 input_buf[2] = (SCD30_UART_ADDRESS_STOP_PERIODIC_MEASUREMENT >> 8) & 0xFF; /* set addr msb */
614 input_buf[3] = (SCD30_UART_ADDRESS_STOP_PERIODIC_MEASUREMENT >> 0) & 0xFF; /* set addr lsb */
615 input_buf[4] = 0x00; /* set 0x00 */
616 input_buf[5] = 0x01; /* set 0x01 */
617 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
618 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
619 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
620 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
621 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
622 if (res != 0) /* check result */
623 {
624 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
625
626 return 1; /* return error */
627 }
628 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
629 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
630 {
631 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
632
633 return 1; /* return error */
634 }
635 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
636 {
637 handle->debug_print("scd30: response check error.\n"); /* response check error */
638
639 return 1; /* return error */
640 }
641 }
642 else /* iic */
643 {
644 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_STOP_PERIODIC_MEASUREMENT, NULL, 0, 20); /* stop measurement command */
645 if (res != 0) /* check result */
646 {
647 handle->debug_print("scd30: stop measurement failed.\n"); /* stop measurement failed */
648
649 return 1; /* return error */
650 }
651 }
652
653 return 0; /* success return 0 */
654}
655
668uint8_t scd30_set_measurement_interval(scd30_handle_t *handle, uint16_t second)
669{
670 uint8_t res;
671
672 if (handle == NULL) /* check handle */
673 {
674 return 2; /* return error */
675 }
676 if (handle->inited != 1) /* check handle initialization */
677 {
678 return 3; /* return error */
679 }
680 if ((second < 2) || (second > 1800)) /* check second range */
681 {
682 handle->debug_print("scd30: second is invalid.\n"); /* second is invalid */
683
684 return 4; /* return error */
685 }
686
687 if (handle->iic_uart != 0) /* uart */
688 {
689 uint8_t input_buf[6 + 2];
690 uint8_t out_buf[6 + 2];
691 uint16_t crc16;
692
693 input_buf[0] = 0x61; /* set slave address */
694 input_buf[1] = 0x06; /* set function code */
695 input_buf[2] = (SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL >> 8) & 0xFF; /* set addr msb */
696 input_buf[3] = (SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL >> 0) & 0xFF; /* set addr lsb */
697 input_buf[4] = (second >> 8) & 0xFF; /* set second msb */
698 input_buf[5] = (second >> 0) & 0xFF; /* set second lsb */
699 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
700 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
701 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
702 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
703 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
704 if (res != 0) /* check result */
705 {
706 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
707
708 return 1; /* return error */
709 }
710 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
711 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
712 {
713 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
714
715 return 1; /* return error */
716 }
717 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
718 {
719 handle->debug_print("scd30: response check error.\n"); /* response check error */
720
721 return 1; /* return error */
722 }
723 }
724 else /* iic */
725 {
726 uint8_t buf[3];
727
728 buf[0] = (second >> 8) & 0xFF; /* set second msb */
729 buf[1] = (second >> 0) & 0xFF; /* set second lsb */
730 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
731 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SET_MEASUREMENT_INTERVAL, (uint8_t *)buf, 3, 20); /* set measurement interval command */
732 if (res != 0) /* check result */
733 {
734 handle->debug_print("scd30: set measurement interval failed.\n"); /* set measurement interval failed */
735
736 return 1; /* return error */
737 }
738 }
739
740 return 0; /* success return 0 */
741}
742
754uint8_t scd30_get_measurement_interval(scd30_handle_t *handle, uint16_t *second)
755{
756 uint8_t res;
757
758 if (handle == NULL) /* check handle */
759 {
760 return 2; /* return error */
761 }
762 if (handle->inited != 1) /* check handle initialization */
763 {
764 return 3; /* return error */
765 }
766
767 if (handle->iic_uart != 0) /* uart */
768 {
769 uint8_t input_buf[6 + 2];
770 uint8_t out_buf[7];
771 uint16_t crc16;
772
773 input_buf[0] = 0x61; /* set slave address */
774 input_buf[1] = 0x03; /* set function code */
775 input_buf[2] = (SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL >> 8) & 0xFF; /* set addr msb */
776 input_buf[3] = (SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL >> 0) & 0xFF; /* set addr lsb */
777 input_buf[4] = 0x00; /* set 0x00 */
778 input_buf[5] = 0x01; /* set 0x01 */
779 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
780 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
781 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
782 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
783 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
784 if (res != 0) /* check result */
785 {
786 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
787
788 return 1; /* return error */
789 }
790 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
791 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
792 {
793 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
794
795 return 1; /* return error */
796 }
797 if (out_buf[0] != 0x61) /* check header */
798 {
799 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
800
801 return 1; /* return error */
802 }
803 if (out_buf[1] != 0x03) /* check code */
804 {
805 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
806
807 return 1; /* return error */
808 }
809 if (out_buf[2] != 0x02) /* check number */
810 {
811 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
812
813 return 1; /* return error */
814 }
815 *second = ((uint16_t)out_buf[3] << 8) | out_buf[4]; /* get second */
816 }
817 else /* iic */
818 {
819 uint8_t buf[3];
820
821 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_SET_MEASUREMENT_INTERVAL, (uint8_t *)buf, 3, 20); /* get measurement interval command */
822 if (res != 0) /* check result */
823 {
824 handle->debug_print("scd30: get measurement interval failed.\n"); /* get measurement interval failed */
825
826 return 1; /* return error */
827 }
828 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
829 {
830 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
831
832 return 1; /* return error */
833 }
834 *second = ((uint16_t)buf[0] << 8) | buf[1]; /* get second */
835 }
836
837 return 0; /* success return 0 */
838}
839
851uint8_t scd30_get_data_ready_status(scd30_handle_t *handle, uint16_t *status)
852{
853 uint8_t res;
854
855 if (handle == NULL) /* check handle */
856 {
857 return 2; /* return error */
858 }
859 if (handle->inited != 1) /* check handle initialization */
860 {
861 return 3; /* return error */
862 }
863
864 if (handle->iic_uart != 0) /* uart */
865 {
866 uint8_t input_buf[6 + 2];
867 uint8_t out_buf[7];
868 uint16_t crc16;
869
870 input_buf[0] = 0x61; /* set slave address */
871 input_buf[1] = 0x03; /* set function code */
872 input_buf[2] = (SCD30_UART_ADDRESS_GET_DATA_READY_STATUS >> 8) & 0xFF; /* set addr msb */
873 input_buf[3] = (SCD30_UART_ADDRESS_GET_DATA_READY_STATUS >> 0) & 0xFF; /* set addr lsb */
874 input_buf[4] = 0x00; /* set 0x00 */
875 input_buf[5] = 0x01; /* set 0x01 */
876 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
877 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
878 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
879 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
880 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
881 if (res != 0) /* check result */
882 {
883 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
884
885 return 1; /* return error */
886 }
887 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
888 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
889 {
890 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
891
892 return 1; /* return error */
893 }
894 if (out_buf[0] != 0x61) /* check header */
895 {
896 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
897
898 return 1; /* return error */
899 }
900 if (out_buf[1] != 0x03) /* check code */
901 {
902 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
903
904 return 1; /* return error */
905 }
906 if (out_buf[2] != 0x02) /* check number */
907 {
908 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
909
910 return 1; /* return error */
911 }
912 *status = ((uint16_t)out_buf[3] << 8) | out_buf[4]; /* get status */
913 }
914 else /* iic */
915 {
916 uint8_t buf[3];
917
918 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_GET_DATA_READY_STATUS, (uint8_t *)buf, 3, 20); /* get data ready status command */
919 if (res != 0) /* check result */
920 {
921 handle->debug_print("scd30: get data ready status failed.\n"); /* get data ready status failed */
922
923 return 1; /* return error */
924 }
925 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
926 {
927 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
928
929 return 1; /* return error */
930 }
931 *status = ((uint16_t)buf[0] << 8) | buf[1]; /* get status */
932 }
933
934 return 0; /* success return 0 */
935}
936
949{
950 uint8_t res;
951
952 if (handle == NULL) /* check handle */
953 {
954 return 2; /* return error */
955 }
956 if (handle->inited != 1) /* check handle initialization */
957 {
958 return 3; /* return error */
959 }
960
961 if (handle->iic_uart != 0) /* uart */
962 {
963 uint8_t input_buf[6 + 2];
964 uint8_t out_buf[6 + 2];
965 uint16_t crc16;
966
967 input_buf[0] = 0x61; /* set slave address */
968 input_buf[1] = 0x06; /* set function code */
969 input_buf[2] = (SCD30_UART_ADDRESS_AUTO_SELF_CALIBRATION >> 8) & 0xFF; /* set addr msb */
970 input_buf[3] = (SCD30_UART_ADDRESS_AUTO_SELF_CALIBRATION >> 0) & 0xFF; /* set addr lsb */
971 input_buf[4] = ((uint16_t)enable >> 8) & 0xFF; /* set bool msb */
972 input_buf[5] = ((uint16_t)enable >> 0) & 0xFF; /* set bool lsb */
973 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
974 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
975 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
976 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
977 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
978 if (res != 0) /* check result */
979 {
980 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
981
982 return 1; /* return error */
983 }
984 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
985 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
986 {
987 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
988
989 return 1; /* return error */
990 }
991 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
992 {
993 handle->debug_print("scd30: response check error.\n"); /* response check error */
994
995 return 1; /* return error */
996 }
997 }
998 else /* iic */
999 {
1000 uint8_t buf[3];
1001
1002 buf[0] = ((uint16_t)enable >> 8) & 0xFF; /* set bool msb */
1003 buf[1] = ((uint16_t)enable >> 0) & 0xFF; /* set bool lsb */
1004 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
1005 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_AUTO_SELF_CALIBRATION, (uint8_t *)buf, 3, 20); /* set auto self calibration command */
1006 if (res != 0) /* check result */
1007 {
1008 handle->debug_print("scd30: set auto self calibration failed.\n"); /* set auto self calibration failed */
1009
1010 return 1; /* return error */
1011 }
1012 }
1013
1014 return 0; /* success return 0 */
1015}
1016
1029{
1030 uint8_t res;
1031
1032 if (handle == NULL) /* check handle */
1033 {
1034 return 2; /* return error */
1035 }
1036 if (handle->inited != 1) /* check handle initialization */
1037 {
1038 return 3; /* return error */
1039 }
1040
1041 if (handle->iic_uart != 0) /* uart */
1042 {
1043 uint8_t input_buf[6 + 2];
1044 uint8_t out_buf[7];
1045 uint16_t crc16;
1046
1047 input_buf[0] = 0x61; /* set slave address */
1048 input_buf[1] = 0x03; /* set function code */
1049 input_buf[2] = (SCD30_UART_ADDRESS_AUTO_SELF_CALIBRATION >> 8) & 0xFF; /* set addr msb */
1050 input_buf[3] = (SCD30_UART_ADDRESS_AUTO_SELF_CALIBRATION >> 0) & 0xFF; /* set addr lsb */
1051 input_buf[4] = 0x00; /* set 0x00 */
1052 input_buf[5] = 0x01; /* set 0x01 */
1053 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1054 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1055 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1056 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1057 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
1058 if (res != 0) /* check result */
1059 {
1060 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1061
1062 return 1; /* return error */
1063 }
1064 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
1065 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
1066 {
1067 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1068
1069 return 1; /* return error */
1070 }
1071 if (out_buf[0] != 0x61) /* check header */
1072 {
1073 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
1074
1075 return 1; /* return error */
1076 }
1077 if (out_buf[1] != 0x03) /* check code */
1078 {
1079 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
1080
1081 return 1; /* return error */
1082 }
1083 if (out_buf[2] != 0x02) /* check number */
1084 {
1085 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
1086
1087 return 1; /* return error */
1088 }
1089 *enable = (scd30_bool_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]); /* get bool */
1090 }
1091 else /* iic */
1092 {
1093 uint8_t buf[3];
1094
1095 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_AUTO_SELF_CALIBRATION, (uint8_t *)buf, 3, 20); /* get auto self calibration command */
1096 if (res != 0) /* check result */
1097 {
1098 handle->debug_print("scd30: get auto self calibration failed.\n"); /* get auto self calibration failed */
1099
1100 return 1; /* return error */
1101 }
1102 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
1103 {
1104 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
1105
1106 return 1; /* return error */
1107 }
1108 *enable = (scd30_bool_t)(((uint16_t)buf[0] << 8) | buf[1]); /* get bool */
1109 }
1110
1111 return 0; /* success return 0 */
1112}
1113
1126uint8_t scd30_set_forced_recalibration(scd30_handle_t *handle, uint16_t co2_ppm)
1127{
1128 uint8_t res;
1129
1130 if (handle == NULL) /* check handle */
1131 {
1132 return 2; /* return error */
1133 }
1134 if (handle->inited != 1) /* check handle initialization */
1135 {
1136 return 3; /* return error */
1137 }
1138 if ((co2_ppm < 400) || (co2_ppm > 2000)) /* check co2_ppm range */
1139 {
1140 handle->debug_print("scd30: co2_ppm is invalid.\n"); /* co2_ppm is invalid */
1141
1142 return 4; /* return error */
1143 }
1144
1145 if (handle->iic_uart != 0) /* uart */
1146 {
1147 uint8_t input_buf[6 + 2];
1148 uint8_t out_buf[6 + 2];
1149 uint16_t crc16;
1150
1151 input_buf[0] = 0x61; /* set slave address */
1152 input_buf[1] = 0x06; /* set function code */
1153 input_buf[2] = (SCD30_UART_ADDRESS_SET_FORCED_RECALIBRATION >> 8) & 0xFF; /* set addr msb */
1154 input_buf[3] = (SCD30_UART_ADDRESS_SET_FORCED_RECALIBRATION >> 0) & 0xFF; /* set addr lsb */
1155 input_buf[4] = (co2_ppm >> 8) & 0xFF; /* set ppm msb */
1156 input_buf[5] = (co2_ppm >> 0) & 0xFF; /* set ppm lsb */
1157 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1158 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1159 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1160 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
1161 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
1162 if (res != 0) /* check result */
1163 {
1164 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1165
1166 return 1; /* return error */
1167 }
1168 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
1169 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
1170 {
1171 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1172
1173 return 1; /* return error */
1174 }
1175 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
1176 {
1177 handle->debug_print("scd30: response check error.\n"); /* response check error */
1178
1179 return 1; /* return error */
1180 }
1181 }
1182 else /* iic */
1183 {
1184 uint8_t buf[3];
1185
1186 buf[0] = (co2_ppm >> 8) & 0xFF; /* set ppm msb */
1187 buf[1] = (co2_ppm >> 0) & 0xFF; /* set ppm lsb */
1188 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
1189 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SET_FORCED_RECALIBRATION, (uint8_t *)buf, 3, 20); /* set forced recalibration command */
1190 if (res != 0) /* check result */
1191 {
1192 handle->debug_print("scd30: set forced recalibration failed.\n"); /* set forced recalibration failed */
1193
1194 return 1; /* return error */
1195 }
1196 }
1197
1198 return 0; /* success return 0 */
1199}
1200
1212uint8_t scd30_get_forced_recalibration(scd30_handle_t *handle, uint16_t *co2_ppm)
1213{
1214 uint8_t res;
1215
1216 if (handle == NULL) /* check handle */
1217 {
1218 return 2; /* return error */
1219 }
1220 if (handle->inited != 1) /* check handle initialization */
1221 {
1222 return 3; /* return error */
1223 }
1224
1225 if (handle->iic_uart != 0) /* uart */
1226 {
1227 uint8_t input_buf[6 + 2];
1228 uint8_t out_buf[7];
1229 uint16_t crc16;
1230
1231 input_buf[0] = 0x61; /* set slave address */
1232 input_buf[1] = 0x03; /* set function code */
1233 input_buf[2] = (SCD30_UART_ADDRESS_SET_FORCED_RECALIBRATION >> 8) & 0xFF; /* set addr msb */
1234 input_buf[3] = (SCD30_UART_ADDRESS_SET_FORCED_RECALIBRATION >> 0) & 0xFF; /* set addr lsb */
1235 input_buf[4] = 0x00; /* set 0x00 */
1236 input_buf[5] = 0x01; /* set 0x01 */
1237 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1238 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1239 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1240 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1241 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
1242 if (res != 0) /* check result */
1243 {
1244 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1245
1246 return 1; /* return error */
1247 }
1248 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
1249 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
1250 {
1251 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1252
1253 return 1; /* return error */
1254 }
1255 if (out_buf[0] != 0x61) /* check header */
1256 {
1257 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
1258
1259 return 1; /* return error */
1260 }
1261 if (out_buf[1] != 0x03) /* check code */
1262 {
1263 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
1264
1265 return 1; /* return error */
1266 }
1267 if (out_buf[2] != 0x02) /* check number */
1268 {
1269 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
1270
1271 return 1; /* return error */
1272 }
1273 *co2_ppm = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]); /* get co2_ppm */
1274 }
1275 else /* iic */
1276 {
1277 uint8_t buf[3];
1278
1279 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_SET_FORCED_RECALIBRATION, (uint8_t *)buf, 3, 20); /* set forced recalibration command */
1280 if (res != 0) /* check result */
1281 {
1282 handle->debug_print("scd30: set forced recalibration failed.\n"); /* set forced recalibration failed */
1283
1284 return 1; /* return error */
1285 }
1286 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
1287 {
1288 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
1289
1290 return 1; /* return error */
1291 }
1292 *co2_ppm = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]); /* get co2_ppm */
1293 }
1294
1295 return 0; /* success return 0 */
1296}
1297
1309uint8_t scd30_set_temperature_offset(scd30_handle_t *handle, uint16_t deg)
1310{
1311 uint8_t res;
1312
1313 if (handle == NULL) /* check handle */
1314 {
1315 return 2; /* return error */
1316 }
1317 if (handle->inited != 1) /* check handle initialization */
1318 {
1319 return 3; /* return error */
1320 }
1321
1322 if (handle->iic_uart != 0) /* uart */
1323 {
1324 uint8_t input_buf[6 + 2];
1325 uint8_t out_buf[6 + 2];
1326 uint16_t crc16;
1327
1328 input_buf[0] = 0x61; /* set slave address */
1329 input_buf[1] = 0x06; /* set function code */
1330 input_buf[2] = (SCD30_UART_ADDRESS_SET_TEMPERATURE_OFFSET >> 8) & 0xFF; /* set addr msb */
1331 input_buf[3] = (SCD30_UART_ADDRESS_SET_TEMPERATURE_OFFSET >> 0) & 0xFF; /* set addr lsb */
1332 input_buf[4] = (deg >> 8) & 0xFF; /* set deg msb */
1333 input_buf[5] = (deg >> 0) & 0xFF; /* set deg lsb */
1334 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1335 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1336 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1337 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
1338 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
1339 if (res != 0) /* check result */
1340 {
1341 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1342
1343 return 1; /* return error */
1344 }
1345 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
1346 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
1347 {
1348 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1349
1350 return 1; /* return error */
1351 }
1352 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
1353 {
1354 handle->debug_print("scd30: response check error.\n"); /* response check error */
1355
1356 return 1; /* return error */
1357 }
1358 }
1359 else /* iic */
1360 {
1361 uint8_t buf[3];
1362
1363 buf[0] = (deg >> 8) & 0xFF; /* set deg msb */
1364 buf[1] = (deg >> 0) & 0xFF; /* set deg lsb */
1365 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
1366 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SET_TEMPERATURE_OFFSET, (uint8_t *)buf, 3, 20); /* set temperature offset command */
1367 if (res != 0) /* check result */
1368 {
1369 handle->debug_print("scd30: set temperature offset failed.\n"); /* set temperature offset failed */
1370
1371 return 1; /* return error */
1372 }
1373 }
1374
1375 return 0; /* success return 0 */
1376}
1377
1389uint8_t scd30_get_temperature_offset(scd30_handle_t *handle, uint16_t *deg)
1390{
1391 uint8_t res;
1392
1393 if (handle == NULL) /* check handle */
1394 {
1395 return 2; /* return error */
1396 }
1397 if (handle->inited != 1) /* check handle initialization */
1398 {
1399 return 3; /* return error */
1400 }
1401
1402 if (handle->iic_uart != 0) /* uart */
1403 {
1404 uint8_t input_buf[6 + 2];
1405 uint8_t out_buf[7];
1406 uint16_t crc16;
1407
1408 input_buf[0] = 0x61; /* set slave address */
1409 input_buf[1] = 0x03; /* set function code */
1410 input_buf[2] = (SCD30_UART_ADDRESS_SET_TEMPERATURE_OFFSET >> 8) & 0xFF; /* set addr msb */
1411 input_buf[3] = (SCD30_UART_ADDRESS_SET_TEMPERATURE_OFFSET >> 0) & 0xFF; /* set addr lsb */
1412 input_buf[4] = 0x00; /* set 0x00 */
1413 input_buf[5] = 0x01; /* set 0x01 */
1414 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1415 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1416 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1417 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1418 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
1419 if (res != 0) /* check result */
1420 {
1421 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1422
1423 return 1; /* return error */
1424 }
1425 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
1426 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
1427 {
1428 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1429
1430 return 1; /* return error */
1431 }
1432 if (out_buf[0] != 0x61) /* check header */
1433 {
1434 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
1435
1436 return 1; /* return error */
1437 }
1438 if (out_buf[1] != 0x03) /* check code */
1439 {
1440 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
1441
1442 return 1; /* return error */
1443 }
1444 if (out_buf[2] != 0x02) /* check number */
1445 {
1446 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
1447
1448 return 1; /* return error */
1449 }
1450 *deg = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]); /* get deg */
1451 }
1452 else /* iic */
1453 {
1454 uint8_t buf[3];
1455
1456 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_SET_TEMPERATURE_OFFSET, (uint8_t *)buf, 3, 20); /* set temperature offset command */
1457 if (res != 0) /* check result */
1458 {
1459 handle->debug_print("scd30: set temperature offset failed.\n"); /* set temperature offset failed */
1460
1461 return 1; /* return error */
1462 }
1463 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
1464 {
1465 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
1466
1467 return 1; /* return error */
1468 }
1469 *deg = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]); /* get deg */
1470 }
1471
1472 return 0; /* success return 0 */
1473}
1474
1486uint8_t scd30_temperature_offset_convert_to_register(scd30_handle_t *handle, float deg, uint16_t *reg)
1487{
1488 if (handle == NULL) /* check handle */
1489 {
1490 return 2; /* return error */
1491 }
1492 if (handle->inited != 1) /* check handle initialization */
1493 {
1494 return 3; /* return error */
1495 }
1496
1497 *reg = (uint8_t)(deg * 100.0f); /* convert real data to register data */
1498
1499 return 0; /* success return 0 */
1500}
1501
1513uint8_t scd30_temperature_offset_convert_to_data(scd30_handle_t *handle, uint16_t reg, float *deg)
1514{
1515 if (handle == NULL) /* check handle */
1516 {
1517 return 2; /* return error */
1518 }
1519 if (handle->inited != 1) /* check handle initialization */
1520 {
1521 return 3; /* return error */
1522 }
1523
1524 *deg = (float)(reg) / 100.0f; /* convert raw data to real data */
1525
1526 return 0; /* success return 0 */
1527}
1528
1541{
1542 uint8_t res;
1543
1544 if (handle == NULL) /* check handle */
1545 {
1546 return 2; /* return error */
1547 }
1548 if (handle->inited != 1) /* check handle initialization */
1549 {
1550 return 3; /* return error */
1551 }
1552
1553 if (handle->iic_uart != 0) /* uart */
1554 {
1555 uint8_t input_buf[6 + 2];
1556 uint8_t out_buf[6 + 2];
1557 uint16_t crc16;
1558
1559 input_buf[0] = 0x61; /* set slave address */
1560 input_buf[1] = 0x06; /* set function code */
1561 input_buf[2] = (SCD30_UART_ADDRESS_SET_ALTITUDE >> 8) & 0xFF; /* set addr msb */
1562 input_buf[3] = (SCD30_UART_ADDRESS_SET_ALTITUDE >> 0) & 0xFF; /* set addr lsb */
1563 input_buf[4] = (m >> 8) & 0xFF; /* set m msb */
1564 input_buf[5] = (m >> 0) & 0xFF; /* set m lsb */
1565 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1566 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1567 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1568 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
1569 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
1570 if (res != 0) /* check result */
1571 {
1572 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1573
1574 return 1; /* return error */
1575 }
1576 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
1577 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
1578 {
1579 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1580
1581 return 1; /* return error */
1582 }
1583 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
1584 {
1585 handle->debug_print("scd30: response check error.\n"); /* response check error */
1586
1587 return 1; /* return error */
1588 }
1589 }
1590 else /* iic */
1591 {
1592 uint8_t buf[3];
1593
1594 buf[0] = (m >> 8) & 0xFF; /* set m msb */
1595 buf[1] = (m >> 0) & 0xFF; /* set m lsb */
1596 buf[2] = a_scd30_generate_crc8((uint8_t *)buf, 2); /* generate crc */
1597 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SET_ALTITUDE, (uint8_t *)buf, 3, 20); /* set altitude command */
1598 if (res != 0) /* check result */
1599 {
1600 handle->debug_print("scd30: set altitude failed.\n"); /* set altitude failed */
1601
1602 return 1; /* return error */
1603 }
1604 }
1605
1606 return 0; /* success return 0 */
1607}
1608
1621{
1622 uint8_t res;
1623
1624 if (handle == NULL) /* check handle */
1625 {
1626 return 2; /* return error */
1627 }
1628 if (handle->inited != 1) /* check handle initialization */
1629 {
1630 return 3; /* return error */
1631 }
1632
1633 if (handle->iic_uart != 0) /* uart */
1634 {
1635 uint8_t input_buf[6 + 2];
1636 uint8_t out_buf[7];
1637 uint16_t crc16;
1638
1639 input_buf[0] = 0x61; /* set slave address */
1640 input_buf[1] = 0x03; /* set function code */
1641 input_buf[2] = (SCD30_UART_ADDRESS_SET_ALTITUDE >> 8) & 0xFF; /* set addr msb */
1642 input_buf[3] = (SCD30_UART_ADDRESS_SET_ALTITUDE >> 0) & 0xFF; /* set addr lsb */
1643 input_buf[4] = 0x00; /* set 0x00 */
1644 input_buf[5] = 0x01; /* set 0x01 */
1645 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1646 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1647 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1648 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1649 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
1650 if (res != 0) /* check result */
1651 {
1652 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1653
1654 return 1; /* return error */
1655 }
1656 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
1657 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
1658 {
1659 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1660
1661 return 1; /* return error */
1662 }
1663 if (out_buf[0] != 0x61) /* check header */
1664 {
1665 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
1666
1667 return 1; /* return error */
1668 }
1669 if (out_buf[1] != 0x03) /* check code */
1670 {
1671 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
1672
1673 return 1; /* return error */
1674 }
1675 if (out_buf[2] != 0x02) /* check number */
1676 {
1677 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
1678
1679 return 1; /* return error */
1680 }
1681 *m = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]); /* get m */
1682 }
1683 else /* iic */
1684 {
1685 uint8_t buf[3];
1686
1687 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_SET_ALTITUDE, (uint8_t *)buf, 3, 20); /* set altitude command */
1688 if (res != 0) /* check result */
1689 {
1690 handle->debug_print("scd30: set altitude failed.\n"); /* set altitude failed */
1691
1692 return 1; /* return error */
1693 }
1694 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
1695 {
1696 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
1697
1698 return 1; /* return error */
1699 }
1700 *m = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]); /* get m */
1701 }
1702
1703 return 0; /* success return 0 */
1704}
1705
1717uint8_t scd30_get_firmware_version(scd30_handle_t *handle, uint16_t *version)
1718{
1719 uint8_t res;
1720
1721 if (handle == NULL) /* check handle */
1722 {
1723 return 2; /* return error */
1724 }
1725 if (handle->inited != 1) /* check handle initialization */
1726 {
1727 return 3; /* return error */
1728 }
1729
1730 if (handle->iic_uart != 0) /* uart */
1731 {
1732 uint8_t input_buf[6 + 2];
1733 uint8_t out_buf[7];
1734 uint16_t crc16;
1735
1736 input_buf[0] = 0x61; /* set slave address */
1737 input_buf[1] = 0x03; /* set function code */
1738 input_buf[2] = (SCD30_UART_ADDRESS_READ_FIRMWARE_VERSION >> 8) & 0xFF; /* set addr msb */
1739 input_buf[3] = (SCD30_UART_ADDRESS_READ_FIRMWARE_VERSION >> 0) & 0xFF; /* set addr lsb */
1740 input_buf[4] = 0x00; /* set 0x00 */
1741 input_buf[5] = 0x01; /* set 0x01 */
1742 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1743 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1744 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1745 memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1746 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 7); /* write read frame */
1747 if (res != 0) /* check result */
1748 {
1749 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1750
1751 return 1; /* return error */
1752 }
1753 crc16 = ((uint16_t)out_buf[6] << 8 | (uint16_t)out_buf[5]); /* get crc16 */
1754 if (crc16 != a_scd30_generate_crc16(out_buf, 5)) /* check crc16 */
1755 {
1756 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1757
1758 return 1; /* return error */
1759 }
1760 if (out_buf[0] != 0x61) /* check header */
1761 {
1762 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
1763
1764 return 1; /* return error */
1765 }
1766 if (out_buf[1] != 0x03) /* check code */
1767 {
1768 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
1769
1770 return 1; /* return error */
1771 }
1772 if (out_buf[2] != 0x02) /* check number */
1773 {
1774 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
1775
1776 return 1; /* return error */
1777 }
1778 *version = (uint16_t)(((uint16_t)out_buf[3] << 8) | out_buf[4]); /* get version */
1779 }
1780 else /* iic */
1781 {
1782 uint8_t buf[3];
1783
1784 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_READ_FIRMWARE_VERSION, (uint8_t *)buf, 3, 20); /* read firmware version command */
1785 if (res != 0) /* check result */
1786 {
1787 handle->debug_print("scd30: read firmware version failed.\n"); /* read firmware version failed */
1788
1789 return 1; /* return error */
1790 }
1791 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf, 2)) /* check crc */
1792 {
1793 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
1794
1795 return 1; /* return error */
1796 }
1797 *version = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]); /* get version */
1798 }
1799
1800 return 0; /* success return 0 */
1801}
1802
1814{
1815 uint8_t res;
1816
1817 if (handle == NULL) /* check handle */
1818 {
1819 return 2; /* return error */
1820 }
1821 if (handle->inited != 1) /* check handle initialization */
1822 {
1823 return 3; /* return error */
1824 }
1825
1826 if (handle->iic_uart != 0) /* uart */
1827 {
1828 uint8_t input_buf[6 + 2];
1829 uint8_t out_buf[6 + 2];
1830 uint16_t crc16;
1831
1832 input_buf[0] = 0x61; /* set slave address */
1833 input_buf[1] = 0x06; /* set function code */
1834 input_buf[2] = (SCD30_UART_ADDRESS_SOFT_RESET >> 8) & 0xFF; /* set addr msb */
1835 input_buf[3] = (SCD30_UART_ADDRESS_SOFT_RESET >> 0) & 0xFF; /* set addr lsb */
1836 input_buf[4] = 0x00; /* set 0x00 */
1837 input_buf[5] = 0x01; /* set 0x01 */
1838 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1839 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1840 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1841 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
1842 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
1843 if (res != 0) /* check result */
1844 {
1845 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1846
1847 return 1; /* return error */
1848 }
1849 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
1850 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
1851 {
1852 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1853
1854 return 1; /* return error */
1855 }
1856 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
1857 {
1858 handle->debug_print("scd30: response check error.\n"); /* response check error */
1859
1860 return 1; /* return error */
1861 }
1862 }
1863 else /* iic */
1864 {
1865 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SOFT_RESET, (uint8_t *)NULL, 0, 20); /* soft reset command */
1866 if (res != 0) /* check result */
1867 {
1868 handle->debug_print("scd30: soft reset failed.\n"); /* soft reset failed */
1869
1870 return 1; /* return error */
1871 }
1872 }
1873 handle->delay_ms(100); /* delay 100ms */
1874
1875 return 0; /* success return 0 */
1876}
1877
1891{
1892 union float_u
1893 {
1894 float f;
1895 uint32_t i;
1896 };
1897 uint8_t res;
1898 uint16_t status;
1899 union float_u prev;
1900 uint32_t timeout = 5000;
1901
1902 if ((handle == NULL) || (data == NULL)) /* check handle */
1903 {
1904 return 2; /* return error */
1905 }
1906 if (handle->inited != 1) /* check handle initialization */
1907 {
1908 return 3; /* return error */
1909 }
1910
1911 while (timeout != 0) /* check timeout */
1912 {
1913 res = a_scd30_get_data_ready_status(handle, &status); /* get data ready status */
1914 if (res != 0) /* check result */
1915 {
1916 handle->debug_print("scd30: get data ready status failed.\n"); /* get data ready status failed */
1917
1918 return 1; /* return error */
1919 }
1920 if (status == 1) /* check status */
1921 {
1922 break; /* break */
1923 }
1924 timeout--; /* timeout-- */
1925 handle->delay_ms(1); /* delay 1ms */
1926 }
1927 if (timeout == 0) /* check timeout */
1928 {
1929 handle->debug_print("scd30: read timeout.\n"); /* read timeout */
1930
1931 return 4; /* return error */
1932 }
1933
1934 if (handle->iic_uart != 0) /* uart */
1935 {
1936 uint8_t input_buf[6 + 2];
1937 uint8_t out_buf[17];
1938 uint16_t crc16;
1939
1940 input_buf[0] = 0x61; /* set slave address */
1941 input_buf[1] = 0x03; /* set function code */
1942 input_buf[2] = (SCD30_UART_ADDRESS_READ_MEASUREMENT >> 8) & 0xFF; /* set addr msb */
1943 input_buf[3] = (SCD30_UART_ADDRESS_READ_MEASUREMENT >> 0) & 0xFF; /* set addr lsb */
1944 input_buf[4] = 0x00; /* set 0x00 */
1945 input_buf[5] = 0x06; /* set 0x01 */
1946 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
1947 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
1948 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
1949 memset(out_buf, 0, sizeof(uint8_t) * 17); /* clear the buffer */
1950 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 17); /* write read frame */
1951 if (res != 0) /* check result */
1952 {
1953 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
1954
1955 return 1; /* return error */
1956 }
1957 crc16 = ((uint16_t)out_buf[16] << 8 | (uint16_t)out_buf[15]); /* get crc16 */
1958 if (crc16 != a_scd30_generate_crc16(out_buf, 15)) /* check crc16 */
1959 {
1960 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
1961
1962 return 1; /* return error */
1963 }
1964 if (out_buf[0] != 0x61) /* check header */
1965 {
1966 handle->debug_print("scd30: header is invalid.\n"); /* header is invalid */
1967
1968 return 1; /* return error */
1969 }
1970 if (out_buf[1] != 0x03) /* check code */
1971 {
1972 handle->debug_print("scd30: code is invalid.\n"); /* code is invalid */
1973
1974 return 1; /* return error */
1975 }
1976 if (out_buf[2] != 0x0C) /* check number */
1977 {
1978 handle->debug_print("scd30: number is invalid.\n"); /* number is invalid */
1979
1980 return 1; /* return error */
1981 }
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); /* integer to float */
1984 data->co2_raw = prev.i; /* save raw */
1985 data->co2_ppm = prev.f; /* save float */
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); /* integer to float */
1988 data->temperature_raw = prev.i; /* save raw */
1989 data->temperature_deg = prev.f; /* save float */
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); /* integer to float */
1992 data->humidity_raw = prev.i; /* save raw */
1993 data->humidity_percent = prev.f; /* save float */
1994 }
1995 else /* iic */
1996 {
1997 uint8_t buf[18];
1998
1999 res = a_scd30_iic_read(handle, SCD30_IIC_COMMAND_READ_MEASUREMENT, (uint8_t *)buf, 18, 20); /* read measurement command */
2000 if (res != 0) /* check result */
2001 {
2002 handle->debug_print("scd30: read measurement failed.\n"); /* read measurement failed */
2003
2004 return 1; /* return error */
2005 }
2006 if (buf[2] != a_scd30_generate_crc8((uint8_t *)buf + 0, 2)) /* check crc */
2007 {
2008 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
2009
2010 return 1; /* return error */
2011 }
2012 if (buf[5] != a_scd30_generate_crc8((uint8_t *)buf + 3, 2)) /* check crc */
2013 {
2014 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
2015
2016 return 1; /* return error */
2017 }
2018 if (buf[8] != a_scd30_generate_crc8((uint8_t *)buf + 6, 2)) /* check crc */
2019 {
2020 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
2021
2022 return 1; /* return error */
2023 }
2024 if (buf[11] != a_scd30_generate_crc8((uint8_t *)buf + 9, 2)) /* check crc */
2025 {
2026 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
2027
2028 return 1; /* return error */
2029 }
2030 if (buf[14] != a_scd30_generate_crc8((uint8_t *)buf + 12, 2)) /* check crc */
2031 {
2032 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
2033
2034 return 1; /* return error */
2035 }
2036 if (buf[17] != a_scd30_generate_crc8((uint8_t *)buf + 15, 2)) /* check crc */
2037 {
2038 handle->debug_print("scd30: crc check failed.\n"); /* crc check failed */
2039
2040 return 1; /* return error */
2041 }
2042 prev.i = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
2043 ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0); /* integer to float */
2044 data->co2_raw = prev.i; /* save raw */
2045 data->co2_ppm = prev.f; /* save float */
2046 prev.i = ((uint32_t)buf[6] << 24) | ((uint32_t)buf[7] << 16) |
2047 ((uint32_t)buf[9] << 8) | ((uint32_t)buf[10] << 0); /* integer to float */
2048 data->temperature_raw = prev.i; /* save raw */
2049 data->temperature_deg = prev.f; /* save float */
2050 prev.i = ((uint32_t)buf[12] << 24) | ((uint32_t)buf[13] << 16) |
2051 ((uint32_t)buf[15] << 8) | ((uint32_t)buf[16] << 0); /* integer to float */
2052 data->humidity_raw = prev.i; /* save raw */
2053 data->humidity_percent = prev.f; /* save float */
2054 }
2055
2056 return 0; /* success return 0 */
2057}
2058
2071{
2072 uint8_t res;
2073
2074 if (handle == NULL) /* check handle */
2075 {
2076 return 2; /* return error */
2077 }
2078 if (handle->debug_print == NULL) /* check debug_print */
2079 {
2080 return 3; /* return error */
2081 }
2082 if (handle->iic_init == NULL) /* check iic_init */
2083 {
2084 handle->debug_print("scd30: iic_init is null.\n"); /* iic_init is null */
2085
2086 return 3; /* return error */
2087 }
2088 if (handle->iic_deinit == NULL) /* check iic_deinit */
2089 {
2090 handle->debug_print("scd30: iic_deinit is null.\n"); /* iic_deinit is null */
2091
2092 return 3; /* return error */
2093 }
2094 if (handle->iic_write_cmd == NULL) /* check iic_write_cmd */
2095 {
2096 handle->debug_print("scd30: iic_write_cmd is null.\n"); /* iic_write_cmd is null */
2097
2098 return 3; /* return error */
2099 }
2100 if (handle->iic_read_cmd == NULL) /* check iic_read_cmd */
2101 {
2102 handle->debug_print("scd30: iic_read_cmd is null.\n"); /* iic_read_cmd is null */
2103
2104 return 3; /* return error */
2105 }
2106 if (handle->uart_init == NULL) /* check uart_init */
2107 {
2108 handle->debug_print("scd30: uart_init is null.\n"); /* uart_init is null */
2109
2110 return 3; /* return error */
2111 }
2112 if (handle->uart_deinit == NULL) /* check uart_deinit */
2113 {
2114 handle->debug_print("scd30: uart_deinit is null.\n"); /* uart_deinit is null */
2115
2116 return 3; /* return error */
2117 }
2118 if (handle->uart_read == NULL) /* check uart_read */
2119 {
2120 handle->debug_print("scd30: uart_read is null.\n"); /* uart_read is null */
2121
2122 return 3; /* return error */
2123 }
2124 if (handle->uart_write == NULL) /* check uart_write */
2125 {
2126 handle->debug_print("scd30: uart_write is null.\n"); /* uart_write is null */
2127
2128 return 3; /* return error */
2129 }
2130 if (handle->uart_flush == NULL) /* check uart_flush */
2131 {
2132 handle->debug_print("scd30: uart_flush is null.\n"); /* uart_flush is null */
2133
2134 return 3; /* return error */
2135 }
2136 if (handle->delay_ms == NULL) /* check delay_ms */
2137 {
2138 handle->debug_print("scd30: delay_ms is null.\n"); /* delay_ms is null */
2139
2140 return 3; /* return error */
2141 }
2142
2143 if (handle->iic_uart != 0) /* uart */
2144 {
2145 uint8_t input_buf[6 + 2];
2146 uint8_t out_buf[6 + 2];
2147 uint16_t crc16;
2148
2149 if (handle->uart_init() != 0) /* uart init */
2150 {
2151 handle->debug_print("scd30: uart init failed.\n"); /* uart init failed */
2152
2153 return 1; /* return error */
2154 }
2155
2156 input_buf[0] = 0x61; /* set slave address */
2157 input_buf[1] = 0x06; /* set function code */
2158 input_buf[2] = (SCD30_UART_ADDRESS_SOFT_RESET >> 8) & 0xFF; /* set addr msb */
2159 input_buf[3] = (SCD30_UART_ADDRESS_SOFT_RESET >> 0) & 0xFF; /* set addr lsb */
2160 input_buf[4] = 0x00; /* set 0x00 */
2161 input_buf[5] = 0x01; /* set 0x01 */
2162 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
2163 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
2164 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
2165 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
2166 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
2167 if (res != 0) /* check result */
2168 {
2169 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
2170
2171 return 4; /* return error */
2172 }
2173 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
2174 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
2175 {
2176 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
2177
2178 return 4; /* return error */
2179 }
2180 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
2181 {
2182 handle->debug_print("scd30: response check error.\n"); /* response check error */
2183
2184 return 4; /* return error */
2185 }
2186 }
2187 else /* iic */
2188 {
2189 if (handle->iic_init() != 0) /* iic init */
2190 {
2191 handle->debug_print("scd30: iic init failed.\n"); /* iic init failed */
2192
2193 return 1; /* return error */
2194 }
2195 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SOFT_RESET, (uint8_t *)NULL, 0, 20); /* soft reset command */
2196 if (res != 0) /* check result */
2197 {
2198 handle->debug_print("scd30: soft reset failed.\n"); /* soft reset failed */
2199
2200 return 4; /* return error */
2201 }
2202 }
2203 handle->delay_ms(100); /* delay 100ms */
2204 handle->inited = 1; /* flag finish initialization */
2205
2206 return 0; /* success return 0 */
2207}
2208
2221{
2222 uint8_t res;
2223
2224 if (handle == NULL) /* check handle */
2225 {
2226 return 2; /* return error */
2227 }
2228 if (handle->inited != 1) /* check handle initialization */
2229 {
2230 return 3; /* return error */
2231 }
2232
2233 if (handle->iic_uart != 0)
2234 {
2235 uint8_t input_buf[6 + 2];
2236 uint8_t out_buf[6 + 2];
2237 uint16_t crc16;
2238
2239 input_buf[0] = 0x61; /* set slave address */
2240 input_buf[1] = 0x06; /* set function code */
2241 input_buf[2] = (SCD30_UART_ADDRESS_SOFT_RESET >> 8) & 0xFF; /* set addr msb */
2242 input_buf[3] = (SCD30_UART_ADDRESS_SOFT_RESET >> 0) & 0xFF; /* set addr lsb */
2243 input_buf[4] = 0x00; /* set 0x00 */
2244 input_buf[5] = 0x01; /* set 0x01 */
2245 crc16 = a_scd30_generate_crc16(input_buf, 6); /* get crc16 */
2246 input_buf[6] = (crc16 >> 0) & 0xFF; /* set crc lsb */
2247 input_buf[7] = (crc16 >> 8) & 0xFF; /* set crc mss */
2248 memset(out_buf, 0, sizeof(uint8_t) * 8); /* clear the buffer */
2249 res = a_scd30_uart_write_read(handle, (uint8_t *)input_buf, 8, 50, (uint8_t *)out_buf, 8); /* write read frame */
2250 if (res != 0) /* check result */
2251 {
2252 handle->debug_print("scd30: write read failed.\n"); /* write read failed */
2253
2254 return 4; /* return error */
2255 }
2256 crc16 = ((uint16_t)out_buf[7] << 8 | (uint16_t)out_buf[6]); /* get crc16 */
2257 if (crc16 != a_scd30_generate_crc16(out_buf, 6)) /* check crc16 */
2258 {
2259 handle->debug_print("scd30: crc check error.\n"); /* crc check error */
2260
2261 return 4; /* return error */
2262 }
2263 if (memcmp(input_buf, out_buf, 8) != 0) /* check the response */
2264 {
2265 handle->debug_print("scd30: response check error.\n"); /* response check error */
2266
2267 return 4; /* return error */
2268 }
2269 if (handle->uart_deinit() != 0) /* uart deinit */
2270 {
2271 handle->debug_print("scd30: uart deinit failed.\n"); /* uart deinit failed */
2272
2273 return 1; /* return error */
2274 }
2275 }
2276 else
2277 {
2278 res = a_scd30_iic_write(handle, SCD30_IIC_COMMAND_SOFT_RESET, (uint8_t *)NULL, 0, 20); /* soft reset command */
2279 if (res != 0) /* check result */
2280 {
2281 handle->debug_print("scd30: soft reset failed.\n"); /* soft reset failed */
2282
2283 return 4; /* return error */
2284 }
2285 res = handle->iic_deinit(); /* iic deinit */
2286 if (res != 0) /* check result */
2287 {
2288 handle->debug_print("scd30: iic deinit failed.\n"); /* iic deinit */
2289
2290 return 1; /* return error */
2291 }
2292 }
2293 handle->delay_ms(100); /* delay 100ms */
2294 handle->inited = 0; /* flag close initialization */
2295
2296 return 0; /* success return 0 */
2297}
2298
2311uint8_t scd30_set_get_reg_uart(scd30_handle_t *handle, uint8_t *input, uint16_t in_len, uint8_t *output, uint16_t out_len)
2312{
2313 if (handle == NULL) /* check handle */
2314 {
2315 return 2; /* return error */
2316 }
2317 if (handle->inited != 1) /* check handle initialization */
2318 {
2319 return 3; /* return error */
2320 }
2321
2322 if (handle->iic_uart != 0)
2323 {
2324 return a_scd30_uart_write_read(handle, input, in_len, 50, output, out_len); /* write and read with the uart interface */
2325 }
2326 else
2327 {
2328 handle->debug_print("scd30: iic interface is invalid.\n"); /* iic interface is invalid */
2329
2330 return 1; /* return error */
2331 }
2332}
2333
2347uint8_t scd30_set_reg_iic(scd30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
2348{
2349 if (handle == NULL) /* check handle */
2350 {
2351 return 2; /* return error */
2352 }
2353 if (handle->inited != 1) /* check handle initialization */
2354 {
2355 return 3; /* return error */
2356 }
2357
2358 if (handle->iic_uart != 0)
2359 {
2360 handle->debug_print("scd30: uart interface is invalid.\n"); /* uart interface is invalid */
2361
2362 return 1; /* return error */
2363 }
2364 else
2365 {
2366 return a_scd30_iic_write(handle, reg, buf, len, 20); /* write the data */
2367 }
2368}
2369
2383uint8_t scd30_get_reg_iic(scd30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
2384{
2385 if (handle == NULL) /* check handle */
2386 {
2387 return 2; /* return error */
2388 }
2389 if (handle->inited != 1) /* check handle initialization */
2390 {
2391 return 3; /* return error */
2392 }
2393
2394 if (handle->iic_uart != 0)
2395 {
2396 handle->debug_print("scd30: uart interface is invalid.\n"); /* uart interface is invalid */
2397
2398 return 1;
2399 }
2400 else
2401 {
2402 return a_scd30_iic_read(handle, reg, buf, len, 20); /* read the data */
2403 }
2404}
2405
2415{
2416 if (info == NULL) /* check handle */
2417 {
2418 return 2; /* return error */
2419 }
2420
2421 memset(info, 0, sizeof(scd30_info_t)); /* initialize scd30 info structure */
2422 strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */
2423 strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */
2424 strncpy(info->interface, "UART IIC", 16); /* copy interface name */
2425 info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */
2426 info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */
2427 info->max_current_ma = MAX_CURRENT; /* set maximum current */
2428 info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */
2429 info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */
2430 info->driver_version = DRIVER_VERSION; /* set driver version */
2431
2432 return 0; /* success return 0 */
2433}
#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 MAX_CURRENT
#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 TEMPERATURE_MAX
#define SCD30_UART_ADDRESS_SET_MEASUREMENT_INTERVAL
#define SCD30_UART_ADDRESS_READ_FIRMWARE_VERSION
#define SCD30_UART_ADDRESS_SOFT_RESET
#define MANUFACTURER_NAME
#define TEMPERATURE_MIN
#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 DRIVER_VERSION
#define SCD30_IIC_COMMAND_SET_FORCED_RECALIBRATION
#define SCD30_IIC_COMMAND_READ_FIRMWARE_VERSION
driver scd30 header file
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
uint16_t temperature_raw
uint16_t humidity_raw
uint16_t co2_raw
float temperature_deg
float humidity_percent
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 temperature_max
float supply_voltage_max_v
uint32_t driver_version
char interface[16]
float temperature_min
float max_current_ma
char manufacturer_name[32]
float supply_voltage_min_v
char chip_name[32]