Skip to content

Commit f26c893

Browse files
committed
Correct bytesToCrc
1 parent 26995c0 commit f26c893

File tree

2 files changed

+55
-42
lines changed

2 files changed

+55
-42
lines changed

src/SparkFun_SCD4x_Arduino_Library.cpp

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ bool SCD4x::begin(TwoWire &wirePort, bool measBegin, bool autoCalibrate, bool sk
4343
//To be safe, let's stop period measurements before we do anything else
4444
//The user can override this by setting skipStopPeriodicMeasurements to true
4545
if (skipStopPeriodicMeasurements == false)
46-
success &= stopPeriodicMeasurement();
46+
success &= stopPeriodicMeasurement(); // Delays for 500ms...
4747

4848
char serialNumber[13]; // Serial number is 12 digits plus trailing NULL
4949
success &= getSerialNumber(serialNumber); // Read the serial number. Return false if the CRC check fails.
@@ -186,23 +186,23 @@ bool SCD4x::readMeasurement(void)
186186
{
187187
case 0:
188188
case 1:
189-
tempCO2.bytes[x == 0 ? 1 : 0] = incoming;
190-
bytesToCrc[x] = incoming;
189+
tempCO2.bytes[x == 0 ? 1 : 0] = incoming; // Store the two CO2 bytes in little-endian format
190+
bytesToCrc[x] = incoming; // Calculate the CRC on the two CO2 bytes in the order they arrive
191191
break;
192192
case 3:
193193
case 4:
194-
tempTemperature.bytes[x == 3 ? 1 : 0] = incoming;
195-
bytesToCrc[x % 2] = incoming;
194+
tempTemperature.bytes[x == 3 ? 1 : 0] = incoming; // Store the two T bytes in little-endian format
195+
bytesToCrc[x % 3] = incoming; // Calculate the CRC on the two T bytes in the order they arrive
196196
break;
197197
case 6:
198198
case 7:
199-
tempHumidity.bytes[x == 6 ? 1 : 0] = incoming;
200-
bytesToCrc[x % 2] = incoming;
199+
tempHumidity.bytes[x == 6 ? 1 : 0] = incoming; // Store the two RH bytes in little-endian format
200+
bytesToCrc[x % 3] = incoming; // Calculate the CRC on the two RH bytes in the order they arrive
201201
break;
202-
default:
202+
default: // x == 2, 5, 8
203203
//Validate CRC
204-
uint8_t foundCrc = computeCRC8(bytesToCrc, 2);
205-
if (foundCrc != incoming)
204+
uint8_t foundCrc = computeCRC8(bytesToCrc, 2); // Calculate what the CRC should be for these two bytes
205+
if (foundCrc != incoming) // Does this match the CRC byte from the sensor?
206206
{
207207
if (_printDebug == true)
208208
{
@@ -366,7 +366,7 @@ bool SCD4x::getTemperatureOffset(float *offset)
366366

367367
//Set the sensor altitude (metres above sea level). See 3.6.3
368368
//Max command duration: 1ms
369-
//The user can set delayMillis to zero f they want the function to return immediately.
369+
//The user can set delayMillis to zero if they want the function to return immediately.
370370
//Reading and writing of the sensor altitude must be done while the SCD4x is in idle mode.
371371
//Typically, the sensor altitude is set once after device installation. To save the setting to the EEPROM,
372372
//the persist setting (see chapter 3.9.1) command must be issued.
@@ -426,8 +426,9 @@ bool SCD4x::getSensorAltitude(uint16_t *altitude)
426426

427427
//Set the ambient pressure (Pa). See 3.6.5
428428
//Max command duration: 1ms
429-
//The user can set delayMillis to zero f they want the function to return immediately.
429+
//The user can set delayMillis to zero if they want the function to return immediately.
430430
//The set_ambient_pressure command can be sent during periodic measurements to enable continuous pressure compensation.
431+
//setAmbientPressure overrides setSensorAltitude
431432
bool SCD4x::setAmbientPressure(float pressure, uint16_t delayMillis)
432433
{
433434
if (pressure < 0)
@@ -465,7 +466,7 @@ float SCD4x::performForcedRecalibration(uint16_t concentration)
465466
return (0.0);
466467
}
467468

468-
float correction;
469+
float correction = 0.0;
469470
bool success = performForcedRecalibration(concentration, &correction);
470471
if ((success == false) && (_printDebug == true))
471472
{
@@ -546,7 +547,7 @@ bool SCD4x::performForcedRecalibration(uint16_t concentration, float *correction
546547

547548
*correction = ((float)correctionWord) - 32768; // FRC correction [ppm CO2] = word[0] – 0x8000
548549

549-
if (correctionWord == 0xffff)
550+
if (correctionWord == 0xffff) //A return value of 0xffff indicates that the forced recalibration has failed
550551
return (false);
551552

552553
return (true);
@@ -669,7 +670,7 @@ bool SCD4x::persistSettings(uint16_t delayMillis)
669670
return (success);
670671
}
671672

672-
//Get 9 bytes from SCD4x. Convert serial number to ASCII chars. See 3.9.2
673+
//Get 9 bytes from SCD4x. Convert 48-bit serial number to ASCII chars. See 3.9.2
673674
//Returns true if serial number is read successfully
674675
//Reading out the serial number can be used to identify the chip and to verify the presence of the sensor.
675676
bool SCD4x::getSerialNumber(char *serialNumber)
@@ -703,20 +704,20 @@ bool SCD4x::getSerialNumber(char *serialNumber)
703704

704705
switch (x)
705706
{
706-
case 0:
707+
case 0: // The serial number arrives as: two bytes, CRC, two bytes, CRC, two bytes, CRC
707708
case 1:
708709
case 3:
709710
case 4:
710711
case 6:
711712
case 7:
712-
serialNumber[digit++] = convertHexToASCII(incoming >> 8);
713+
serialNumber[digit++] = convertHexToASCII(incoming >> 4); // Convert each nibble to ASCII
713714
serialNumber[digit++] = convertHexToASCII(incoming & 0x0F);
714-
bytesToCrc[x % 2] = incoming;
715+
bytesToCrc[x % 3] = incoming;
715716
break;
716-
default:
717+
default: // x == 2, 5, 8
717718
//Validate CRC
718-
uint8_t foundCrc = computeCRC8(bytesToCrc, 2);
719-
if (foundCrc != incoming)
719+
uint8_t foundCrc = computeCRC8(bytesToCrc, 2); // Calculate what the CRC should be for these two bytes
720+
if (foundCrc != incoming) // Does this match the CRC byte from the sensor?
720721
{
721722
if (_printDebug == true)
722723
{
@@ -794,7 +795,7 @@ bool SCD4x::performSelfTest(void)
794795
_debugPort->println(response, HEX);
795796
}
796797

797-
return (success && (response == 0x0000));
798+
return (success && (response == 0x0000)); // word[0] = 0 → no malfunction detected
798799
}
799800

800801
//Peform factory reset. See 3.9.4

src/SparkFun_SCD4x_Arduino_Library.h

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class SCD4x
9696
public:
9797
SCD4x(scd4x_sensor_type_e sensorType = SCD4x_SENSOR_SCD40);
9898

99+
// Please see the code examples for an explanation of what measBegin, autoCalibrate and skipStopPeriodicMeasurements do
99100
bool begin(bool measBegin) { return begin(Wire, measBegin); }
100101
bool begin(bool measBegin, bool autoCalibrate) { return begin(Wire, measBegin, autoCalibrate); }
101102
bool begin(bool measBegin, bool autoCalibrate, bool skipStopPeriodicMeasurements) { return begin(Wire, measBegin, autoCalibrate, skipStopPeriodicMeasurements); }
@@ -105,49 +106,60 @@ class SCD4x
105106
bool begin(TwoWire &wirePort = Wire, bool measBegin = true, bool autoCalibrate = true, bool skipStopPeriodicMeasurements = false); //By default use Wire port
106107
#endif
107108

108-
void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used.
109+
void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used
110+
111+
bool startPeriodicMeasurement(void); // Signal update interval is 5 seconds
109112

110-
bool startPeriodicMeasurement(void); //Signal update interval is 5 seconds
111113
// stopPeriodicMeasurement can be called before .begin if required
112114
// If the sensor has been begun (_i2cPort is not NULL) then _i2cPort is used
113115
// If the sensor has not been begun (_i2cPort is NULL) then wirePort and address are used (which will default to Wire)
116+
// Note that the sensor will only respond to other commands after waiting 500 ms after issuing the stop_periodic_measurement command.
114117
#ifdef USE_TEENSY3_I2C_LIB
115-
bool stopPeriodicMeasurement(uint16_t delayMillis = 500, i2c_t3 &wirePort = Wire); //Note that the sensor will only respond to other commands after waiting 500 ms after issuing the stop_periodic_measurement command.
118+
bool stopPeriodicMeasurement(uint16_t delayMillis = 500, i2c_t3 &wirePort = Wire);
116119
#else
117-
bool stopPeriodicMeasurement(uint16_t delayMillis = 500, TwoWire &wirePort = Wire); //Note that the sensor will only respond to other commands after waiting 500 ms after issuing the stop_periodic_measurement command.
120+
bool stopPeriodicMeasurement(uint16_t delayMillis = 500, TwoWire &wirePort = Wire);
118121
#endif
119122

120-
bool readMeasurement(void);
123+
bool readMeasurement(void); // Check for fresh data; store it. Returns true if fresh data is available
121124

122-
uint16_t getCO2(void);
123-
float getHumidity(void);
124-
float getTemperature(void);
125+
uint16_t getCO2(void); // Return the CO2 PPM. Automatically request fresh data is the data is 'stale'
126+
float getHumidity(void); // Return the RH. Automatically request fresh data is the data is 'stale'
127+
float getTemperature(void); // Return the temperature. Automatically request fresh data is the data is 'stale'
125128

126-
bool setTemperatureOffset(float offset, uint16_t delayMillis = 1);
129+
// Define how warm the sensor is compared to ambient, so RH and T are temperature compensated. Has no effect on the CO2 reading
130+
// Default offset is 4C
131+
bool setTemperatureOffset(float offset, uint16_t delayMillis = 1); // Returns true if I2C transfer was OK
127132
float getTemperatureOffset(void); // Will return zero if offset is invalid
128133
bool getTemperatureOffset(float *offset); // Returns true if offset is valid
134+
135+
// Define the sensor altitude in metres above sea level, so RH and CO2 are compensated for atmospheric pressure
136+
// Default altitude is 0m
129137
bool setSensorAltitude(uint16_t altitude, uint16_t delayMillis = 1);
130-
uint16_t getSensorAltitude(void); // Will return zero if offset is invalid
131-
bool getSensorAltitude(uint16_t *altitude); // Returns true if offset is valid
138+
uint16_t getSensorAltitude(void); // Will return zero if altitude is invalid
139+
bool getSensorAltitude(uint16_t *altitude); // Returns true if altitude is valid
140+
141+
// Define the ambient pressure in Pascals, so RH and CO2 are compensated for atmospheric pressure
142+
// setAmbientPressure overrides setSensorAltitude
132143
bool setAmbientPressure(float pressure, uint16_t delayMillis = 1);
133144

134-
float performForcedRecalibration(uint16_t concentration);
145+
float performForcedRecalibration(uint16_t concentration); // Returns the FRC correction value
135146
bool performForcedRecalibration(uint16_t concentration, float *correction); // Returns true if FRC is successful
147+
136148
bool setAutomaticSelfCalibrationEnabled(bool enabled = true, uint16_t delayMillis = 1);
137149
bool getAutomaticSelfCalibrationEnabled(void);
138150
bool getAutomaticSelfCalibrationEnabled(uint16_t *enabled);
139151

140-
bool startLowPowerPeriodicMeasurement(void);
141-
bool getDataReadyStatus(void);
152+
bool startLowPowerPeriodicMeasurement(void); // Start low power measurements - receive data every 30 seconds
153+
bool getDataReadyStatus(void); // Returns true if fresh data is available
142154

143-
bool persistSettings(uint16_t delayMillis = 800);
155+
bool persistSettings(uint16_t delayMillis = 800); // Copy sensor settings from RAM to EEPROM
144156
bool getSerialNumber(char *serialNumber); // Returns true if serial number is read correctly
145-
bool performSelfTest(void);
146-
bool performFactoryReset(uint16_t delayMillis = 1200);
147-
bool reInit(uint16_t delayMillis = 20);
157+
bool performSelfTest(void); // Takes 10 seconds to complete. Returns true if the test is successful
158+
bool performFactoryReset(uint16_t delayMillis = 1200); // Reset all settings to the factory values
159+
bool reInit(uint16_t delayMillis = 20); // Re-initialize the sensor, load settings from EEPROM
148160

149-
bool measureSingleShot(void); // SCD41 only
150-
bool measureSingleShotRHTOnly(void); // SCD41 only
161+
bool measureSingleShot(void); // SCD41 only. Request a single measurement. Data will be ready in 5 seconds
162+
bool measureSingleShotRHTOnly(void); // SCD41 only. Request RH and T data only. Data will be ready in 50ms
151163

152164
bool sendCommand(uint16_t command, uint16_t arguments);
153165
bool sendCommand(uint16_t command);

0 commit comments

Comments
 (0)