LibDriver SPS30  1.0.0
SPS30 full-featured driver
driver_sps30.c
Go to the documentation of this file.
1 
37 #include "driver_sps30.h"
38 
42 #define CHIP_NAME "Sensirion SPS30"
43 #define MANUFACTURER_NAME "Sensirion"
44 #define SUPPLY_VOLTAGE_MIN 4.50f
45 #define SUPPLY_VOLTAGE_MAX 5.50f
46 #define MAX_CURRENT 80.0f
47 #define TEMPERATURE_MIN -10.0f
48 #define TEMPERATURE_MAX 60.0f
49 #define DRIVER_VERSION 1000
54 #define SPS30_ADDRESS (0x69 << 1)
59 #define SPS30_IIC_COMMAND_START_MEASUREMENT 0x0010U
60 #define SPS30_IIC_COMMAND_STOP_MEASUREMENT 0x0104U
61 #define SPS30_IIC_COMMAND_READ_DATA_READY_FLAG 0x0202U
62 #define SPS30_IIC_COMMAND_READ_MEASURED_VALUES 0x0300U
63 #define SPS30_IIC_COMMAND_SLEEP 0x1001U
64 #define SPS30_IIC_COMMAND_WAKE_UP 0x1103U
65 #define SPS30_IIC_COMMAND_START_FAN_CLEANING 0x5607U
66 #define SPS30_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL 0x8004U
67 #define SPS30_IIC_COMMAND_READ_PRODUCT_TYPE 0xD002U
68 #define SPS30_IIC_COMMAND_READ_SERIAL_NUMBER 0xD033U
69 #define SPS30_IIC_COMMAND_READ_VERSION 0xD100U
70 #define SPS30_IIC_COMMAND_READ_DEVICE_STATUS_REG 0xD206U
71 #define SPS30_IIC_COMMAND_CLEAR_DEVICE_STATUS_REG 0xD210U
72 #define SPS30_IIC_COMMAND_RESET 0xD304U
73 #define SPS30_UART_COMMAND_START_MEASUREMENT 0x00
74 #define SPS30_UART_COMMAND_STOP_MEASUREMENT 0x01
75 #define SPS30_UART_COMMAND_READ_MEASURED_VALUES 0x03
76 #define SPS30_UART_COMMAND_SLEEP 0x10
77 #define SPS30_UART_COMMAND_WAKE_UP 0x11
78 #define SPS30_UART_COMMAND_START_FAN_CLEANING 0x56
79 #define SPS30_UART_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL 0x80
80 #define SPS30_UART_COMMAND_READ_PRODUCT_TYPE 0xD0
81 #define SPS30_UART_COMMAND_READ_VERSION 0xD1
82 #define SPS30_UART_COMMAND_READ_DEVICE_STATUS_REG 0xD2
83 #define SPS30_UART_COMMAND_RESET 0xD3
93 static uint8_t a_sps30_generate_crc(sps30_handle_t *handle, uint8_t* data, uint8_t count)
94 {
95  if (handle->iic_uart == SPS30_INTERFACE_IIC)
96  {
97  uint8_t current_byte;
98  uint8_t crc = 0xFF;
99  uint8_t crc_bit;
100 
101  for (current_byte = 0; current_byte < count; ++current_byte) /* calculate crc */
102  {
103  crc ^= (data[current_byte]); /* xor data */
104  for (crc_bit = 8; crc_bit > 0; --crc_bit) /* 8 bit */
105  {
106  if ((crc & 0x80) != 0) /* if 7th bit is 1 */
107  {
108  crc = (crc << 1) ^ 0x31; /* xor */
109  }
110  else
111  {
112  crc = crc << 1; /* left shift 1 */
113  }
114  }
115  }
116 
117  return crc; /* return crc */
118  }
119  else
120  {
121  uint8_t i;
122  uint32_t crc = 0x00;
123 
124  for (i = 0; i < count; i++) /* sum */
125  {
126  crc += data[i]; /* sum */
127  }
128 
129  return (uint8_t)(~(crc & 0xFF)); /* take the least significant byte of the result and invert it */
130  }
131 }
132 
146 static uint8_t a_sps30_iic_read(sps30_handle_t *handle, uint8_t addr, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
147 {
148  uint8_t buf[2];
149 
150  buf[0] = (reg >> 8) & 0xFF; /* set msb */
151  buf[1] = (reg >> 0) & 0xFF; /* set lsb */
152  if (handle->iic_write_cmd(addr, (uint8_t *)buf, 2) != 0) /* write data */
153  {
154  return 1; /* return error */
155  }
156  handle->delay_ms(delay_ms); /* delay ms */
157  if (handle->iic_read_cmd(addr, (uint8_t *)data, len) != 0) /* read data */
158  {
159  return 1; /* return error */
160  }
161 
162  return 0; /* success return 0 */
163 }
164 
178 static uint8_t a_sps30_iic_write(sps30_handle_t *handle, uint8_t addr, uint16_t reg, uint8_t *data, uint16_t len, uint16_t delay_ms)
179 {
180  uint8_t buf[16];
181 
182  if (len > 14) /* check length */
183  {
184  return 1; /* return error */
185  }
186  buf[0] = (reg >> 8) & 0xFF; /* set msb */
187  buf[1] = (reg >> 0) & 0xFF; /* set lsb */
188  memcpy((uint8_t *)&buf[2], data, len); /* copy data */
189  if (handle->iic_write_cmd(addr, (uint8_t *)buf, len + 2) != 0) /* write data */
190  {
191  return 1; /* return error */
192  }
193  handle->delay_ms(delay_ms); /* delay ms */
194 
195  return 0; /* success return 0 */
196 }
197 
209 static uint8_t a_sps30_uart_get_rx_frame(sps30_handle_t *handle, uint16_t len, uint8_t *output, uint16_t out_len)
210 {
211  uint16_t i, point;
212 
213  output[0] = handle->buf[0]; /* set buf[0] */
214  point = 1; /* set point 1 */
215  for (i = 1; i < (len - 1); i++) /* run n -2 times */
216  {
217  if (point >= (out_len - 1)) /* check length */
218  {
219  return 1; /* return error */
220  }
221  if (((handle->buf[i] == 0x7D) && (handle->buf[i + 1]) == 0x5E) || /* check buffer */
222  ((handle->buf[i] == 0x7D) && (handle->buf[i + 1]) == 0x5D) ||
223  ((handle->buf[i] == 0x7D) && (handle->buf[i + 1]) == 0x31) ||
224  ((handle->buf[i] == 0x7D) && (handle->buf[i + 1]) == 0x33)
225  )
226  {
227  switch (handle->buf[i + 1]) /* judge */
228  {
229  case 0x5E : /* 0x5E */
230  {
231  output[point] = 0x7E; /* set output */
232  point++; /* point++ */
233  i++; /* i++ */
234 
235  break; /* break */
236  }
237  case 0x5D : /* 0x5D */
238  {
239  output[point] = 0x7D; /* set output */
240  point++; /* point++ */
241  i++; /* i++ */
242 
243  break; /* break */
244  }
245  case 0x31 : /* 0x31 */
246  {
247  output[point] = 0x11; /* set output */
248  point++; /* point++ */
249  i++; /* i++ */
250 
251  break; /* break */
252  }
253  case 0x33 : /* 0x33 */
254  {
255  output[point] = 0x13; /* set output */
256  point++; /* point++ */
257  i++; /* i++ */
258 
259  break; /* break */
260  }
261  default :
262  {
263  break; /* break */
264  }
265  }
266  }
267  else
268  {
269  output[point] = handle->buf[i]; /* set output */
270  point++; /* point++ */
271  }
272  }
273  output[point] = handle->buf[len - 1]; /* set the end part */
274  point++; /* point++ */
275  if (point != out_len) /* check point */
276  {
277  return 1; /* return error */
278  }
279 
280  return 0; /* success return 0 */
281 }
282 
294 static uint8_t a_sps30_uart_set_tx_frame(sps30_handle_t *handle, uint8_t *input, uint16_t in_len, uint16_t *out_len)
295 {
296  uint16_t i;
297 
298  memset(handle->buf, 0, sizeof(uint8_t) * 256); /* clear buffer */
299  handle->buf[0] = input[0]; /* set buf[0] */
300  *out_len = 1; /* set output length */
301  for (i = 1; i < (in_len - 1); i++)
302  {
303  if ((*out_len) >= 255) /* check output length */
304  {
305  return 1; /* return error */
306  }
307  if ((input[i] == 0x7E) || (input[i] == 0x7D) || /* check data */
308  (input[i] == 0x11) || (input[i] == 0x13)
309  )
310  {
311  switch (input[i]) /* judge input */
312  {
313  case 0x7E : /* 0x7E */
314  {
315  handle->buf[*out_len] = 0x7D; /* 0x7D */
316  (*out_len)++; /* output length++ */
317  handle->buf[*out_len] = 0x5E; /* 0x5E */
318  (*out_len)++; /* output length++ */
319 
320  break; /* break */
321  }
322  case 0x7D : /* 0x7D */
323  {
324  handle->buf[*out_len] = 0x7D; /* set 0x7D */
325  (*out_len)++; /* output length++ */
326  handle->buf[*out_len] = 0x5D; /* set 0x5D */
327  (*out_len)++; /* output length++ */
328 
329  break; /* break */
330  }
331  case 0x11 : /* 0x11 */
332  {
333  handle->buf[*out_len] = 0x7D; /* set 0x7D */
334  (*out_len)++; /* output length++ */
335  handle->buf[*out_len] = 0x31; /* set 0x31 */
336  (*out_len)++; /* output length++ */
337 
338  break; /* break */
339  }
340  case 0x13 : /* 0x13 */
341  {
342  handle->buf[*out_len] = 0x7D; /* set 0x7D */
343  (*out_len)++; /* output length++ */
344  handle->buf[*out_len] = 0x33; /* set 0x33 */
345  (*out_len)++; /* output length++ */
346 
347  break; /* break */
348  }
349  default :
350  {
351  break; /* break */
352  }
353  }
354  }
355  else
356  {
357  handle->buf[*out_len] = input[i]; /* set the buffer */
358  (*out_len)++; /* output length++ */
359  }
360  }
361  handle->buf[*out_len] = input[in_len - 1];
362  (*out_len)++; /* copy the end frame */
363 
364  return 0; /* success return 0 */
365 }
366 
380 static uint8_t a_sps30_uart_write_read(sps30_handle_t *handle, uint8_t *input, uint16_t in_len,
381  uint16_t delay_ms, uint8_t *output, uint16_t out_len)
382 {
383  uint16_t len;
384 
385  if (a_sps30_uart_set_tx_frame(handle, input, in_len, (uint16_t *)&len) != 0) /* set tx frame */
386  {
387  return 1; /* return error */
388  }
389  if (handle->uart_flush() != 0) /* uart flush */
390  {
391  return 1; /* return error */
392  }
393  if (handle->uart_write(handle->buf, len) != 0) /* write data */
394  {
395  return 1; /* return error */
396  }
397  handle->delay_ms(delay_ms); /* delay ms */
398  len = handle->uart_read(handle->buf, 256); /* read data */
399  if (a_sps30_uart_get_rx_frame(handle, len, output, out_len) != 0) /* get rx frame */
400  {
401  return 1; /* return error */
402  }
403 
404  return 0; /* success return 0 */
405 }
406 
414 static uint8_t a_sps30_uart_error(sps30_handle_t *handle, uint8_t e)
415 {
416  switch (e)
417  {
418  case 0x00 :
419  {
420  break;
421  }
422  case 0x01 :
423  {
424  handle->debug_print("sps30: wrong data length for this command error.\n"); /* wrong data length for this command error */
425 
426  break;
427  }
428  case 0x02 :
429  {
430  handle->debug_print("sps30: unknown command.\n"); /* unknown command */
431 
432  break;
433  }
434  case 0x03 :
435  {
436  handle->debug_print("sps30: no access right for command.\n"); /* no access right for command */
437 
438  break;
439  }
440  case 0x04 :
441  {
442  handle->debug_print("sps30: illegal command parameter or parameter "
443  "out of allowed range.\n"); /* illegal command parameter or parameter out of allowed range */
444 
445  break;
446  }
447  case 0x28 :
448  {
449  handle->debug_print("sps30: internal function argument out of range.\n"); /* internal function argument out of range */
450 
451  break;
452  }
453  case 0x43 :
454  {
455  handle->debug_print("sps30: command not allowed in current state.\n"); /* command not allowed in current state */
456 
457  break;
458  }
459  default :
460  {
461  handle->debug_print("sps30: unknown code.\n"); /* unknown code */
462 
463  break;
464  }
465  }
466 
467  return e; /* return error code */
468 }
469 
480 {
481  if (handle == NULL) /* check handle */
482  {
483  return 2; /* return error */
484  }
485 
486  handle->iic_uart = (uint8_t)interface; /* set interface */
487 
488  return 0; /* success return 0 */
489 }
490 
501 {
502  if (handle == NULL) /* check handle */
503  {
504  return 2; /* return error */
505  }
506 
507  *interface = (sps30_interface_t)(handle->iic_uart); /* get interface */
508 
509  return 0; /* success return 0 */
510 }
511 
524 {
525  uint8_t res;
526 
527  if (handle == NULL) /* check handle */
528  {
529  return 2; /* return error */
530  }
531  if (handle->inited != 1) /* check handle initialization */
532  {
533  return 3; /* return error */
534  }
535 
536  if (handle->iic_uart != 0) /* uart */
537  {
538  uint8_t input_buf[6 + 2];
539  uint8_t out_buf[7];
540 
541  input_buf[0] = 0x7E; /* set start */
542  input_buf[1] = 0x00; /* set addr */
543  input_buf[2] = SPS30_UART_COMMAND_START_MEASUREMENT; /* set command */
544  input_buf[3] = 0x02; /* set length */
545  input_buf[4] = 0x01; /* set 0x01 */
546  input_buf[5] = format; /* set format */
547  handle->format = format; /* save format */
548  input_buf[6] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 5); /* set crc */
549  input_buf[7] = 0x7E; /* set stop */
550  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
551  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 8, 20, (uint8_t *)out_buf, 7); /* write read frame */
552  if (res != 0) /* check result */
553  {
554  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
555 
556  return 1; /* return error */
557  }
558  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
559  {
560  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
561 
562  return 1; /* return error */
563  }
564  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
565  {
566  return 1; /* return error */
567  }
568  }
569  else /* iic */
570  {
571  uint8_t buf[3];
572 
573  buf[0] = format; /* set format */
574  handle->format = format; /* save format */
575  buf[1] = 0x00; /* set dummy */
576  buf[2] = a_sps30_generate_crc(handle, (uint8_t *)buf, 2); /* generate crc */
577  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_START_MEASUREMENT, (uint8_t *)buf, 3, 20); /* start measurement command */
578  if (res != 0) /* check result */
579  {
580  handle->debug_print("sps30: start measurement failed.\n"); /* start measurement failed */
581 
582  return 1; /* return error */
583  }
584  }
585 
586  return 0; /* success return 0 */
587 }
588 
600 {
601  uint8_t res;
602 
603  if (handle == NULL) /* check handle */
604  {
605  return 2; /* return error */
606  }
607  if (handle->inited != 1) /* check handle initialization */
608  {
609  return 3; /* return error */
610  }
611 
612  if (handle->iic_uart != 0) /* uart */
613  {
614  uint8_t input_buf[6 + 0];
615  uint8_t out_buf[7];
616 
617  input_buf[0] = 0x7E; /* set start */
618  input_buf[1] = 0x00; /* set addr */
619  input_buf[2] = SPS30_UART_COMMAND_STOP_MEASUREMENT; /* set command */
620  input_buf[3] = 0x00; /* set length */
621  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
622  input_buf[5] = 0x7E; /* set stop */
623  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
624  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 20, (uint8_t *)out_buf, 7); /* write read frame */
625  if (res != 0) /* check result */
626  {
627  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
628 
629  return 1; /* return error */
630  }
631  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
632  {
633  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
634 
635  return 1; /* return error */
636  }
637  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
638  {
639  return 1; /* return error */
640  }
641  }
642  else /* iic */
643  {
644  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_STOP_MEASUREMENT, NULL, 0, 20); /* stop measurement command */
645  if (res != 0) /* check result */
646  {
647  handle->debug_print("sps30: stop measurement failed.\n"); /* stop measurement failed */
648 
649  return 1; /* return error */
650  }
651  }
652 
653  return 0; /* success return 0 */
654 }
655 
668 {
669  uint8_t res;
670 
671  if (handle == NULL) /* check handle */
672  {
673  return 2; /* return error */
674  }
675  if (handle->inited != 1) /* check handle initialization */
676  {
677  return 3; /* return error */
678  }
679 
680  if (handle->iic_uart != 0) /* uart */
681  {
682  handle->debug_print("sps30: uart has no command.\n"); /* uart has no command */
683 
684  return 1; /* return error */
685  }
686  else /* iic */
687  {
688  uint8_t buf[3];
689 
690  memset(buf, 0, sizeof(uint8_t) * 3); /* clear the buffer */
691  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)buf, 3, 20); /* read data ready flag command */
692  if (res != 0) /* check result */
693  {
694  handle->debug_print("sps30: read data ready flag failed.\n"); /* read data ready flag failed */
695 
696  return 1; /* return error */
697  }
698  if (buf[2] != a_sps30_generate_crc(handle, (uint8_t *)buf, 2)) /* check crc */
699  {
700  handle->debug_print("sps30: crc check failed.\n"); /* crc check failed */
701 
702  return 1; /* return error */
703  }
704  *flag = (sps30_data_ready_flag_t)(buf[1] & 0x01); /* get the data ready flag */
705  }
706 
707  return 0; /* success return 0 */
708 }
709 
720 uint8_t sps30_sleep(sps30_handle_t *handle)
721 {
722  uint8_t res;
723 
724  if (handle == NULL) /* check handle */
725  {
726  return 2; /* return error */
727  }
728  if (handle->inited != 1) /* check handle initialization */
729  {
730  return 3; /* return error */
731  }
732 
733  if (handle->iic_uart != 0) /* uart */
734  {
735  uint8_t input_buf[6 + 0];
736  uint8_t out_buf[7];
737 
738  input_buf[0] = 0x7E; /* set start */
739  input_buf[1] = 0x00; /* set addr */
740  input_buf[2] = SPS30_UART_COMMAND_SLEEP; /* set command */
741  input_buf[3] = 0x00; /* set length */
742  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
743  input_buf[5] = 0x7E; /* set stop */
744  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
745  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 5, (uint8_t *)out_buf, 7); /* write read frame */
746  if (res != 0) /* check result */
747  {
748  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
749 
750  return 1; /* return error */
751  }
752  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
753  {
754  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
755 
756  return 1; /* return error */
757  }
758  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
759  {
760  return 1; /* return error */
761  }
762  }
763  else /* iic */
764  {
765  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_SLEEP, NULL, 0, 5); /* sleep command */
766  if (res != 0) /* check result */
767  {
768  handle->debug_print("sps30: sleep failed.\n"); /* sleep failed */
769 
770  return 1; /* return error */
771  }
772  }
773 
774  return 0; /* success return 0 */
775 }
776 
788 {
789  uint8_t res;
790 
791  if (handle == NULL) /* check handle */
792  {
793  return 2; /* return error */
794  }
795  if (handle->inited != 1) /* check handle initialization */
796  {
797  return 3; /* return error */
798  }
799 
800  if (handle->iic_uart != 0) /* uart */
801  {
802  uint8_t input_buf[6 + 0];
803  uint8_t out_buf[7];
804  uint8_t wake_up = 0xFF;
805 
806  input_buf[0] = 0x7E; /* set start */
807  input_buf[1] = 0x00; /* set addr */
808  input_buf[2] = SPS30_UART_COMMAND_WAKE_UP; /* set command */
809  input_buf[3] = 0x00; /* set length */
810  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
811  input_buf[5] = 0x7E; /* set stop */
812  if (handle->uart_write((uint8_t *)&wake_up, 1) != 0) /* write data */
813  {
814  return 1; /* return error */
815  }
816  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
817  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 100, (uint8_t *)out_buf, 7); /* write read frame */
818  if (res != 0) /* check result */
819  {
820  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
821 
822  return 1; /* return error */
823  }
824  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
825  {
826  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
827 
828  return 1; /* return error */
829  }
830  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
831  {
832  return 1; /* return error */
833  }
834  }
835  else /* iic */
836  {
837  (void)a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_WAKE_UP, NULL, 0, 0); /* wake up command */
838  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_WAKE_UP, NULL, 0, 100); /* wake up command */
839  if (res != 0) /* check result */
840  {
841  handle->debug_print("sps30: wake up failed.\n"); /* wake up failed */
842 
843  return 1; /* return error */
844  }
845  }
846 
847  return 0; /* success return 0 */
848 }
849 
861 {
862  uint8_t res;
863 
864  if (handle == NULL) /* check handle */
865  {
866  return 2; /* return error */
867  }
868  if (handle->inited != 1) /* check handle initialization */
869  {
870  return 3; /* return error */
871  }
872 
873  if (handle->iic_uart != 0) /* uart */
874  {
875  uint8_t input_buf[6 + 0];
876  uint8_t out_buf[7];
877 
878  input_buf[0] = 0x7E; /* set start */
879  input_buf[1] = 0x00; /* set addr */
880  input_buf[2] = SPS30_UART_COMMAND_START_FAN_CLEANING; /* set command */
881  input_buf[3] = 0x00; /* set length */
882  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
883  input_buf[5] = 0x7E; /* set stop */
884  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
885  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 20, (uint8_t *)out_buf, 7); /* write read frame */
886  if (res != 0) /* check result */
887  {
888  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
889 
890  return 1; /* return error */
891  }
892  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
893  {
894  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
895 
896  return 1; /* return error */
897  }
898  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
899  {
900  return 1; /* return error */
901  }
902  }
903  else /* iic */
904  {
905  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_START_FAN_CLEANING, NULL, 0, 20); /* start the fan cleaning command */
906  if (res != 0) /* check result */
907  {
908  handle->debug_print("sps30: start the fan cleaning failed.\n"); /* start the fan cleaning failed */
909 
910  return 1; /* return error */
911  }
912  }
913 
914  return 0; /* success return 0 */
915 }
916 
929 uint8_t sps30_set_auto_cleaning_interval(sps30_handle_t *handle, uint32_t second)
930 {
931  uint8_t res;
932 
933  if (handle == NULL) /* check handle */
934  {
935  return 2; /* return error */
936  }
937  if (handle->inited != 1) /* check handle initialization */
938  {
939  return 3; /* return error */
940  }
941  if ((second < 10) || (second > 604800)) /* check second */
942  {
943  handle->debug_print("sps30: second is invalid.\n"); /* second is invalid */
944 
945  return 4; /* return error */
946  }
947 
948  if (handle->iic_uart != 0) /* uart */
949  {
950  uint8_t input_buf[6 + 5];
951  uint8_t out_buf[7];
952 
953  input_buf[0] = 0x7E; /* set start */
954  input_buf[1] = 0x00; /* set addr */
955  input_buf[2] = SPS30_UART_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL; /* set command */
956  input_buf[3] = 0x05; /* set length */
957  input_buf[4] = 0x00; /* set 0x00 */
958  input_buf[5] = (second >> 24) & 0xFF; /* set 32 - 24 bits */
959  input_buf[6] = (second >> 16) & 0xFF; /* set 24 - 16 bits */
960  input_buf[7] = (second >> 8) & 0xFF; /* set 16 - 8 bits */
961  input_buf[8] = (second >> 0) & 0xFF; /* set 8 - 0 bits */
962  input_buf[9] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 8); /* set crc */
963  input_buf[10] = 0x7E; /* set stop */
964  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
965  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 11, 20, (uint8_t *)out_buf, 7); /* write read frame */
966  if (res != 0) /* check result */
967  {
968  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
969 
970  return 1; /* return error */
971  }
972  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
973  {
974  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
975 
976  return 1; /* return error */
977  }
978  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
979  {
980  return 1; /* return error */
981  }
982  }
983  else /* iic */
984  {
985  uint8_t buf[6];
986 
987  buf[0] = (second >> 24) & 0xFF; /* set byte 4 */
988  buf[1] = (second >> 16) & 0xFF; /* set byte 3 */
989  buf[2] = a_sps30_generate_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
990  buf[3] = (second >> 8) & 0xFF; /* set byte 2 */
991  buf[4] = (second >> 0) & 0xFF; /* set byte 1 */
992  buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
993  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL,
994  (uint8_t *)buf, 6, 20); /* set auto cleaning interval command */
995  if (res != 0) /* check result */
996  {
997  handle->debug_print("sps30: set auto cleaning interval failed.\n"); /* set auto cleaning interval failed */
998 
999  return 1; /* return error */
1000  }
1001  }
1002 
1003  return 0; /* success return 0 */
1004 }
1005 
1017 uint8_t sps30_get_auto_cleaning_interval(sps30_handle_t *handle, uint32_t *second)
1018 {
1019  uint8_t res;
1020 
1021  if (handle == NULL) /* check handle */
1022  {
1023  return 2; /* return error */
1024  }
1025  if (handle->inited != 1) /* check handle initialization */
1026  {
1027  return 3; /* return error */
1028  }
1029 
1030  if (handle->iic_uart != 0) /* uart */
1031  {
1032  uint8_t input_buf[6 + 1];
1033  uint8_t out_buf[7 + 4];
1034 
1035  input_buf[0] = 0x7E; /* set start */
1036  input_buf[1] = 0x00; /* set addr */
1037  input_buf[2] = SPS30_UART_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL; /* set command */
1038  input_buf[3] = 0x01; /* set length */
1039  input_buf[4] = 0x00; /* set length */
1040  input_buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 4); /* set crc */
1041  input_buf[6] = 0x7E; /* set stop */
1042  memset(out_buf, 0, sizeof(uint8_t) * 11); /* clear the buffer */
1043  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 7, 20, (uint8_t *)out_buf, 11); /* write read frame */
1044  if (res != 0) /* check result */
1045  {
1046  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1047 
1048  return 1; /* return error */
1049  }
1050  if (out_buf[9] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 8)) /* check crc */
1051  {
1052  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1053 
1054  return 1; /* return error */
1055  }
1056  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1057  {
1058  return 1; /* return error */
1059  }
1060  *second = ((uint32_t)out_buf[5] << 24) | ((uint32_t)out_buf[6] << 16) |
1061  ((uint32_t)out_buf[7] << 8) | ((uint32_t)out_buf[8] << 0); /* get second */
1062  }
1063  else /* iic */
1064  {
1065  uint8_t buf[6];
1066 
1067  memset(buf, 0, sizeof(uint8_t) * 6); /* clear the buffer */
1068  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL,
1069  (uint8_t *)buf, 6, 20); /* get auto cleaning interval command */
1070  if (res != 0) /* check result */
1071  {
1072  handle->debug_print("sps30: get auto cleaning interval failed.\n"); /* get auto cleaning interval failed */
1073 
1074  return 1; /* return error */
1075  }
1076  if (buf[2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1077  {
1078  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1079 
1080  return 1; /* return error */
1081  }
1082  if (buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1083  {
1084  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1085 
1086  return 1; /* return error */
1087  }
1088  *second = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
1089  ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0); /* get second */
1090  }
1091 
1092  return 0; /* success return 0 */
1093 }
1094 
1106 {
1107  uint8_t res;
1108  uint32_t second;
1109 
1110  if (handle == NULL) /* check handle */
1111  {
1112  return 2; /* return error */
1113  }
1114  if (handle->inited != 1) /* check handle initialization */
1115  {
1116  return 3; /* return error */
1117  }
1118 
1119  if (handle->iic_uart != 0) /* uart */
1120  {
1121  uint8_t input_buf[6 + 5];
1122  uint8_t out_buf[7];
1123 
1124  second = 0; /* disable second */
1125  input_buf[0] = 0x7E; /* set start */
1126  input_buf[1] = 0x00; /* set addr */
1127  input_buf[2] = SPS30_UART_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL; /* set command */
1128  input_buf[3] = 0x05; /* set length */
1129  input_buf[4] = 0x00; /* set length */
1130  input_buf[5] = (second >> 24) & 0xFF; /* set 32 - 24 bits */
1131  input_buf[6] = (second >> 16) & 0xFF; /* set 24 - 16 bits */
1132  input_buf[7] = (second >> 8) & 0xFF; /* set 16 - 8 bits */
1133  input_buf[8] = (second >> 0) & 0xFF; /* set 8 - 0 bits */
1134  input_buf[9] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 8); /* set crc */
1135  input_buf[10] = 0x7E; /* set stop */
1136  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1137  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 11, 20, (uint8_t *)out_buf, 7); /* write read frame */
1138  if (res != 0) /* check result */
1139  {
1140  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1141 
1142  return 1; /* return error */
1143  }
1144  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
1145  {
1146  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1147 
1148  return 1; /* return error */
1149  }
1150  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1151  {
1152  return 1; /* return error */
1153  }
1154  }
1155  else /* iic */
1156  {
1157  uint8_t buf[6];
1158 
1159  second = 0; /* disable second */
1160  buf[0] = (second >> 24) & 0xFF; /* set byte 4 */
1161  buf[1] = (second >> 16) & 0xFF; /* set byte 3 */
1162  buf[2] = a_sps30_generate_crc(handle, (uint8_t *)&buf[0], 2); /* set crc */
1163  buf[3] = (second >> 8) & 0xFF; /* set byte 2 */
1164  buf[4] = (second >> 0) & 0xFF; /* set byte 1 */
1165  buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&buf[3], 2); /* set crc */
1166  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL,
1167  (uint8_t *)buf, 6, 20); /* set auto cleaning interval command */
1168  if (res != 0) /* check result */
1169  {
1170  handle->debug_print("sps30: set auto cleaning interval failed.\n"); /* set auto cleaning interval failed */
1171 
1172  return 1; /* return error */
1173  }
1174  }
1175 
1176  return 0; /* success return 0 */
1177 }
1178 
1190 uint8_t sps30_get_product_type(sps30_handle_t *handle, char type[9])
1191 {
1192  uint8_t res, i, j;
1193 
1194  if (handle == NULL) /* check handle */
1195  {
1196  return 2; /* return error */
1197  }
1198  if (handle->inited != 1) /* check handle initialization */
1199  {
1200  return 3; /* return error */
1201  }
1202 
1203  if (handle->iic_uart != 0) /* uart */
1204  {
1205  uint8_t input_buf[6 + 1];
1206  uint8_t out_buf[7 + 9];
1207 
1208  input_buf[0] = 0x7E; /* set start */
1209  input_buf[1] = 0x00; /* set addr */
1210  input_buf[2] = SPS30_UART_COMMAND_READ_PRODUCT_TYPE; /* set command */
1211  input_buf[3] = 0x01; /* set length */
1212  input_buf[4] = 0x00; /* set length */
1213  input_buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 4); /* set crc */
1214  input_buf[6] = 0x7E; /* set stop */
1215  memset(out_buf, 0, sizeof(uint8_t) * 16); /* clear the buffer */
1216  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 7, 20, (uint8_t *)out_buf, 16); /* write read frame */
1217  if (res != 0) /* check result */
1218  {
1219  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1220 
1221  return 1; /* return error */
1222  }
1223  if (out_buf[14] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 13)) /* check crc */
1224  {
1225  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1226 
1227  return 1; /* return error */
1228  }
1229  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1230  {
1231  return 1; /* return error */
1232  }
1233  memcpy((uint8_t *)type, (uint8_t *)&out_buf[5], 9); /* copy data*/
1234  }
1235  else /* iic */
1236  {
1237  uint8_t buf[12];
1238 
1239  memset(buf, 0, sizeof(uint8_t) * 12); /* clear the buffer */
1240  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_PRODUCT_TYPE, (uint8_t *)buf, 12, 20); /* read product type command */
1241  if (res != 0) /* check result */
1242  {
1243  handle->debug_print("sps30: read product type failed.\n"); /* read product type failed */
1244 
1245  return 1; /* return error */
1246  }
1247  for (i = 0; i < 4; i++) /* check crc */
1248  {
1249  if (buf[i * 3 + 2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
1250  {
1251  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1252 
1253  return 1; /* return error */
1254  }
1255  }
1256  j = 0; /* set zero */
1257  for (i = 0; i < 4; i++) /* copy type */
1258  {
1259  type[j] = buf[i * 3 + 0]; /* set type */
1260  j++; /* j++ */
1261  type[j] = buf[i * 3 + 1]; /* set type */
1262  j++; /* j++ */
1263  }
1264  type[j] = 0; /* set type */
1265  }
1266 
1267  return 0; /* success return 0 */
1268 }
1269 
1281 uint8_t sps30_get_serial_number(sps30_handle_t *handle, char sn[17])
1282 {
1283  uint8_t res, i, j;
1284 
1285  if (handle == NULL) /* check handle */
1286  {
1287  return 2; /* return error */
1288  }
1289  if (handle->inited != 1) /* check handle initialization */
1290  {
1291  return 3; /* return error */
1292  }
1293 
1294  if (handle->iic_uart != 0) /* uart */
1295  {
1296  uint8_t input_buf[6 + 1];
1297  uint8_t out_buf[7 + 17];
1298 
1299  input_buf[0] = 0x7E; /* set start */
1300  input_buf[1] = 0x00; /* set addr */
1301  input_buf[2] = SPS30_UART_COMMAND_READ_PRODUCT_TYPE; /* set command */
1302  input_buf[3] = 0x01; /* set length */
1303  input_buf[4] = 0x03; /* set command */
1304  input_buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 4); /* set crc */
1305  input_buf[6] = 0x7E; /* set stop */
1306  memset(out_buf, 0, sizeof(uint8_t) * 24); /* clear the buffer */
1307  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 7, 20, (uint8_t *)out_buf, 24); /* write read frame */
1308  if (res != 0) /* check result */
1309  {
1310  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1311 
1312  return 1; /* return error */
1313  }
1314  if (out_buf[22] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 21)) /* check crc */
1315  {
1316  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1317 
1318  return 1; /* return error */
1319  }
1320  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1321  {
1322  return 1; /* return error */
1323  }
1324  memcpy((uint8_t *)sn, (uint8_t *)&out_buf[5], 17); /* copy data*/
1325  }
1326  else /* iic */
1327  {
1328  uint8_t buf[24];
1329 
1330  memset(buf, 0, sizeof(uint8_t) * 24); /* clear the buffer */
1331  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_SERIAL_NUMBER, (uint8_t *)buf, 24, 20); /* read serial number command */
1332  if (res != 0) /* check result */
1333  {
1334  handle->debug_print("sps30: read serial number failed.\n"); /* read serial number failed */
1335 
1336  return 1; /* return error */
1337  }
1338  for (i = 0; i < 8; i++) /* check crc */
1339  {
1340  if (buf[i * 3 + 2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
1341  {
1342  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1343 
1344  return 1; /* return error */
1345  }
1346  }
1347  j = 0; /* set zero */
1348  for (i = 0; i < 8; i++) /* copy serial number */
1349  {
1350  sn[j] = buf[i * 3 + 0]; /* set serial number */
1351  j++; /* j++ */
1352  sn[j] = buf[i * 3 + 1]; /* set serial number */
1353  j++; /* j++ */
1354  }
1355  sn[j] = 0; /* set NULL */
1356  }
1357 
1358  return 0; /* success return 0 */
1359 }
1360 
1373 uint8_t sps30_get_version(sps30_handle_t *handle, uint8_t *major, uint8_t *minor)
1374 {
1375  uint8_t res;
1376  uint8_t buf[3];
1377 
1378  if (handle == NULL) /* check handle */
1379  {
1380  return 2; /* return error */
1381  }
1382  if (handle->inited != 1) /* check handle initialization */
1383  {
1384  return 3; /* return error */
1385  }
1386 
1387  if (handle->iic_uart != 0) /* uart */
1388  {
1389  uint8_t input_buf[6];
1390  uint8_t out_buf[7 + 7];
1391 
1392  input_buf[0] = 0x7E; /* set start */
1393  input_buf[1] = 0x00; /* set addr */
1394  input_buf[2] = SPS30_UART_COMMAND_READ_VERSION; /* set command */
1395  input_buf[3] = 0x00; /* set length */
1396  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
1397  input_buf[5] = 0x7E; /* set stop */
1398  memset(out_buf, 0, sizeof(uint8_t) * 14); /* clear the buffer */
1399  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 20, (uint8_t *)out_buf, 14); /* write read frame */
1400  if (res != 0) /* check result */
1401  {
1402  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1403 
1404  return 1; /* return error */
1405  }
1406  if (out_buf[12] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 11)) /* check crc */
1407  {
1408  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1409 
1410  return 1; /* return error */
1411  }
1412  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1413  {
1414  return 1; /* return error */
1415  }
1416  *major = out_buf[5]; /* set major */
1417  *minor = out_buf[6]; /* set minor */
1418  }
1419  else /* iic */
1420  {
1421  memset(buf, 0, sizeof(uint8_t) * 3); /* clear the buffer */
1422  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_VERSION, (uint8_t *)buf, 3, 20); /* read version command */
1423  if (res != 0) /* check result */
1424  {
1425  handle->debug_print("sps30: read version failed.\n"); /* read version failed */
1426 
1427  return 1; /* return error */
1428  }
1429  if (buf[2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1430  {
1431  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1432 
1433  return 1; /* return error */
1434  }
1435  *major = buf[0]; /* set major */
1436  *minor = buf[1]; /* set minor */
1437  }
1438 
1439  return 0; /* success return 0 */
1440 }
1441 
1453 uint8_t sps30_get_device_status(sps30_handle_t *handle, uint32_t *status)
1454 {
1455  uint8_t res;
1456 
1457  if (handle == NULL) /* check handle */
1458  {
1459  return 2; /* return error */
1460  }
1461  if (handle->inited != 1) /* check handle initialization */
1462  {
1463  return 3; /* return error */
1464  }
1465 
1466  if (handle->iic_uart != 0) /* uart */
1467  {
1468  uint8_t input_buf[6 + 1];
1469  uint8_t out_buf[7 + 5];
1470 
1471  input_buf[0] = 0x7E; /* set start */
1472  input_buf[1] = 0x00; /* set addr */
1473  input_buf[2] = SPS30_UART_COMMAND_READ_DEVICE_STATUS_REG; /* set command */
1474  input_buf[3] = 0x01; /* set length */
1475  input_buf[4] = 0x00; /* set 0x00 */
1476  input_buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 4); /* set crc */
1477  input_buf[6] = 0x7E; /* set stop */
1478  memset(out_buf, 0, sizeof(uint8_t) * 12); /* clear the buffer */
1479  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 7, 20, (uint8_t *)out_buf, 12); /* write read frame */
1480  if (res != 0) /* check result */
1481  {
1482  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1483 
1484  return 1; /* return error */
1485  }
1486  if (out_buf[10] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 9)) /* check crc */
1487  {
1488  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1489 
1490  return 1; /* return error */
1491  }
1492  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1493  {
1494  return 1; /* return error */
1495  }
1496  *status = ((uint32_t)out_buf[5] << 24) | ((uint32_t)out_buf[6] << 16) |
1497  ((uint32_t)out_buf[7] << 8) | ((uint32_t)out_buf[8] << 0); /* get status */
1498  }
1499  else /* iic */
1500  {
1501  uint8_t buf[6];
1502 
1503  memset(buf, 0, sizeof(uint8_t) * 6); /* clear the buffer */
1504  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_DEVICE_STATUS_REG,
1505  (uint8_t *)buf, 6, 20); /* get device status command */
1506  if (res != 0) /* check result */
1507  {
1508  handle->debug_print("sps30: get device status failed.\n"); /* get device status failed */
1509 
1510  return 1; /* return error */
1511  }
1512  if (buf[2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[0], 2)) /* check crc */
1513  {
1514  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1515 
1516  return 1; /* return error */
1517  }
1518  if (buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&buf[3], 2)) /* check crc */
1519  {
1520  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1521 
1522  return 1; /* return error */
1523  }
1524  *status = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
1525  ((uint32_t)buf[3] << 8) | ((uint32_t)buf[4] << 0); /* get status */
1526  }
1527 
1528  return 0; /* success return 0 */
1529 }
1530 
1542 {
1543  uint8_t res;
1544 
1545  if (handle == NULL) /* check handle */
1546  {
1547  return 2; /* return error */
1548  }
1549  if (handle->inited != 1) /* check handle initialization */
1550  {
1551  return 3; /* return error */
1552  }
1553 
1554  if (handle->iic_uart != 0) /* uart */
1555  {
1556  uint8_t input_buf[6 + 1];
1557  uint8_t out_buf[7 + 5];
1558 
1559  input_buf[0] = 0x7E; /* set start */
1560  input_buf[1] = 0x00; /* set addr */
1561  input_buf[2] = SPS30_UART_COMMAND_READ_DEVICE_STATUS_REG; /* set command */
1562  input_buf[3] = 0x01; /* set length */
1563  input_buf[4] = 0x01; /* set 0x01 */
1564  input_buf[5] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 4); /* set crc */
1565  input_buf[6] = 0x7E; /* set stop */
1566  memset(out_buf, 0, sizeof(uint8_t) * 12); /* clear the buffer */
1567  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 7, 20, (uint8_t *)out_buf, 12); /* write read frame */
1568  if (res != 0) /* check result */
1569  {
1570  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1571 
1572  return 1; /* return error */
1573  }
1574  if (out_buf[10] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 9)) /* check crc */
1575  {
1576  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1577 
1578  return 1; /* return error */
1579  }
1580  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1581  {
1582  return 1; /* return error */
1583  }
1584  }
1585  else /* iic */
1586  {
1587  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_CLEAR_DEVICE_STATUS_REG, NULL, 0, 20); /* clear device status command */
1588  if (res != 0) /* check result */
1589  {
1590  handle->debug_print("sps30: clear device status failed.\n"); /* clear device status failed */
1591 
1592  return 1; /* return error */
1593  }
1594  }
1595 
1596  return 0; /* success return 0 */
1597 }
1598 
1609 uint8_t sps30_reset(sps30_handle_t *handle)
1610 {
1611  uint8_t res;
1612 
1613  if (handle == NULL) /* check handle */
1614  {
1615  return 2; /* return error */
1616  }
1617  if (handle->inited != 1) /* check handle initialization */
1618  {
1619  return 3; /* return error */
1620  }
1621 
1622  if (handle->iic_uart != 0) /* uart */
1623  {
1624  uint8_t input_buf[6];
1625  uint8_t out_buf[7];
1626 
1627  input_buf[0] = 0x7E; /* set start */
1628  input_buf[1] = 0x00; /* set addr */
1629  input_buf[2] = SPS30_UART_COMMAND_RESET; /* set command */
1630  input_buf[3] = 0x00; /* set length */
1631  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
1632  input_buf[5] = 0x7E; /* set stop */
1633  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
1634  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 100, (uint8_t *)out_buf, 7); /* write read frame */
1635  if (res != 0) /* check result */
1636  {
1637  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1638 
1639  return 1; /* return error */
1640  }
1641  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
1642  {
1643  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1644 
1645  return 1; /* return error */
1646  }
1647  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1648  {
1649  return 1; /* return error */
1650  }
1651  }
1652  else /* iic */
1653  {
1654  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_RESET, NULL, 0, 100); /* reset command */
1655  if (res != 0) /* check result */
1656  {
1657  handle->debug_print("sps30: reset failed.\n"); /* reset failed */
1658 
1659  return 1; /* return error */
1660  }
1661  }
1662 
1663  return 0; /* success return 0 */
1664 }
1665 
1678 uint8_t sps30_read(sps30_handle_t *handle, sps30_pm_t *pm)
1679 {
1680  union float_u
1681  {
1682  float f;
1683  uint32_t i;
1684  };
1685  uint8_t res, i;
1686  union float_u f;
1687 
1688  if ((handle == NULL) || (pm == NULL)) /* check handle */
1689  {
1690  return 2; /* return error */
1691  }
1692  if (handle->inited != 1) /* check handle initialization */
1693  {
1694  return 3; /* return error */
1695  }
1696 
1697  if (handle->iic_uart != 0) /* uart */
1698  {
1699  if (handle->format == SPS30_FORMAT_IEEE754) /* float */
1700  {
1701  uint8_t input_buf[6];
1702  uint8_t out_buf[7 + 40];
1703 
1704  input_buf[0] = 0x7E; /* set start */
1705  input_buf[1] = 0x00; /* set addr */
1706  input_buf[2] = SPS30_UART_COMMAND_READ_MEASURED_VALUES; /* set command */
1707  input_buf[3] = 0x00; /* set length */
1708  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
1709  input_buf[5] = 0x7E; /* set stop */
1710  memset(out_buf, 0, sizeof(uint8_t) * 47); /* clear the buffer */
1711  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 20, (uint8_t *)out_buf, 47); /* write read frame */
1712  if (res != 0) /* check result */
1713  {
1714  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1715 
1716  return 1; /* return error */
1717  }
1718  if (out_buf[45] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 44)) /* check crc */
1719  {
1720  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1721 
1722  return 1; /* return error */
1723  }
1724  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1725  {
1726  return 1; /* return error */
1727  }
1728  f.i = (uint32_t)(out_buf[5 + 0]) << 24 | (uint32_t)(out_buf[5 + 1]) << 16 |
1729  (uint32_t)(out_buf[5 + 2]) << 8 | (uint32_t)(out_buf[5 + 3]) << 0; /* copy data */
1730  pm->pm1p0_ug_m3 = f.f; /* copy pm1.0 ug/m3 */
1731  f.i = (uint32_t)(out_buf[5 + 4]) << 24 | (uint32_t)(out_buf[5 + 5]) << 16 |
1732  (uint32_t)(out_buf[5 + 6]) << 8 | (uint32_t)(out_buf[5 + 7]) << 0; /* copy data */
1733  pm->pm2p5_ug_m3 = f.f; /* copy pm2.5 ug/m3 */
1734  f.i = (uint32_t)(out_buf[5 + 8]) << 24 | (uint32_t)(out_buf[5 + 9]) << 16 |
1735  (uint32_t)(out_buf[5 + 10]) << 8 | (uint32_t)(out_buf[5 + 11]) << 0; /* copy data */
1736  pm->pm4p0_ug_m3 = f.f; /* copy pm4.0 ug/m3 */
1737  f.i = (uint32_t)(out_buf[5 + 12]) << 24 | (uint32_t)(out_buf[5 + 13]) << 16 |
1738  (uint32_t)(out_buf[5 + 14]) << 8 | (uint32_t)(out_buf[5 + 15]) << 0; /* copy data */
1739  pm->pm10_ug_m3 = f.f; /* copy pm10.0 ug/m3 */
1740  f.i = (uint32_t)(out_buf[5 + 16]) << 24 | (uint32_t)(out_buf[5 + 17]) << 16 |
1741  (uint32_t)(out_buf[5 + 18]) << 8 | (uint32_t)(out_buf[5 + 19]) << 0; /* copy data */
1742  pm->pm0p5_cm3 = f.f; /* copy pm0.5 cm3 */
1743  f.i = (uint32_t)(out_buf[5 + 20]) << 24 | (uint32_t)(out_buf[5 + 21]) << 16 |
1744  (uint32_t)(out_buf[5 + 22]) << 8 | (uint32_t)(out_buf[5 + 23]) << 0; /* copy data */
1745  pm->pm1p0_cm3 = f.f; /* copy pm1.0 cm3 */
1746  f.i = (uint32_t)(out_buf[5 + 24]) << 24 | (uint32_t)(out_buf[5 + 25]) << 16 |
1747  (uint32_t)(out_buf[5 + 26]) << 8 | (uint32_t)(out_buf[5 + 27]) << 0; /* copy data */
1748  pm->pm2p5_cm3 = f.f; /* copy pm2.5 cm3 */
1749  f.i = (uint32_t)(out_buf[5 + 28]) << 24 | (uint32_t)(out_buf[5 + 29]) << 16 |
1750  (uint32_t)(out_buf[5 + 30]) << 8 | (uint32_t)(out_buf[5 + 31]) << 0; /* copy data */
1751  pm->pm4p0_cm3 = f.f; /* copy pm4.0 cm3 */
1752  f.i = (uint32_t)(out_buf[5 + 32]) << 24 | (uint32_t)(out_buf[5 + 33]) << 16 |
1753  (uint32_t)(out_buf[5 + 34]) << 8 | (uint32_t)(out_buf[5 + 35]) << 0; /* copy data */
1754  pm->pm10_cm3 = f.f; /* copy pm10.0 cm3 */
1755  f.i = (uint32_t)(out_buf[5 + 36]) << 24 | (uint32_t)(out_buf[5 + 37]) << 16 |
1756  (uint32_t)(out_buf[5 + 38]) << 8 | (uint32_t)(out_buf[5 + 39]) << 0; /* copy data */
1757  pm->typical_particle_um = f.f; /* copy typical particle um */
1758  }
1759  else if (handle->format == SPS30_FORMAT_UINT16) /* uint16 */
1760  {
1761  uint8_t input_buf[6];
1762  uint8_t out_buf[7 + 20];
1763 
1764  input_buf[0] = 0x7E; /* set start */
1765  input_buf[1] = 0x00; /* set addr */
1766  input_buf[2] = SPS30_UART_COMMAND_READ_MEASURED_VALUES; /* set command */
1767  input_buf[3] = 0x00; /* set length */
1768  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
1769  input_buf[5] = 0x7E; /* set stop */
1770  memset(out_buf, 0, sizeof(uint8_t) * 27); /* clear the buffer */
1771  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 20, (uint8_t *)out_buf, 27); /* write read frame */
1772  if (res != 0) /* check result */
1773  {
1774  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
1775 
1776  return 1; /* return error */
1777  }
1778  if (out_buf[25] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 24)) /* check crc */
1779  {
1780  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
1781 
1782  return 1; /* return error */
1783  }
1784  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
1785  {
1786  return 1; /* return error */
1787  }
1788  pm->pm1p0_ug_m3 = (float)(((uint16_t)(out_buf[5 + 0]) << 8) | ((uint16_t)(out_buf[5 + 1]) << 0)); /* copy pm1.0 ug/m3 */
1789  pm->pm2p5_ug_m3 = (float)(((uint16_t)(out_buf[5 + 2]) << 8) | ((uint16_t)(out_buf[5 + 3]) << 0)); /* copy pm2.5 ug/m3 */
1790  pm->pm4p0_ug_m3 = (float)(((uint16_t)(out_buf[5 + 4]) << 8) | ((uint16_t)(out_buf[5 + 5]) << 0)); /* copy pm4.0 ug/m3 */
1791  pm->pm10_ug_m3 = (float)(((uint16_t)(out_buf[5 + 6]) << 8) | ((uint16_t)(out_buf[5 + 7]) << 0)); /* copy pm10 ug/m3 */
1792  pm->pm0p5_cm3 = (float)(((uint16_t)(out_buf[5 + 8]) << 8) | ((uint16_t)(out_buf[5 + 9]) << 0)); /* copy pm0.5 cm3 */
1793  pm->pm1p0_cm3 = (float)(((uint16_t)(out_buf[5 + 10]) << 8) | ((uint16_t)(out_buf[5 + 11]) << 0)); /* copy pm1.0 cm3 */
1794  pm->pm2p5_cm3 = (float)(((uint16_t)(out_buf[5 + 12]) << 8) | ((uint16_t)(out_buf[5 + 13]) << 0)); /* copy pm2.5 cm3 */
1795  pm->pm4p0_cm3 = (float)(((uint16_t)(out_buf[5 + 14]) << 8) | ((uint16_t)(out_buf[5 + 15]) << 0)); /* copy pm4.0 cm3 */
1796  pm->pm10_cm3 = (float)(((uint16_t)(out_buf[5 + 16]) << 8) | ((uint16_t)(out_buf[5 + 17]) << 0)); /* copy pm10 cm3 */
1797  pm->typical_particle_um = (float)(((uint16_t)(out_buf[5 + 18]) << 8) | ((uint16_t)(out_buf[5 + 19]) << 0)); /* copy typical particle */
1798  pm->typical_particle_um /= 1000.0f; /* div 1000 */
1799  }
1800  else
1801  {
1802  handle->debug_print("sps30: mode is invalid.\n"); /* mode is invalid */
1803 
1804  return 4; /* return error */
1805  }
1806  }
1807  else /* iic */
1808  {
1809  uint8_t check[3];
1810 
1811  memset(check, 0, sizeof(uint8_t) * 3); /* clear the buffer */
1812  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_DATA_READY_FLAG, (uint8_t *)check, 3, 20); /* read data ready flag command */
1813  if (res != 0) /* check result */
1814  {
1815  handle->debug_print("sps30: read data ready flag failed.\n"); /* read data ready flag failed */
1816 
1817  return 1; /* return error */
1818  }
1819  if (check[2] != a_sps30_generate_crc(handle, (uint8_t *)check, 2)) /* check crc */
1820  {
1821  handle->debug_print("sps30: crc check failed.\n"); /* crc check failed */
1822 
1823  return 1; /* return error */
1824  }
1825  if ((check[1] & 0x01) == 0) /* check flag */
1826  {
1827  handle->debug_print("sps30: data not ready.\n"); /* data not ready */
1828 
1829  return 1; /* return error */
1830  }
1831 
1832  if (handle->format == SPS30_FORMAT_IEEE754) /* float */
1833  {
1834  uint8_t buf[60];
1835 
1836  memset(buf, 0, sizeof(uint8_t) * 60); /* clear the buffer */
1837  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_MEASURED_VALUES, (uint8_t *)buf, 60, 20); /* read measured values command */
1838  if (res != 0) /* check result */
1839  {
1840  handle->debug_print("sps30: read measured values failed.\n"); /* read measured values failed */
1841 
1842  return 1; /* return error */
1843  }
1844  for (i = 0; i < 20; i++) /* check crc */
1845  {
1846  if (buf[i * 3 + 2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
1847  {
1848  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1849 
1850  return 1; /* return error */
1851  }
1852  }
1853  f.i = (uint32_t)(buf[0]) << 24 | (uint32_t)(buf[1]) << 16 |
1854  (uint32_t)(buf[3]) << 8 | (uint32_t)(buf[4]) << 0; /* copy data */
1855  pm->pm1p0_ug_m3 = f.f; /* copy pm1.0 ug/m3 */
1856  f.i = (uint32_t)(buf[6]) << 24 | (uint32_t)(buf[7]) << 16 |
1857  (uint32_t)(buf[9]) << 8 | (uint32_t)(buf[10]) << 0; /* copy data */
1858  pm->pm2p5_ug_m3 = f.f; /* copy pm2.5 ug/m3 */
1859  f.i = (uint32_t)(buf[12]) << 24 | (uint32_t)(buf[13]) << 16 |
1860  (uint32_t)(buf[15]) << 8 | (uint32_t)(buf[16]) << 0; /* copy data */
1861  pm->pm4p0_ug_m3 = f.f; /* copy pm4.0 ug/m3 */
1862  f.i = (uint32_t)(buf[18]) << 24 | (uint32_t)(buf[19]) << 16 |
1863  (uint32_t)(buf[21]) << 8 | (uint32_t)(buf[22]) << 0; /* copy data */
1864  pm->pm10_ug_m3 = f.f; /* copy pm10.0 ug/m3 */
1865  f.i = (uint32_t)(buf[24]) << 24 | (uint32_t)(buf[25]) << 16 |
1866  (uint32_t)(buf[27]) << 8 | (uint32_t)(buf[28]) << 0; /* copy data */
1867  pm->pm0p5_cm3 = f.f; /* copy pm0.5 cm3 */
1868  f.i = (uint32_t)(buf[30]) << 24 | (uint32_t)(buf[31]) << 16 |
1869  (uint32_t)(buf[33]) << 8 | (uint32_t)(buf[34]) << 0; /* copy data */
1870  pm->pm1p0_cm3 = f.f; /* copy pm1.0 cm3 */
1871  f.i = (uint32_t)(buf[36]) << 24 | (uint32_t)(buf[37]) << 16 |
1872  (uint32_t)(buf[39]) << 8 | (uint32_t)(buf[40]) << 0; /* copy data */
1873  pm->pm2p5_cm3 = f.f; /* copy pm2.5 cm3 */
1874  f.i = (uint32_t)(buf[42]) << 24 | (uint32_t)(buf[43]) << 16 |
1875  (uint32_t)(buf[45]) << 8 | (uint32_t)(buf[46]) << 0; /* copy data */
1876  pm->pm4p0_cm3 = f.f; /* copy pm4.0 cm3 */
1877  f.i = (uint32_t)(buf[48]) << 24 | (uint32_t)(buf[49]) << 16 |
1878  (uint32_t)(buf[51]) << 8 | (uint32_t)(buf[52]) << 0; /* copy data */
1879  pm->pm10_cm3 = f.f; /* copy pm10.0 cm3 */
1880  f.i = (uint32_t)(buf[54]) << 24 | (uint32_t)(buf[55]) << 16 |
1881  (uint32_t)(buf[57]) << 8 | (uint32_t)(buf[58]) << 0; /* copy data */
1882  pm->typical_particle_um = f.f; /* copy typical particle um */
1883  }
1884  else if (handle->format == SPS30_FORMAT_UINT16) /* uint16 */
1885  {
1886  uint8_t buf[30];
1887 
1888  memset(buf, 0, sizeof(uint8_t) * 30); /* clear the buffer */
1889  res = a_sps30_iic_read(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_READ_MEASURED_VALUES, (uint8_t *)buf, 30, 20); /* read measured values command */
1890  if (res != 0) /* check result */
1891  {
1892  handle->debug_print("sps30: read measured values failed.\n"); /* read measured values failed */
1893 
1894  return 1; /* return error */
1895  }
1896  for (i = 0; i < 10; i++) /* check crc */
1897  {
1898  if (buf[i * 3 + 2] != a_sps30_generate_crc(handle, (uint8_t *)&buf[i * 3], 2)) /* check crc */
1899  {
1900  handle->debug_print("sps30: crc is error.\n"); /* crc is error */
1901 
1902  return 1; /* return error */
1903  }
1904  }
1905  pm->pm1p0_ug_m3 = (float)(((uint16_t)(buf[0]) << 8) | ((uint16_t)(buf[1]) << 0)); /* copy pm1.0 ug/m3 */
1906  pm->pm2p5_ug_m3 = (float)(((uint16_t)(buf[3]) << 8) | ((uint16_t)(buf[4]) << 0)); /* copy pm2.5 ug/m3 */
1907  pm->pm4p0_ug_m3 = (float)(((uint16_t)(buf[6]) << 8) | ((uint16_t)(buf[7]) << 0)); /* copy pm4.0 ug/m3 */
1908  pm->pm10_ug_m3 = (float)(((uint16_t)(buf[9]) << 8) | ((uint16_t)(buf[10]) << 0)); /* copy pm10 ug/m3 */
1909  pm->pm0p5_cm3 = (float)(((uint16_t)(buf[12]) << 8) | ((uint16_t)(buf[13]) << 0)); /* copy pm0.5 cm3 */
1910  pm->pm1p0_cm3 = (float)(((uint16_t)(buf[15]) << 8) | ((uint16_t)(buf[16]) << 0)); /* copy pm1.0 cm3 */
1911  pm->pm2p5_cm3 = (float)(((uint16_t)(buf[18]) << 8) | ((uint16_t)(buf[19]) << 0)); /* copy pm2.5 cm3 */
1912  pm->pm4p0_cm3 = (float)(((uint16_t)(buf[21]) << 8) | ((uint16_t)(buf[22]) << 0)); /* copy pm4.0 cm3 */
1913  pm->pm10_cm3 = (float)(((uint16_t)(buf[24]) << 8) | ((uint16_t)(buf[25]) << 0)); /* copy pm10 cm3 */
1914  pm->typical_particle_um = (float)(((uint16_t)(buf[27]) << 8) | ((uint16_t)(buf[28]) << 0)); /* copy typical particle */
1915  pm->typical_particle_um /= 1000.0f; /* div 1000 */
1916  }
1917  else
1918  {
1919  handle->debug_print("sps30: mode is invalid.\n"); /* mode is invalid */
1920 
1921  return 4; /* return error */
1922  }
1923  }
1924 
1925  return 0; /* success return 0 */
1926 }
1927 
1939 uint8_t sps30_init(sps30_handle_t *handle)
1940 {
1941  uint8_t res;
1942 
1943  if (handle == NULL) /* check handle */
1944  {
1945  return 2; /* return error */
1946  }
1947  if (handle->debug_print == NULL) /* check debug_print */
1948  {
1949  return 3; /* return error */
1950  }
1951  if (handle->iic_init == NULL) /* check iic_init */
1952  {
1953  handle->debug_print("sps30: iic_init is null.\n"); /* iic_init is null */
1954 
1955  return 3; /* return error */
1956  }
1957  if (handle->iic_deinit == NULL) /* check iic_deinit */
1958  {
1959  handle->debug_print("sps30: iic_deinit is null.\n"); /* iic_deinit is null */
1960 
1961  return 3; /* return error */
1962  }
1963  if (handle->iic_write_cmd == NULL) /* check iic_write_cmd */
1964  {
1965  handle->debug_print("sps30: iic_write_cmd is null.\n"); /* iic_write_cmd is null */
1966 
1967  return 3; /* return error */
1968  }
1969  if (handle->iic_read_cmd == NULL) /* check iic_read_cmd */
1970  {
1971  handle->debug_print("sps30: iic_read_cmd is null.\n"); /* iic_read_cmd is null */
1972 
1973  return 3; /* return error */
1974  }
1975  if (handle->uart_init == NULL) /* check uart_init */
1976  {
1977  handle->debug_print("sps30: uart_init is null.\n"); /* uart_init is null */
1978 
1979  return 3; /* return error */
1980  }
1981  if (handle->uart_deinit == NULL) /* check uart_deinit */
1982  {
1983  handle->debug_print("sps30: uart_deinit is null.\n"); /* uart_deinit is null */
1984 
1985  return 3; /* return error */
1986  }
1987  if (handle->uart_read == NULL) /* check uart_read */
1988  {
1989  handle->debug_print("sps30: uart_read is null.\n"); /* uart_read is null */
1990 
1991  return 3; /* return error */
1992  }
1993  if (handle->uart_write == NULL) /* check uart_write */
1994  {
1995  handle->debug_print("sps30: uart_write is null.\n"); /* uart_write is null */
1996 
1997  return 3; /* return error */
1998  }
1999  if (handle->uart_flush == NULL) /* check uart_flush */
2000  {
2001  handle->debug_print("sps30: uart_flush is null.\n"); /* uart_flush is null */
2002 
2003  return 3; /* return error */
2004  }
2005  if (handle->delay_ms == NULL) /* check delay_ms */
2006  {
2007  handle->debug_print("sps30: delay_ms is null.\n"); /* delay_ms is null */
2008 
2009  return 3; /* return error */
2010  }
2011 
2012  if (handle->iic_uart != 0)
2013  {
2014  uint8_t input_buf[6];
2015  uint8_t out_buf[7];
2016 
2017  if (handle->uart_init() != 0) /* uart init */
2018  {
2019  handle->debug_print("sps30: uart init failed.\n"); /* uart init failed */
2020 
2021  return 1; /* return error */
2022  }
2023  input_buf[0] = 0x7E; /* set start */
2024  input_buf[1] = 0x00; /* set addr */
2025  input_buf[2] = SPS30_UART_COMMAND_RESET; /* set command */
2026  input_buf[3] = 0x00; /* set length */
2027  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
2028  input_buf[5] = 0x7E; /* set stop */
2029  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
2030  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 100, (uint8_t *)out_buf, 7); /* write read frame */
2031  if (res != 0) /* check result */
2032  {
2033  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
2034  (void)handle->uart_deinit(); /* uart deinit */
2035 
2036  return 4; /* return error */
2037  }
2038  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
2039  {
2040  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
2041  (void)handle->uart_deinit(); /* uart deinit */
2042 
2043  return 4; /* return error */
2044  }
2045  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
2046  {
2047  (void)handle->uart_deinit(); /* uart deinit */
2048 
2049  return 4; /* return error */
2050  }
2051  }
2052  else
2053  {
2054  if (handle->iic_init() != 0) /* iic init */
2055  {
2056  handle->debug_print("sps30: iic init failed.\n"); /* iic init failed */
2057 
2058  return 1; /* return error */
2059  }
2060  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_RESET, NULL, 0, 100); /* reset command */
2061  if (res != 0) /* check result */
2062  {
2063  handle->debug_print("sps30: reset failed.\n"); /* reset failed */
2064  (void)handle->iic_deinit(); /* iic deinit */
2065 
2066  return 4; /* return error */
2067  }
2068  }
2069  handle->inited = 1; /* flag finish initialization */
2070 
2071  return 0; /* success return 0 */
2072 }
2073 
2086 {
2087  uint8_t res;
2088 
2089  if (handle == NULL) /* check handle */
2090  {
2091  return 2; /* return error */
2092  }
2093  if (handle->inited != 1) /* check handle initialization */
2094  {
2095  return 3; /* return error */
2096  }
2097 
2098  if (handle->iic_uart != 0)
2099  {
2100  uint8_t input_buf[6];
2101  uint8_t out_buf[7];
2102 
2103  input_buf[0] = 0x7E; /* set start */
2104  input_buf[1] = 0x00; /* set addr */
2105  input_buf[2] = SPS30_UART_COMMAND_RESET; /* set command */
2106  input_buf[3] = 0x00; /* set length */
2107  input_buf[4] = a_sps30_generate_crc(handle, (uint8_t *)&input_buf[1], 3); /* set crc */
2108  input_buf[5] = 0x7E; /* set stop */
2109  memset(out_buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
2110  res = a_sps30_uart_write_read(handle, (uint8_t *)input_buf, 6, 100, (uint8_t *)out_buf, 7); /* write read frame */
2111  if (res != 0) /* check result */
2112  {
2113  handle->debug_print("sps30: write read failed.\n"); /* write read failed */
2114 
2115  return 4; /* return error */
2116  }
2117  if (out_buf[5] != a_sps30_generate_crc(handle, (uint8_t *)&out_buf[1], 4)) /* check crc */
2118  {
2119  handle->debug_print("sps30: crc check error.\n"); /* crc check error */
2120 
2121  return 4; /* return error */
2122  }
2123  if (a_sps30_uart_error(handle, out_buf[3]) != 0) /* check status */
2124  {
2125  return 4; /* return error */
2126  }
2127  if (handle->uart_deinit() != 0) /* uart deinit */
2128  {
2129  handle->debug_print("sps30: uart deinit failed.\n"); /* uart deinit failed */
2130 
2131  return 1; /* return error */
2132  }
2133  }
2134  else
2135  {
2136  res = a_sps30_iic_write(handle, SPS30_ADDRESS, SPS30_IIC_COMMAND_RESET, NULL, 0, 100); /* reset command */
2137  if (res != 0) /* check result */
2138  {
2139  handle->debug_print("sps30: reset failed.\n"); /* reset failed */
2140 
2141  return 4; /* return error */
2142  }
2143  res = handle->iic_deinit(); /* iic deinit */
2144  if (res != 0) /* check result */
2145  {
2146  handle->debug_print("sps30: iic deinit failed.\n"); /* iic deinit */
2147 
2148  return 1; /* return error */
2149  }
2150  }
2151 
2152  handle->inited = 0; /* flag close initialization */
2153 
2154  return 0; /* success return 0 */
2155 }
2156 
2169 uint8_t sps30_set_get_reg_uart(sps30_handle_t *handle, uint8_t *input, uint16_t in_len, uint8_t *output, uint16_t out_len)
2170 {
2171  if (handle == NULL) /* check handle */
2172  {
2173  return 2; /* return error */
2174  }
2175  if (handle->inited != 1) /* check handle initialization */
2176  {
2177  return 3; /* return error */
2178  }
2179 
2180  if (handle->iic_uart != 0)
2181  {
2182  return a_sps30_uart_write_read(handle, input, in_len, 20, output, out_len); /* write and read with the uart interface */
2183  }
2184  else
2185  {
2186  handle->debug_print("sps30: iic interface is invalid.\n"); /* iic interface is invalid */
2187 
2188  return 1; /* return error */
2189  }
2190 }
2191 
2205 uint8_t sps30_set_reg_iic(sps30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
2206 {
2207  if (handle == NULL) /* check handle */
2208  {
2209  return 2; /* return error */
2210  }
2211  if (handle->inited != 1) /* check handle initialization */
2212  {
2213  return 3; /* return error */
2214  }
2215 
2216  if (handle->iic_uart != 0)
2217  {
2218  handle->debug_print("sps30: uart interface is invalid.\n"); /* uart interface is invalid */
2219 
2220  return 1; /* return error */
2221  }
2222  else
2223  {
2224  return a_sps30_iic_write(handle, SPS30_ADDRESS, reg, buf, len, 20); /* write the data */
2225  }
2226 }
2227 
2241 uint8_t sps30_get_reg_iic(sps30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
2242 {
2243  if (handle == NULL) /* check handle */
2244  {
2245  return 2; /* return error */
2246  }
2247  if (handle->inited != 1) /* check handle initialization */
2248  {
2249  return 3; /* return error */
2250  }
2251 
2252  if (handle->iic_uart != 0)
2253  {
2254  handle->debug_print("sps30: uart interface is invalid.\n"); /* uart interface is invalid */
2255 
2256  return 1;
2257  }
2258  else
2259  {
2260  return a_sps30_iic_read(handle, SPS30_ADDRESS, reg, buf, len, 20); /* read the data */
2261  }
2262 }
2263 
2272 uint8_t sps30_info(sps30_info_t *info)
2273 {
2274  if (info == NULL) /* check handle */
2275  {
2276  return 2; /* return error */
2277  }
2278 
2279  memset(info, 0, sizeof(sps30_info_t)); /* initialize sps30 info structure */
2280  strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */
2281  strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */
2282  strncpy(info->interface, "UART IIC", 16); /* copy interface name */
2283  info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */
2284  info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */
2285  info->max_current_ma = MAX_CURRENT; /* set maximum current */
2286  info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */
2287  info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */
2288  info->driver_version = DRIVER_VERSION; /* set driver version */
2289 
2290  return 0; /* success return 0 */
2291 }
#define SPS30_UART_COMMAND_WAKE_UP
Definition: driver_sps30.c:77
#define SPS30_UART_COMMAND_START_FAN_CLEANING
Definition: driver_sps30.c:78
#define MAX_CURRENT
Definition: driver_sps30.c:46
#define SPS30_IIC_COMMAND_READ_DATA_READY_FLAG
Definition: driver_sps30.c:61
#define SPS30_UART_COMMAND_READ_MEASURED_VALUES
Definition: driver_sps30.c:75
#define SPS30_IIC_COMMAND_CLEAR_DEVICE_STATUS_REG
Definition: driver_sps30.c:71
#define SPS30_UART_COMMAND_SLEEP
Definition: driver_sps30.c:76
#define SPS30_IIC_COMMAND_READ_SERIAL_NUMBER
Definition: driver_sps30.c:68
#define SPS30_IIC_COMMAND_START_MEASUREMENT
chip command definition
Definition: driver_sps30.c:59
#define SPS30_UART_COMMAND_READ_DEVICE_STATUS_REG
Definition: driver_sps30.c:82
#define SPS30_UART_COMMAND_RESET
Definition: driver_sps30.c:83
#define SPS30_UART_COMMAND_STOP_MEASUREMENT
Definition: driver_sps30.c:74
#define SPS30_UART_COMMAND_READ_VERSION
Definition: driver_sps30.c:81
#define SPS30_UART_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL
Definition: driver_sps30.c:79
#define SPS30_UART_COMMAND_START_MEASUREMENT
Definition: driver_sps30.c:73
#define SUPPLY_VOLTAGE_MAX
Definition: driver_sps30.c:45
#define SPS30_IIC_COMMAND_READ_WRITE_AUTO_CLEANING_INTERVAL
Definition: driver_sps30.c:66
#define SPS30_IIC_COMMAND_SLEEP
Definition: driver_sps30.c:63
#define SPS30_IIC_COMMAND_READ_PRODUCT_TYPE
Definition: driver_sps30.c:67
#define SPS30_IIC_COMMAND_READ_VERSION
Definition: driver_sps30.c:69
#define TEMPERATURE_MAX
Definition: driver_sps30.c:48
#define MANUFACTURER_NAME
Definition: driver_sps30.c:43
#define TEMPERATURE_MIN
Definition: driver_sps30.c:47
#define SUPPLY_VOLTAGE_MIN
Definition: driver_sps30.c:44
#define SPS30_IIC_COMMAND_STOP_MEASUREMENT
Definition: driver_sps30.c:60
#define SPS30_IIC_COMMAND_READ_DEVICE_STATUS_REG
Definition: driver_sps30.c:70
#define SPS30_IIC_COMMAND_RESET
Definition: driver_sps30.c:72
#define SPS30_UART_COMMAND_READ_PRODUCT_TYPE
Definition: driver_sps30.c:80
#define CHIP_NAME
chip information definition
Definition: driver_sps30.c:42
#define SPS30_IIC_COMMAND_WAKE_UP
Definition: driver_sps30.c:64
#define SPS30_IIC_COMMAND_READ_MEASURED_VALUES
Definition: driver_sps30.c:62
#define DRIVER_VERSION
Definition: driver_sps30.c:49
#define SPS30_IIC_COMMAND_START_FAN_CLEANING
Definition: driver_sps30.c:65
#define SPS30_ADDRESS
chip address definition
Definition: driver_sps30.c:54
driver sps30 header file
uint8_t sps30_get_interface(sps30_handle_t *handle, sps30_interface_t *interface)
get the chip interface
Definition: driver_sps30.c:500
uint8_t sps30_set_auto_cleaning_interval(sps30_handle_t *handle, uint32_t second)
set the auto cleaning interval
Definition: driver_sps30.c:929
sps30_data_ready_flag_t
sps30 data ready flag enumeration definition
Definition: driver_sps30.h:81
uint8_t sps30_start_fan_cleaning(sps30_handle_t *handle)
start the fan cleaning
Definition: driver_sps30.c:860
uint8_t sps30_get_auto_cleaning_interval(sps30_handle_t *handle, uint32_t *second)
get the auto cleaning interval
uint8_t sps30_read(sps30_handle_t *handle, sps30_pm_t *pm)
read the result
uint8_t sps30_wake_up(sps30_handle_t *handle)
wake up the chip
Definition: driver_sps30.c:787
sps30_interface_t
sps30 interface enumeration definition
Definition: driver_sps30.h:63
uint8_t sps30_start_measurement(sps30_handle_t *handle, sps30_format_t format)
start the measurement
Definition: driver_sps30.c:523
uint8_t sps30_stop_measurement(sps30_handle_t *handle)
stop the measurement
Definition: driver_sps30.c:599
sps30_format_t
sps30 format enumeration definition
Definition: driver_sps30.h:72
uint8_t sps30_get_product_type(sps30_handle_t *handle, char type[9])
get the product type
uint8_t sps30_get_device_status(sps30_handle_t *handle, uint32_t *status)
get the device status
uint8_t sps30_disable_auto_cleaning_interval(sps30_handle_t *handle)
disable the auto cleaning interval
uint8_t sps30_reset(sps30_handle_t *handle)
reset the chip
uint8_t sps30_read_data_flag(sps30_handle_t *handle, sps30_data_ready_flag_t *flag)
read the data read flag
Definition: driver_sps30.c:667
uint8_t sps30_info(sps30_info_t *info)
get chip information
uint8_t sps30_deinit(sps30_handle_t *handle)
close the chip
uint8_t sps30_init(sps30_handle_t *handle)
initialize the chip
uint8_t sps30_sleep(sps30_handle_t *handle)
enter the sleep mode
Definition: driver_sps30.c:720
uint8_t sps30_set_interface(sps30_handle_t *handle, sps30_interface_t interface)
set the chip interface
Definition: driver_sps30.c:479
uint8_t sps30_clear_device_status(sps30_handle_t *handle)
clear the device status
uint8_t sps30_get_version(sps30_handle_t *handle, uint8_t *major, uint8_t *minor)
get the version
uint8_t sps30_get_serial_number(sps30_handle_t *handle, char sn[17])
get the serial number
@ SPS30_INTERFACE_IIC
Definition: driver_sps30.h:64
@ SPS30_FORMAT_UINT16
Definition: driver_sps30.h:74
@ SPS30_FORMAT_IEEE754
Definition: driver_sps30.h:73
uint8_t sps30_get_reg_iic(sps30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
get the chip register with iic interface
uint8_t sps30_set_get_reg_uart(sps30_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 sps30_set_reg_iic(sps30_handle_t *handle, uint16_t reg, uint8_t *buf, uint16_t len)
set the chip register with iic interface
sps30 handle structure definition
Definition: driver_sps30.h:100
uint8_t iic_uart
Definition: driver_sps30.h:113
uint8_t(* uart_flush)(void)
Definition: driver_sps30.h:108
uint8_t buf[256]
Definition: driver_sps30.h:115
uint8_t(* uart_write)(uint8_t *buf, uint16_t len)
Definition: driver_sps30.h:109
void(* delay_ms)(uint32_t ms)
Definition: driver_sps30.h:110
uint8_t(* uart_deinit)(void)
Definition: driver_sps30.h:106
void(* debug_print)(const char *const fmt,...)
Definition: driver_sps30.h:111
uint8_t(* iic_init)(void)
Definition: driver_sps30.h:101
uint16_t(* uart_read)(uint8_t *buf, uint16_t len)
Definition: driver_sps30.h:107
uint8_t(* iic_read_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
Definition: driver_sps30.h:104
uint8_t(* uart_init)(void)
Definition: driver_sps30.h:105
uint8_t(* iic_deinit)(void)
Definition: driver_sps30.h:102
uint8_t(* iic_write_cmd)(uint8_t addr, uint8_t *buf, uint16_t len)
Definition: driver_sps30.h:103
sps30 information structure definition
Definition: driver_sps30.h:139
float temperature_max
Definition: driver_sps30.h:147
float supply_voltage_max_v
Definition: driver_sps30.h:144
uint32_t driver_version
Definition: driver_sps30.h:148
char interface[16]
Definition: driver_sps30.h:142
float temperature_min
Definition: driver_sps30.h:146
float max_current_ma
Definition: driver_sps30.h:145
char manufacturer_name[32]
Definition: driver_sps30.h:141
float supply_voltage_min_v
Definition: driver_sps30.h:143
char chip_name[32]
Definition: driver_sps30.h:140
sps30 pm structure definition
Definition: driver_sps30.h:122
float pm1p0_cm3
Definition: driver_sps30.h:128
float typical_particle_um
Definition: driver_sps30.h:132
float pm4p0_cm3
Definition: driver_sps30.h:130
float pm10_cm3
Definition: driver_sps30.h:131
float pm1p0_ug_m3
Definition: driver_sps30.h:123
float pm0p5_cm3
Definition: driver_sps30.h:127
float pm4p0_ug_m3
Definition: driver_sps30.h:125
float pm10_ug_m3
Definition: driver_sps30.h:126
float pm2p5_cm3
Definition: driver_sps30.h:129
float pm2p5_ug_m3
Definition: driver_sps30.h:124