-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMHZ19.cpp
165 lines (131 loc) · 3.85 KB
/
MHZ19.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
* Designed to work with Winsen MH-Z19B CO2 sensor
* - https://www.winsen-sensor.com/products/ndir-co2-sensor/mh-z19b.html
* According to:
* - https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf
*
* This library implements methods for working with sensor via UART.
*
* Written by Kostiantyn Levytskyi <[email protected]>
*
* MIT License
*
*/
#include <MHZ19.h>
/*
* Checks a crc of an 9 bype packet
*/
byte MHZ19::getCheckSum(byte* packet) {
byte checksum = 0;
for(uint8_t i = 1; i < 8; i++) {
checksum += packet[i];
}
checksum = 0xff - checksum;
checksum += 1;
return checksum;
}
byte MHZ19::CMD_READ[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // Read command
byte MHZ19::CMD_CALIBRATE_ZERO[9] = {0xFF, 0x01, 0x87, 0x00, 0x00,0x00, 0x00, 0x00, 0x78}; // Calibrate ZERO point
byte MHZ19::CMD_ABC_ON[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; // Enables Automatic Baseline Correction
byte MHZ19::CMD_ABC_OFF[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; // Disables Automatic Baseline Correction
/*
* Sends command to MH-Z19 with back crc checking
* @param 9 bytes that needed to be send
* @return bool indicating command receive
*/
bool MHZ19::sendCmd(byte cmd[9]) {
unsigned char response[9];
_streamRef->write(cmd, 9);
_streamRef->readBytes(response, 9);
byte crc = getCheckSum(response);
if (response[0] == 0xFF && response[1] == cmd[2] && response[8] == crc) {
return true;
}
return false;
}
/*
* @param Stream instance reference. Usually HardwareSerial or SoftwareSerial
*/
void MHZ19::setSerial(Stream *streamRef) {
_streamRef = streamRef;
};
/*
* Sets CO2 detection ranges, 0-2000ppm or 0-5000ppm.
* @param range top from 1000 to 5000
* Setting lower than 1000 is unavaliable.
* NOTE: Datasheet recomends usage of 0-2000ppm and 0-5000ppm detection ranges.
*/
bool MHZ19::setRange(int range) {
if (!(range >= 1000 && range <= 5000)) {
return false;
}
byte range6thByte = range >> 8;
byte range7thByte = range & 0xFA;
byte rangeCmd[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, range6thByte, range7thByte, 0x00};
rangeCmd[8] = getCheckSum(rangeCmd);
return sendCmd(rangeCmd);
}
/*
* Enables sensor Automatic Baseline Correction (ABC)
*/
bool MHZ19::enableABC() {
return sendCmd(CMD_ABC_ON);
}
/*
* Disables sensor Automatic Baseline Correction (ABC)
*/
bool MHZ19::disableABC() {
return sendCmd(CMD_ABC_OFF);
}
/*
* Calibrates sensor's zero point assuming that current value is 400ppm
*/
bool MHZ19::calibrateZero() {
return sendCmd(CMD_CALIBRATE_ZERO);
}
/*
* Calibrates sensor's span point (have no idea what it is)
*/
bool MHZ19::calibrateSpan(int span) {
if (!(span >= 1000 && span <= 5000)) {
return false;
}
byte span6thByte = span >> 8;
byte span7thByte = span & 0xFA;
byte spanCmd[9] = {0xFF, 0x01, 0x88, 0x00, 0x00, 0x00, span6thByte, span7thByte, 0x00};
spanCmd[8] = getCheckSum(spanCmd);
return sendCmd(spanCmd);
}
/*
* Read current ppm from sensor
*/
int MHZ19::readValue() {
unsigned int co2 = -1;
unsigned char response[9];
_streamRef->write(CMD_READ, 9);
if (_streamRef->available()) {
_streamRef->readBytes(response, 9);
byte crc = getCheckSum(response);
if (response[0] == 0xFF && response[1] == CMD_READ[2] && response[8] == crc) {
unsigned int responseHigh = (unsigned int) response[2];
unsigned int responseLow = (unsigned int) response[3];
unsigned int ppm = (256*responseHigh) + responseLow;
co2 = ppm;
}
}
return co2;
}
/*
* Returns if sensor is ready to use and sends real data.
* According to datasheet MH-Z19 preheat time is 3 mins.
*/
bool MHZ19::isReady() {
if (!sensorIsReady) {
if (millis() > PREHEAT_TIME) {
sensorIsReady = true;
return sensorIsReady;
}
return false;
}
return sensorIsReady;
}