Skip to content

Commit 7baf987

Browse files
committed
rename SCD40 examples to SCD4x
1 parent 5c619da commit 7baf987

File tree

3 files changed

+267
-2
lines changed

3 files changed

+267
-2
lines changed

SCD40_I2C_FRC_Forced_Recalibration_Example/SCD40_I2C_FRC_Forced_Recalibration_Example.ino renamed to SCD4x_I2C_FRC_Forced_Recalibration_Example/SCD4x_I2C_FRC_Forced_Recalibration_Example.ino

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,8 @@ void setup() {
105105
ret = Wire.endTransmission();
106106
Serial.println(ret);
107107

108-
109108
// wait for sensor
110-
//delay(20);
109+
delay(20);
111110

112111
// assuming an external reference shows 350 ppm
113112
calibration = 650;
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/*
2+
* Copyright (c) 2020, Sensirion AG
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* * Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* * Neither the name of Sensirion AG nor the names of its
16+
* contributors may be used to endorse or promote products derived from
17+
* this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
* POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
#include <Wire.h>
33+
34+
// SEN44
35+
const int16_t SEN44_ADDRESS = 0x69;
36+
37+
void setup() {
38+
int16_t voc_offset,voc_learning, voc_gating, voc_initial;
39+
uint8_t data[12], counter;
40+
41+
Serial.begin(115200);
42+
// wait for serial connection from PC
43+
// comment the following line if you'd like the output
44+
// without waiting for the interface being ready
45+
while(!Serial);
46+
47+
// output format
48+
Serial.println("PM1.0\tPM2.5\tPM4.0\tPM10.0\tVOC_Index\tRH\tT");
49+
50+
// init I2C
51+
Wire.begin();
52+
53+
// wait until sensors startup, > 1 ms according to datasheet
54+
delay(100);
55+
56+
// make sure sensor is stopped to change parameters
57+
Wire.beginTransmission(SEN44_ADDRESS);
58+
Wire.write(0x01);
59+
Wire.write(0x04);
60+
Wire.endTransmission();
61+
62+
// wait until sensor is ready
63+
delay(100);
64+
65+
// read current VOC parameters from flash memory
66+
Wire.beginTransmission(SEN44_ADDRESS);
67+
Wire.write(0x60);
68+
Wire.write(0x83);
69+
Wire.endTransmission();
70+
71+
// wait 10 ms to allow the sensor to fill the internal buffer
72+
delay(10);
73+
74+
// read offset data, after two bytes a CRC follows
75+
Wire.requestFrom(SEN44_ADDRESS, 12);
76+
counter = 0;
77+
while (Wire.available()) {
78+
data[counter++] = Wire.read();
79+
}
80+
81+
// values are unscaled
82+
// offset is arbitrary
83+
voc_offset = (uint16_t)data[0] << 8 | data[1];
84+
// learning time is in hours
85+
voc_learning = (uint16_t)data[3] << 8 | data[4];
86+
// gating time is in minutes
87+
voc_gating = (uint16_t)data[6] << 8 | data[7];
88+
// standard initial is arbitrary
89+
voc_initial = (uint16_t)data[9] << 8 | data[10]; Serial.println();
90+
91+
Serial.println("default parameters (offset, learning, gating, initial): ");
92+
Serial.println(voc_offset);
93+
Serial.println(voc_learning);
94+
Serial.println(voc_gating);
95+
Serial.println(voc_initial);
96+
Serial.println();
97+
98+
// Set new algorithm parameters
99+
// Offset 200 instead of 100
100+
voc_offset = 200;
101+
// Learning 6 h instead of 12 h
102+
voc_learning = 12;
103+
// gating 60 min instead of 180 min
104+
voc_gating = 60;
105+
// initial same as default with 50
106+
voc_initial = 50;
107+
108+
// prepare buffer with algorithm parameter data
109+
// calculate CRC for each 2 bytes of data
110+
data[0] = (voc_offset & 0xff00) >> 8;
111+
data[1] = voc_offset & 0x00ff;
112+
data[2] = CalcCrc(data);
113+
data[3] = (voc_learning & 0xff00) >> 8;
114+
data[4] = voc_learning & 0x00ff;
115+
data[5] = CalcCrc(data+3);
116+
data[6] = (voc_gating & 0xff00) >> 8;
117+
data[7] = voc_gating & 0x00ff;
118+
data[8] = CalcCrc(data+6);
119+
data[9] = (voc_initial & 0xff00) >> 8;
120+
data[10] = voc_initial & 0x00ff;
121+
data[11] = CalcCrc(data+9);
122+
123+
// send new value for voc parameters to sensor (will be hold in RAM, not persistent)
124+
Wire.beginTransmission(SEN44_ADDRESS);
125+
Wire.write(0x60);
126+
Wire.write(0x83);
127+
Wire.write(data[0]);
128+
Wire.write(data[1]);
129+
Wire.write(data[2]);
130+
Wire.write(data[3]);
131+
Wire.write(data[4]);
132+
Wire.write(data[5]);
133+
Wire.write(data[6]);
134+
Wire.write(data[7]);
135+
Wire.write(data[8]);
136+
Wire.write(data[9]);
137+
Wire.write(data[10]);
138+
Wire.write(data[11]);
139+
Wire.endTransmission();
140+
141+
// wait 10 ms to allow the sensor to fill the internal buffer
142+
delay(10);
143+
144+
// now send command to save parameter in the flash (NVM memory) of the sensor to have persistence
145+
Wire.beginTransmission(SEN44_ADDRESS);
146+
Wire.write(0x60);
147+
Wire.write(0x02);
148+
Wire.endTransmission();
149+
150+
// wait 30 ms to allow the sensor to write the data into the flash
151+
delay(30);
152+
153+
// repeat read data to make sure that the values are applied correctly
154+
Wire.beginTransmission(SEN44_ADDRESS);
155+
Wire.write(0x60);
156+
Wire.write(0x83);
157+
Wire.endTransmission();
158+
159+
// wait 10 ms to allow the sensor to fill the internal buffer
160+
delay(10);
161+
162+
// read offset data, after two bytes a CRC follows
163+
Wire.requestFrom(SEN44_ADDRESS, 12);
164+
counter = 0;
165+
while (Wire.available()) {
166+
data[counter++] = Wire.read();
167+
}
168+
// values are unscaled
169+
// offset is arbitrary
170+
voc_offset = (uint16_t)data[0] << 8 | data[1];
171+
// learning time is in hours
172+
voc_learning = (uint16_t)data[3] << 8 | data[4];
173+
// gating time is in minutes
174+
voc_gating = (uint16_t)data[6] << 8 | data[7];
175+
// standard initial is arbitrary
176+
voc_initial = (uint16_t)data[9] << 8 | data[10]; Serial.println();
177+
178+
Serial.println("new parameters (offset, learning, gating, initial): ");
179+
Serial.println(voc_offset);
180+
Serial.println(voc_learning);
181+
Serial.println(voc_gating);
182+
Serial.println(voc_initial);
183+
Serial.println();
184+
185+
// wait 10 ms to allow the sensor to be ready again
186+
delay(10);
187+
188+
// start up sensor, sensor will go to continous measurement mode
189+
// each second there will be new measurement values
190+
Wire.beginTransmission(SEN44_ADDRESS);
191+
Wire.write(0x00);
192+
Wire.write(0x21);
193+
Wire.endTransmission();
194+
195+
// wait until sensors is ready, fan is initialized
196+
delay(2000);
197+
}
198+
199+
void loop() {
200+
uint16_t pm1p0, pm2p5, pm4p0, pm10p0;
201+
int16_t voc, humidity, temperature;
202+
uint8_t data[21], counter;
203+
204+
// read measurement data
205+
Wire.beginTransmission(SEN44_ADDRESS);
206+
Wire.write(0x03);
207+
Wire.write(0x74);
208+
Wire.endTransmission();
209+
210+
// wait 10 ms to allow the sensor to fill the internal buffer
211+
delay(10);
212+
213+
// read measurement data sen44, after two bytes a CRC follows
214+
Wire.requestFrom(SEN44_ADDRESS, 21);
215+
counter = 0;
216+
while (Wire.available()) {
217+
data[counter++] = Wire.read();
218+
}
219+
220+
// PM1.0 to PM10 are unscaled unsigned integer values in ug / um3
221+
// VOC level is a signed int and scaled by a factor of 10 and needs to be divided by 10
222+
// VOC raw value is an uint16_t and has no scaling
223+
// humidity is a signed int and scaled by 100 and need to be divided by 100
224+
// temperature is a signed int and scaled by 200 and need to be divided by 200
225+
pm1p0 = (uint16_t)data[0] << 8 | data[1];
226+
pm2p5 = (uint16_t)data[3] << 8 | data[4];
227+
pm4p0 = (uint16_t)data[6] << 8 | data[7];
228+
pm10p0 = (uint16_t)data[9] << 8 | data[10];
229+
voc = (uint16_t)data[12] << 8 | data[13];
230+
humidity = (uint16_t)data[15] << 8 | data[16];
231+
temperature = (uint16_t)data[18] << 8 | data[19];
232+
233+
Serial.print(pm1p0);
234+
Serial.print("\t");
235+
Serial.print(pm2p5);
236+
Serial.print("\t");
237+
Serial.print(pm4p0);
238+
Serial.print("\t");
239+
Serial.print(pm10p0);
240+
Serial.print("\t");
241+
Serial.print(String(float(voc) / 10));
242+
Serial.print("\t");
243+
Serial.print(String(float(humidity) / 100));
244+
Serial.print("\t");
245+
Serial.print(String(float(temperature) / 200));
246+
Serial.println();
247+
248+
// wait 1 s for next measurement
249+
delay(1000);
250+
}
251+
252+
// calculate CRC according to datasheet
253+
uint8_t CalcCrc(uint8_t data[2]) {
254+
uint8_t crc = 0xFF;
255+
for(int i = 0; i < 2; i++) {
256+
crc ^= data[i];
257+
for(uint8_t bit = 8; bit > 0; --bit) {
258+
if(crc & 0x80) {
259+
crc = (crc << 1) ^ 0x31u;
260+
} else {
261+
crc = (crc << 1);
262+
}
263+
}
264+
}
265+
return crc;
266+
}

0 commit comments

Comments
 (0)