Did temperature_compensation break my SCD30?

Have been running a SCD30 - SCD30 CO₂, Temperature and Relative Humidity Sensor — ESPHome - for a year without any issues. Just now saw that the temperature was a bit off and tried setting the temperature_offset value to first -2.0 °C, then 0.25 °C and finally removed it altogether from the configuration. Unfortunately now the temperature reading is way off showing minus degrees and fluctuating wildly, even with temperature_offset removed :frowning:

Any idea how to recover my sensor? ESPhome 2023.5.5

sensor:
  - platform: uptime
    name: Uptime Sensor
  - platform: scd30
    co2:
      id: my_sensor
      name: "Arbetsrum CO2"
      accuracy_decimals: 1
    temperature:
      name: "Arbetsrum Temp"
      id: temp
      accuracy_decimals: 1
    humidity:
      name: "Arbetsrum Fuktighet"
      id: hum
      accuracy_decimals: 1
    address: 0x61
    automatic_self_calibration: true

OK - google is your friend - seems like this is a known issue with ESPhome - Setting SCD30 temperature offset causes the sensor to report bogus values · Issue #3063 · esphome/issues · GitHub
Will try to recover the sensor with the instructions in the thread. Would be nice if the PR fixing this would be merged or at least the docs would be updated…

OK - took 30 minutes but I have now recovered my sensor. Here are the steps if someone finds themselves in the same situation:

  1. Install micropython tools. I won’t go into details here because you will have to ruin your own python installation.
  2. Find firmware for your device at MicroPython - Python for microcontrollers - I have a Wemos D1 and used the ESP8266 firmware
  3. Use esptool.py to flash the micropython firmware. For my D1 I used the following commands:
esptool.py erase_flash
esptool.py --chip esp8266 write_flash --flash_mode dio --flash_size detect 0x0 Downloads/esp8266-20230426-v1.20.0.bin
  1. Install the SCD30 library on the device:
mpremote  mip install github:agners/micropython-scd30/scd30.py
  1. Connect to the device and use python commands to reset the calibration. Notice that I2C my be different and that ESP8266 doesn’t have a master address argument to I2C():
$ mpremote
Connected to MicroPython at /dev/cu.usbserial-310
Use Ctrl-] or Ctrl-x to exit this shell

>>> from machine import I2C, Pin
>>> from scd30 import SCD30
>>> i2cbus = I2C(scl=Pin(5), sda=Pin(4))
>>> i2cbus.scan()
[32, 60, 97]
>>> scd30 = SCD30(i2cbus, 0x61)
>>> scd30.get_status_ready()
1
>>> scd30.read_measurement()
(996.998, -115.996, 1.6135e+09)
>>> scd30.get_temperature_offset()
655.11
>>> scd30.set_temperature_offset(0)
>>> scd30.soft_reset()
>>> scd30.get_status_ready()
0
>>> scd30.get_status_ready()
0
>>> scd30.get_status_ready()
0
>>> scd30.get_status_ready()
0
>>> scd30.get_status_ready()
1
>>> scd30.read_measurement()
(1824.33, 25.2243, 31.9565)
>>> scd30.read_measurement()
(nan, nan, nan)
>>> scd30.read_measurement()
(954.115, 25.3925, 31.0974)
  1. Reflashed the ESPhome firmware with esphomeflasher.
  2. All is well.
1 Like

THANK YOU, @msa !

Thank you for confirming that I am not crazy, seeing my office at -650C! Thank you for these helpful instructions!

Of course, I am not confident enough to try this. :grinning:

But there is an open bug in ESPHome, with a known fix. When will ESPHome accept the patch and release a correct version? (I have not been using ESPHome for long, and so I am unfamiliar with their tempo.)

Unfortunately I have no clue when it will be fixed, given 872 open issues I guess the maintainers are struggling to keep up. I’ve been using ESPhome for many years and this is the first time I have encountered a bug with the project.

I hope you muster some courage to try restoring your sensor - be brave! :slight_smile:

1 Like

With your encouragement, I tried it – and it worked! Now it’s only 26C in my office: much more comfortable than -650C on Monday! :smile:

Congrats! Well done! :smiley:

1 Like

If you want to avoid the integration of the scd30 library in msa´s solution, you can just manually write registers in the Micropython REPL:

from machine import I2C, Pin
i2cbus = I2C(scl=Pin(5), sda=Pin(4))
i2cbus.scan()
i2cbus.writeto(97,b'\xd3\x04')
# Wait some seconds
i2cbus.writeto_mem(0x61, 0x5403, b'\x00\x00\x81', addrsize=16)
i2cbus.writeto(97,b'\xd3\x04')