SCD30 and ESPhome negative temperature

Hello

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

Hello - I had this problem. As far as I can tell, it’s a bug. Here’s what I do:

    temperature:
      name: "Bedroom Temperature"
      accuracy_decimals: 1
      filters:
        - offset: 1.5

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:

    co2:
      name: "Bedroom CO2"
      accuracy_decimals: 0
      filters:
        - offset: -50.0
        - exponential_moving_average:
            send_every: 5