I have the SCD30 on a Wemos D1 mini.
The temperature and humidity values were correct until I changed the temperature_offset value from 0°C to -2°C. As a result, the sensor gave negative temperature readings and infinite humidity %.
To check, I later changed the temperature_offset from -2°C to 0°C. However, the sensor continues to give negative temperature values.
Can someone help me further?
Below the log:
[19:03:09][C][scd30:121]: scd30:
[19:03:09][C][scd30:122]: Address: 0x61
[19:03:09][C][scd30:140]: Altitude compensation: OFF
[19:03:09][C][scd30:144]: Automatic self calibration: ON
[19:03:09][C][scd30:145]: Ambient pressure compensation: 0mBar
[19:03:09][C][scd30:146]: Temperature offset: 0.00 °C
[19:03:09][C][scd30:147]: Update interval: 10s
[19:03:09][C][scd30:148]: CO2 'SCD30 CO2 44'
[19:03:09][C][scd30:148]: State Class: 'measurement'
[19:03:09][C][scd30:148]: Unit of Measurement: 'ppm'
[19:03:09][C][scd30:148]: Accuracy Decimals: 1
[19:03:09][C][scd30:148]: Icon: 'mdi:molecule-co2'
[19:03:09][C][scd30:149]: Temperature 'SCD30 TEMP 44'
[19:03:09][C][scd30:149]: Device Class: 'temperature'
[19:03:09][C][scd30:149]: State Class: 'measurement'
[19:03:09][C][scd30:149]: Unit of Measurement: '°C'
[19:03:09][C][scd30:149]: Accuracy Decimals: 2
[19:03:09][C][scd30:150]: Humidity 'SCD30 HUMIDITY 44'
[19:03:09][C][scd30:150]: Device Class: 'humidity'
[19:03:09][C][scd30:150]: State Class: 'measurement'
[19:03:09][C][scd30:150]: Unit of Measurement: '%'
[19:03:09][C][scd30:150]: Accuracy Decimals: 1
[19:03:09][C][captive_portal:151]: Captive Portal:
[19:03:09][C][ota:082]: Over-The-Air Updates:
[19:03:09][C][ota:083]: Address: espd1mini3.local:8266
[19:03:09][C][ota:086]: Using Password.
[19:03:09][C][api:134]: API Server:
[19:03:09][C][api:135]: Address: espd1mini3.local:6053
[19:03:09][C][api:139]: Using noise encryption: NO
[19:03:09][C][mdns:084]: mDNS:
[19:03:09][C][mdns:085]: Hostname: espd1mini3
[19:03:18][D][scd30:187]: Got CO2=974.57ppm temperature=-48.60°C humidity=14907.10%
[19:03:18][D][sensor:113]: 'SCD30 CO2 44': Sending state 974.56750 ppm with 1 decimals of accuracy
[19:03:18][D][sensor:113]: 'SCD30 TEMP 44': Sending state -48.59838 °C with 2 decimals of accuracy
[19:03:18][D][sensor:113]: 'SCD30 HUMIDITY 44': Sending state 14907.09961 % with 1 decimals of accuracy
[19:03:30][D][scd30:187]: Got CO2=975.50ppm temperature=-47.88°C humidity=13683.24%
[19:03:30][D][sensor:113]: 'SCD30 CO2 44': Sending state 975.49506 ppm with 1 decimals of accuracy
[19:03:30][D][sensor:113]: 'SCD30 TEMP 44': Sending state -47.87605 °C with 2 decimals of accuracy
[19:03:30][D][sensor:113]: 'SCD30 HUMIDITY 44': Sending state 13683.24121 % with 1 decimals of accuracy
[19:03:41][D][scd30:187]: Got CO2=973.89ppm temperature=-47.12°C humidity=12593.79%
[19:03:41][D][sensor:113]: 'SCD30 CO2 44': Sending state 973.89496 ppm with 1 decimals of accuracy
[19:03:41][D][sensor:113]: 'SCD30 TEMP 44': Sending state -47.11678 °C with 2 decimals of accuracy
[19:03:41][D][sensor:113]: 'SCD30 HUMIDITY 44': Sending state 12593.78809 % with 1 decimals of accuracy
BTW, I also observed 2 identical SCD30’s producing wildly different values. Turned out their calibration settings, temperature offsets, and altitudes were different. I modified an Adafruit example script to fire them both up, sit for 5 minutes (outside), force calibrate the CO2 sensor to 400ppm, then turn off autocalibrate.
// Firmware to force calibrate an SCD30 to 400 ppm
// Place outdoors. Power up. After 5 minutes, the onboard LED illumates to
// signal calibration compelete.
#include <Adafruit_SCD30.h>
#include <Arduino.h>
#include <SimpleTimer.h>
Adafruit_SCD30 scd30;
SimpleTimer timer_5min(5 * 60 * 1000); // 5 minute
bool calibrated = false;
void setup(void) {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); // Off
Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
Serial.println("Adafruit SCD30 Sensor adjustment test!");
// Try to initialize!
if (!scd30.begin()) {
Serial.println("Failed to find SCD30 chip");
while (1) {
delay(10);
}
}
Serial.println("SCD30 Found!");
/***
* The code below will report the current settings for each of the
* settings that can be changed. To see how they work, uncomment the setting
* code above a status message and adjust the value
*
* **Note:** Since Automatic self calibration and forcing recalibration with
* a reference value overwrite each other, you should only set one or the
*other
***/
/*** Adjust the rate at which measurements are taken, from 2-1800 seconds */
// if (!scd30.setMeasurementInterval(5)) {
// Serial.println("Failed to set measurement interval");
// while(1){ delay(10);}
// }
Serial.print("Measurement interval: ");
Serial.print(scd30.getMeasurementInterval());
Serial.println(" seconds");
/*** Restart continuous measurement with a pressure offset from 700 to 1400
* millibar. Giving no argument or setting the offset to 0 will disable offset
* correction
*/
// if (!scd30.startContinuousMeasurement(0)){
// Serial.println("Failed to set ambient pressure offset");
// while(1){ delay(10);}
// }
Serial.print("Ambient pressure offset: ");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
/*** Set an altitude offset in meters above sea level.
* Offset value stored in non-volatile memory of SCD30.
* Setting an altitude offset will override any pressure offset.
*/
// if (!scd30.setAltitudeOffset(110)){
// Serial.println("Failed to set altitude offset");
// while(1){ delay(10);}
// }
Serial.print("Altitude offset: ");
Serial.print(scd30.getAltitudeOffset());
Serial.println(" meters");
/*** Set a temperature offset in hundredths of a degree celcius.
* Offset value stored in non-volatile memory of SCD30.
*/
if (!scd30.setTemperatureOffset(0)) { // 19.84 degrees celcius
Serial.println("Failed to set temperature offset");
while (1) {
delay(10);
}
}
Serial.print("Temperature offset: ");
Serial.print((float)scd30.getTemperatureOffset() / 100.0);
Serial.println(" degrees C");
/*** Force the sensor to recalibrate with the given reference value
* from 400-2000 ppm. Writing a recalibration reference will overwrite
* any previous self calibration values.
* Reference value stored in non-volatile memory of SCD30.
*/
// if (!scd30.forceRecalibrationWithReference(400)){
// Serial.println("Failed to force recalibration with reference");
// while(1) { delay(10); }
// }
Serial.print("Forced Recalibration reference: ");
Serial.print(scd30.getForcedCalibrationReference());
Serial.println(" ppm");
/*** Enable or disable automatic self calibration (ASC).
* Parameter stored in non-volatile memory of SCD30.
* Enabling self calibration will override any previously set
* forced calibration value.
* ASC needs continuous operation with at least 1 hour
* 400ppm CO2 concentration daily.
*/
// if (!scd30.selfCalibrationEnabled(true)){
// Serial.println("Failed to enable or disable self calibration");
// while(1) { delay(10); }
// }
if (scd30.selfCalibrationEnabled()) {
Serial.print("Self calibration enabled");
} else {
Serial.print("Self calibration disabled");
}
Serial.println("\n\n");
}
uint32_t start_millis = millis();
void loop() {
if (scd30.dataReady()) {
if (!scd30.read()) {
Serial.println("Error reading sensor data");
return;
}
Serial.print("Temperature: ");
Serial.print(scd30.temperature);
Serial.println(" degrees C");
Serial.print("Relative Humidity: ");
Serial.print(scd30.relative_humidity);
Serial.println(" %");
Serial.print("CO2: ");
Serial.print(scd30.CO2, 3);
Serial.println(" ppm");
Serial.println("");
}
delay(100);
if (timer_5min.isReady() && !calibrated) {
if (!scd30.forceRecalibrationWithReference(400)) {
Serial.println("Failed to force recalibration with reference");
while (1) {
delay(10);
}
} else {
if (!scd30.selfCalibrationEnabled(false)) {
Serial.println("Failed to enable or disable self calibration");
while (1) {
delay(10);
}
}
digitalWrite(LED_BUILTIN, LOW); // On
Serial.println();
Serial.println("Forced recalibration with reference 400ppm");
Serial.println("Self calibration disabled");
Serial.println();
calibrated = true;
}
}
}
Temperate and humidity were within 1 or 2%, but CO2’s were different by ~10%. So I add this, and add in some averaging:
I am having this exact same problem. Problem is I can’t get the bug to go away same as OP. My humidity value quickly converges to infinity.
[22:59:31][D][sensor:125]: 'SCD30 CO2': Sending state 713.61096 ppm with 1 decimals of accuracy
[22:59:31][D][sensor:125]: 'SCD30 Temperature': Sending state -439.50809 °C with 1 decimals of accuracy
[22:59:31][D][sensor:125]: 'SCD30 Humidity': Sending state 0.00000 % with 1 decimals of accuracy
I have set all the values back to normal and even flashed the esp8266 with a new config and still the same thing.
I cannot thank you enough for this Arduino IDE calibration script! Worked like a charm. I calibrated 2 sensors that both had widely different CO2 readings from one other. Same situation as you that got me concerned about accuracy to begin with.
I am not sure if it matters but I added:
automatic_self_calibration: false
To my ESPhome config just in case it reverts back since I think it defaults to true.
Getting the LOLIN/Wemos D1 mini libraries and the Adafruit SDC30 libraries into Arduino IDE was easy enough and the script runs great. I was afraid the calibration wasn’t going to be persistent after reboot but indeed it is.
If only ESPhome could add this as a feature that didn’t require all the extra work with Arduino IDE it would be awesome, none the less it’s much appreciated again.
I’ve just run into this. Reverting the offset setting, recalibrating the SCD30 or unpowering the ESP32 did not help. Seems like this bug is still present. Any hints what I could try to recover a working state?