-
Notifications
You must be signed in to change notification settings - Fork 0
/
SDS011Reader.cpp
113 lines (92 loc) · 2.67 KB
/
SDS011Reader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <SDS011Reader.h>
SDS011Reader::SDS011Reader(){}
bool SDS011Reader::read_data(){
// clear serial buffer (no old data):
while (Serial.available()) Serial.read();
uint32_t reading_timeout = millis() + 1200;
while (millis() < reading_timeout){
if (process_serial()){
// retry many times until valid data was processed
return true;
}
}
return false;
}
bool SDS011Reader::process_serial(){
// SDS011_laser_PM2.5_sensor_specification-V1.3.pdf
// See section "The UART communication protocol" on page 5
if (Serial.available() < 10){
return false;
}
pm10_int = 0;
pm25_int = 0;
// checksum_total overflows but that doesn't matter for the check
uint8_t checksum_total = 0;
uint8_t checksum_byte_sds011 = 0;
for (int i = 0; i < 10; i++){
uint8_t sds011_byte = Serial.read();
if (i >= 2 && i <= 7){
checksum_total += sds011_byte;
}
if (i == 0 && sds011_byte != 0xAA){
return false;
} else if (i == 1 && sds011_byte != 0xC0){
return false;
} else if (i == 2){
pm25_int = sds011_byte;
} else if (i == 3){
pm25_int += sds011_byte<<8;
} else if (i == 4){
pm10_int = sds011_byte;
} else if (i == 5){
pm10_int += sds011_byte<<8;
} else if (i == 8){
checksum_byte_sds011 = sds011_byte;
} else if (i == 9 && sds011_byte != 0xAB){
return false;
}
}
if (checksum_total != checksum_byte_sds011){
//Serial.println(F("checksum error"));
return false;
}
//Serial.println(F("checksum ok"));
return true;
}
bool SDS011Reader::get_avg_reading(uint8_t number_of_readings){
uint16_t avg_reading_pm25_total = 0;
uint16_t avg_reading_pm10_total = 0;
uint8_t ok_readings = 0;
const uint8_t max_failed = 2;
uint8_t failed = 0;
while (ok_readings < number_of_readings){
if (read_data()){
avg_reading_pm25_total += pm25_int;
avg_reading_pm10_total += pm10_int;
ok_readings++;
//Serial.println(F("ok reading.."));
} else {
failed++;
}
if (failed >= max_failed){
pm25_int_avg = 0;
pm10_int_avg = 0;
return false;
}
}
pm25_int_avg = avg_reading_pm25_total / number_of_readings;
pm10_int_avg = avg_reading_pm10_total / number_of_readings;
return true;
}
float SDS011Reader::pm10(){
return pm10_int / 10.0;
}
float SDS011Reader::pm25(){
return pm25_int / 10.0;
}
float SDS011Reader::pm10_avg(){
return pm10_int_avg / 10.0;
}
float SDS011Reader::pm25_avg(){
return pm25_int_avg / 10.0;
}