@@ -107,41 +107,46 @@ 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
// Set the temperature offset. See 1.3.8.
127
- void SCD30::setTemperatureOffset (float tempOffset)
129
+ bool SCD30::setTemperatureOffset (float tempOffset)
128
130
{
129
131
int16_t tickOffset = tempOffset * 100 ;
130
- sendCommand (COMMAND_SET_TEMPERATURE_OFFSET, tickOffset);
132
+ return sendCommand (COMMAND_SET_TEMPERATURE_OFFSET, tickOffset);
131
133
}
132
134
133
135
// Set the altitude compenstation. See 1.3.9.
134
- void SCD30::setAltitudeCompensation (uint16_t altitude)
136
+ bool SCD30::setAltitudeCompensation (uint16_t altitude)
135
137
{
136
- sendCommand (COMMAND_SET_ALTITUDE_COMPENSATION, altitude);
138
+ return sendCommand (COMMAND_SET_ALTITUDE_COMPENSATION, altitude);
137
139
}
138
140
139
141
// Set the pressure compenstation. This is passed during measurement startup.
140
142
// mbar can be 700 to 1200
141
- void SCD30::setAmbientPressure (uint16_t pressure_mbar)
143
+ bool SCD30::setAmbientPressure (uint16_t pressure_mbar)
142
144
{
143
- if (pressure_mbar < 700 || pressure_mbar > 1200 ) pressure_mbar = 0 ; // Error check
144
- sendCommand (COMMAND_CONTINUOUS_MEASUREMENT, pressure_mbar);
145
+ if (pressure_mbar < 700 || pressure_mbar > 1200 )
146
+ {
147
+ return false ;
148
+ }
149
+ return sendCommand (COMMAND_CONTINUOUS_MEASUREMENT, pressure_mbar);
145
150
}
146
151
147
152
// Begins continuous measurements
@@ -162,9 +167,9 @@ boolean SCD30::beginMeasuring(void)
162
167
163
168
// Sets interval between measurements
164
169
// 2 seconds to 1800 seconds (30 minutes)
165
- void SCD30::setMeasurementInterval (uint16_t interval)
170
+ bool SCD30::setMeasurementInterval (uint16_t interval)
166
171
{
167
- sendCommand (COMMAND_SET_MEASUREMENT_INTERVAL, interval);
172
+ return sendCommand (COMMAND_SET_MEASUREMENT_INTERVAL, interval);
168
173
}
169
174
170
175
// Returns true when data is available
@@ -195,9 +200,11 @@ boolean SCD30::readMeasurement()
195
200
if (_i2cPort->endTransmission () != 0 )
196
201
return (0 ); // Sensor did not ACK
197
202
198
- _i2cPort->requestFrom ((uint8_t )SCD30_ADDRESS, (uint8_t )18 );
203
+ const uint8_t receivedBytes = _i2cPort->requestFrom ((uint8_t )SCD30_ADDRESS, (uint8_t )18 );
204
+ bool error = false ;
199
205
if (_i2cPort->available ())
200
206
{
207
+ byte bytesToCrc[2 ];
201
208
for (byte x = 0 ; x < 18 ; x++)
202
209
{
203
210
byte incoming = _i2cPort->read ();
@@ -210,28 +217,43 @@ boolean SCD30::readMeasurement()
210
217
case 4 :
211
218
tempCO2 <<= 8 ;
212
219
tempCO2 |= incoming;
220
+ bytesToCrc[x%3 ] = incoming;
213
221
break ;
214
222
case 6 :
215
223
case 7 :
216
224
case 9 :
217
225
case 10 :
218
226
tempTemperature <<= 8 ;
219
227
tempTemperature |= incoming;
228
+ bytesToCrc[x%3 ] = incoming;
220
229
break ;
221
230
case 12 :
222
231
case 13 :
223
232
case 15 :
224
233
case 16 :
225
234
tempHumidity <<= 8 ;
226
235
tempHumidity |= incoming;
236
+ bytesToCrc[x%3 ] = incoming;
227
237
break ;
228
238
default :
229
- // Do nothing with the CRC bytes
239
+ // Validate CRC
240
+ const uint8_t foundCrc = computeCRC8 (bytesToCrc, 2 );
241
+ if (foundCrc != incoming) {
242
+ Serial.printf (" Found CRC in byte %u, expected %u, got %u\n " , x, incoming, foundCrc);
243
+ error = true ;
244
+ }
230
245
break ;
231
246
}
232
247
}
248
+ } else {
249
+ Serial.printf (" No SCD30 data found from I2C, i2c claims we should receive %u bytes\n " , receivedBytes);
250
+ return false ;
233
251
}
234
252
253
+ if (error) {
254
+ Serial.println (" Encountered error reading SCD30 data." );
255
+ return false ;
256
+ }
235
257
// Now copy the uint32s into their associated floats
236
258
memcpy (&co2, &tempCO2, sizeof (co2));
237
259
memcpy (&temperature, &tempTemperature, sizeof (temperature));
0 commit comments