@@ -107,20 +107,22 @@ float SCD30::getTemperature(void)
107
107
}
108
108
109
109
// Enables or disables the ASC
110
- void SCD30::setAutoSelfCalibration (boolean enable)
110
+ bool SCD30::setAutoSelfCalibration (boolean enable)
111
111
{
112
112
if (enable)
113
- sendCommand (COMMAND_AUTOMATIC_SELF_CALIBRATION, 1 ); // Activate continuous ASC
113
+ return sendCommand (COMMAND_AUTOMATIC_SELF_CALIBRATION, 1 ); // Activate continuous ASC
114
114
else
115
- sendCommand (COMMAND_AUTOMATIC_SELF_CALIBRATION, 0 ); // Deactivate continuous ASC
115
+ return sendCommand (COMMAND_AUTOMATIC_SELF_CALIBRATION, 0 ); // Deactivate continuous ASC
116
116
}
117
117
118
118
// Set the forced recalibration factor. See 1.3.7.
119
119
// The reference CO2 concentration has to be within the range 400 ppm ≤ cref(CO2) ≤ 2000 ppm.
120
- void SCD30::setForcedRecalibrationFactor (uint16_t concentration)
120
+ bool SCD30::setForcedRecalibrationFactor (uint16_t concentration)
121
121
{
122
- if (concentration < 400 || concentration > 2000 ) return ; // Error check.
123
- sendCommand (COMMAND_SET_FORCED_RECALIBRATION_FACTOR, concentration);
122
+ if (concentration < 400 || concentration > 2000 ) {
123
+ return false ; // Error check.
124
+ }
125
+ return sendCommand (COMMAND_SET_FORCED_RECALIBRATION_FACTOR, concentration);
124
126
}
125
127
126
128
// Get the temperature offset. See 1.3.8.
@@ -131,24 +133,27 @@ float SCD30::getTemperatureOffset()
131
133
}
132
134
133
135
// Set the temperature offset. See 1.3.8.
134
- void SCD30::setTemperatureOffset (float tempOffset)
136
+ bool SCD30::setTemperatureOffset (float tempOffset)
135
137
{
136
138
int16_t tickOffset = tempOffset * 100 ;
137
- sendCommand (COMMAND_SET_TEMPERATURE_OFFSET, tickOffset);
139
+ return sendCommand (COMMAND_SET_TEMPERATURE_OFFSET, tickOffset);
138
140
}
139
141
140
142
// Set the altitude compenstation. See 1.3.9.
141
- void SCD30::setAltitudeCompensation (uint16_t altitude)
143
+ bool SCD30::setAltitudeCompensation (uint16_t altitude)
142
144
{
143
- sendCommand (COMMAND_SET_ALTITUDE_COMPENSATION, altitude);
145
+ return sendCommand (COMMAND_SET_ALTITUDE_COMPENSATION, altitude);
144
146
}
145
147
146
148
// Set the pressure compenstation. This is passed during measurement startup.
147
149
// mbar can be 700 to 1200
148
- void SCD30::setAmbientPressure (uint16_t pressure_mbar)
150
+ bool SCD30::setAmbientPressure (uint16_t pressure_mbar)
149
151
{
150
- if (pressure_mbar < 700 || pressure_mbar > 1200 ) pressure_mbar = 0 ; // Error check
151
- sendCommand (COMMAND_CONTINUOUS_MEASUREMENT, pressure_mbar);
152
+ if (pressure_mbar < 700 || pressure_mbar > 1200 )
153
+ {
154
+ return false ;
155
+ }
156
+ return sendCommand (COMMAND_CONTINUOUS_MEASUREMENT, pressure_mbar);
152
157
}
153
158
154
159
// Begins continuous measurements
@@ -169,9 +174,9 @@ boolean SCD30::beginMeasuring(void)
169
174
170
175
// Sets interval between measurements
171
176
// 2 seconds to 1800 seconds (30 minutes)
172
- void SCD30::setMeasurementInterval (uint16_t interval)
177
+ bool SCD30::setMeasurementInterval (uint16_t interval)
173
178
{
174
- sendCommand (COMMAND_SET_MEASUREMENT_INTERVAL, interval);
179
+ return sendCommand (COMMAND_SET_MEASUREMENT_INTERVAL, interval);
175
180
}
176
181
177
182
// Returns true when data is available
@@ -202,9 +207,11 @@ boolean SCD30::readMeasurement()
202
207
if (_i2cPort->endTransmission () != 0 )
203
208
return (0 ); // Sensor did not ACK
204
209
205
- _i2cPort->requestFrom ((uint8_t )SCD30_ADDRESS, (uint8_t )18 );
210
+ const uint8_t receivedBytes = _i2cPort->requestFrom ((uint8_t )SCD30_ADDRESS, (uint8_t )18 );
211
+ bool error = false ;
206
212
if (_i2cPort->available ())
207
213
{
214
+ byte bytesToCrc[2 ];
208
215
for (byte x = 0 ; x < 18 ; x++)
209
216
{
210
217
byte incoming = _i2cPort->read ();
@@ -217,28 +224,43 @@ boolean SCD30::readMeasurement()
217
224
case 4 :
218
225
tempCO2 <<= 8 ;
219
226
tempCO2 |= incoming;
227
+ bytesToCrc[x%3 ] = incoming;
220
228
break ;
221
229
case 6 :
222
230
case 7 :
223
231
case 9 :
224
232
case 10 :
225
233
tempTemperature <<= 8 ;
226
234
tempTemperature |= incoming;
235
+ bytesToCrc[x%3 ] = incoming;
227
236
break ;
228
237
case 12 :
229
238
case 13 :
230
239
case 15 :
231
240
case 16 :
232
241
tempHumidity <<= 8 ;
233
242
tempHumidity |= incoming;
243
+ bytesToCrc[x%3 ] = incoming;
234
244
break ;
235
245
default :
236
- // Do nothing with the CRC bytes
246
+ // Validate CRC
247
+ const uint8_t foundCrc = computeCRC8 (bytesToCrc, 2 );
248
+ if (foundCrc != incoming) {
249
+ Serial.printf (" Found CRC in byte %u, expected %u, got %u\n " , x, incoming, foundCrc);
250
+ error = true ;
251
+ }
237
252
break ;
238
253
}
239
254
}
255
+ } else {
256
+ Serial.printf (" No SCD30 data found from I2C, i2c claims we should receive %u bytes\n " , receivedBytes);
257
+ return false ;
240
258
}
241
259
260
+ if (error) {
261
+ Serial.println (" Encountered error reading SCD30 data." );
262
+ return false ;
263
+ }
242
264
// Now copy the uint32s into their associated floats
243
265
memcpy (&co2, &tempCO2, sizeof (co2));
244
266
memcpy (&temperature, &tempTemperature, sizeof (temperature));
0 commit comments