esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 34 forks source link

SPS30 not initializing #2735

Closed matthijsberg closed 2 years ago

matthijsberg commented 2 years ago

The problem

I have a Lolin D1 mini board connected to a Sensirion SPS30 sensor via I2C. When I run connect ESPhome to this the sensor is not recognized. The log message is:

[11:50:40][C][sps30:068]:   Address: 0x69
[11:50:40][W][sps30:084]: Unable to request sensor firmware version
[11:50:40][C][sps30:094]:   Update Interval: 10.0s
[11:50:40][C][sps30:095]:   Serial Number: ''

When i start up Arduino and use an example sketch myself using this lib (https://github.com/paulvha/sps30) it works like a charm and the readings come in. So from a hardware perspective it looks good.

16:05:05.054 -> Trying to connect
16:05:05.054 -> Detected SPS30.
16:05:07.072 ->     Serial number : 6B19E22CD975E11A
16:05:07.072 ->     Product name  : 00080000
16:05:07.072 -> Firmware level: 1.0
16:05:07.072 -> Library level : 1.4
16:05:07.072 -> Detected SCD30
16:05:07.072 ->     Serial number : 215165⸮
16:05:08.106 -> Measurement started
16:05:08.106 -> 
16:05:08.106 -> Hit <enter> to continue reading
16:05:10.114 -> Hit <enter> to continue reading
16:05:12.095 -> Hit <enter> to continue reading
16:05:14.101 -> ==================================== SPS30 ===================================== ========= SCD30 ==========
16:05:14.134 -> -------------Mass -----------    ------------- Number --------------   -Average- CO2   Humidity Temperature
16:05:14.134 ->      Concentration [μg/m3]             Concentration [#/cm3]             [μm]    [ppm]    [%]      [*C]
16:05:14.134 -> P1.0    P2.5    P4.0    P10 P0.5    P1.0    P2.5    P4.0    P10 PrtSize
16:05:14.134 -> 
16:05:14.134 -> 7.78    11.73   14.17   15.29   43.44   55.81   59.20   59.63   59.71   0.69      1507   45.6     25.99

My knowledge about the libs / integration in ESP is limited, but the initialization looks a bit different init or checking for the S/N, etc. Because when I flash it manually it works, and when I flash it afterwards with ESPhome I get a different result:

During init I now get:

[12:48:49][C][sps30:067]: sps30:
[12:48:49][C][sps30:068]:   Address: 0x69
[12:48:49][C][sps30:094]:   Update Interval: 10.0s
[12:48:49][C][sps30:095]:   Serial Number: '6B19E22CD975E11A'

During probing I nog get

[12:46:45][D][sps30:105]: Trying to reconnect the sensor...
[12:46:45][D][sps30:116]: Sensor soft-reset failed. Is the sensor offline?

Which version of ESPHome has the issue?

2021.11.1

What type of installation are you using?

Home Assistant Add-on

Which version of Home Assistant has the issue?

core-2021.11.4

What platform are you using?

ESP8266

Board

Lolin D1 Mini

Component causing the issue

SPS30 sensor over I2C

Example YAML snippet

#----
# AirQual Meter sensor thingy

substitutions:
  device_name_friendly: 'AQ! Ceiling Overloop D1'
  device_name: 'aqi-overloop'
  wifi_fb_password: 'xxx'
  scd30_temp_offset: '5.7'
#No changes after here required.

esphome:
  name: ${device_name}
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: !secret wifi_ssid_iot
  password: !secret wifi_password_iot
  fast_connect: true

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: '${device_name_friendly} Fallback'
    password: ${wifi_fb_password}

# captive_portal:

# Example configuration entry
debug:

# Logger must be at least debug (default)
logger:
  level: debug

#web_server:
#  port: 80

# Enable Home Assistant API
api:
  password: !secret esphome_local
  reboot_timeout: 300s
  encryption: 
    key: !secret esphome_api_key
  id: device_name

ota:
  password: !secret esphome_local

i2c:
  sda: D2
  scl: D1
  scan: True
  id: bus_a
  frequency: 100kHz

time:
  - platform: homeassistant
    id: homeassistant_time

sensor:
  - platform: scd30
    i2c_id: bus_a
    address: 0x61
    co2:
      name: '${device_name_friendly} CO2'
      accuracy_decimals: 1
    temperature:
      name: '${device_name_friendly} Temperature'
      id: scd30_temperature
      accuracy_decimals: 1
    humidity:
      name: '${device_name_friendly} Humidity'
      id: scd30_humidity
      accuracy_decimals: 1
    temperature_offset: ${scd30_temp_offset}
    update_interval: 10s
    altitude_compensation: 7m

  - platform: sgp30
    i2c_id: bus_a
    address: 0x58
    eco2:
      name: '${device_name_friendly} eCO2'
      accuracy_decimals: 1
    tvoc:
      name: '${device_name_friendly} TVOC'
      accuracy_decimals: 1
    update_interval: 10s
    compensation:
      temperature_source: scd30_temperature
      humidity_source: scd30_humidity

  - platform: sps30
    i2c_id: bus_a
    address: 0x69
    pm_1_0:
      name: '${device_name_friendly} <1µm Weight concentration'
    pm_2_5:
      name: '${device_name_friendly} <2.5µm Weight concentration'
    pm_4_0:
      name: '${device_name_friendly} <4µm Weight concentration'
    pm_10_0:
      name: '${device_name_friendly} <10µm Weight concentration'
    pmc_0_5:
      name: '${device_name_friendly} <0.5µm Number concentration'
    pmc_1_0:
      name: '${device_name_friendly} <1µm Number concentration'
    pmc_2_5:
      name: '${device_name_friendly} <2.5µm Number concentration'
    pmc_4_0:
      name: '${device_name_friendly} <4µm Number concentration'
    pmc_10_0:
      name: '${device_name_friendly} <10µm Number concentration'
    update_interval: 10s

Anything in the logs that might be useful for us?

[11:50:40][C][sps30:068]:   Address: 0x69
[11:50:40][W][sps30:084]: Unable to request sensor firmware version
[11:50:40][C][sps30:094]:   Update Interval: 10.0s
[11:50:40][C][sps30:095]:   Serial Number: ''


### Additional information

_No response_
martgras commented 2 years ago

I'm seeing the same issue with my sps30. Adding 2 12k pullup resistors (to 3.3v) seems to reduce the frequency of the problem. However it's happening from time to time with my second one that is on the same i2c bus with spg40 and scd41 which have pull-ups on the breakout. If I have time next week I'll have a look at the code.

matthijsberg commented 2 years ago

Thanks, really appreciate this! I have been playing with resistors at no success with ESPhome. I have, like you, 2 other sensors connected in the same I2C bus that have internal pull-up resistors, and with the PaulvH code this works every time. So hardware wise it's able to work.

Playing with the bus frequency going both up and down from 10 to 200 has no effect either.

Looking forward to what you find.

martgras commented 2 years ago

Can you try my fork. I changed the size of the "read fw version command". Not sure if that makes a difference for you.

Just add this to your YAML for testing

external_components:
  - source: github://martgras/esphome@sps30-fix
    components: ["sps30"]
matthijsberg commented 2 years ago

thanks.

Current status is that when I use this fork I get a firmware reading:

[sps30:094]:   Serial Number: '6B19E12CD975X11A' 

But for the value part I still get this:

[22:22:27][D][sps30:104]: Trying to reconnect the sensor...
[22:22:27][D][sps30:115]: Sensor soft-reset failed. Is the sensor offline?

tried different freq. from 10 to 100.

Weird thing is when I reflash the board, I do not get a serial number too ([sps30:083]: Unable to request sensor firmware version), and when I physically power cycle by unplugging and plugging back in, it does read s/n again.

martgras commented 2 years ago

I only get this behavior without pullups on my test setup using only a SPS30 sensor. On my "air monitor" with all the other sensors I have not seen the problem for quite some time. Can you try testing only SPS30 without other sensors connected. I can't spot any real difference to the code from https://github.com/paulvha/sps30 (Well esphome uses different i2c code )

matthijsberg commented 2 years ago

thanks. modified this to use 10K pullups as per the manual from Sensirion.

Current status is that when I use this fork I get a firmware reading:

[sps30:094]:   Serial Number: '6B19E12CD975X11A' 

But for the value part I still get this (verbose logging):

[10:36:48][D][sps30:104]: Trying to reconnect the sensor...
[10:36:48][VV][i2c.idf:161]: 0x69 TX D304
[10:36:48][VV][i2c.idf:198]: TX to 69 failed: not acked
[10:36:48][D][sps30:115]: Sensor soft-reset failed. Is the sensor offline?

tried different freq. from 10 to 100 and 2 types of boards.

Weird thing is when I reflash the board ota, I do not get a serial number too ([sps30:083]: Unable to request sensor firmware version), and when I physically power cycle by unplugging and plugging back in, it does read s/n again.

matthijsberg commented 2 years ago

I put in the paulvh sketch and enabled debugging to see what happens in terms of I2C communication when it works. Maybe it helps.

What I see, with my limited knowledge, is that the below sends both a "reset" and a "Read Serial Number", not only a reset (D304). Could that make a difference?

12:52:24.237 -> SPS30-Example13: Basic reading with any I2C channel select. press <enter> to start
12:52:26.211 -> Trying to connect.
12:52:26.211 -> I2C Sending:  0xD1 0x00 **_(Read Firmware Version)_**
12:52:26.211 -> I2C Received: 0x01 0x00 length: 2
12:52:26.246 -> 
12:52:26.246 -> Detected SPS30.
12:52:26.246 -> I2C Sending:  0xD3 0x04 _**(Reset)**_
12:52:28.212 -> I2C Sending:  0xD0 0x33 **_(Read Serial Number)_**
12:52:28.212 -> I2C Received: 0x36 0x42 0x31 0x39 0x45 0x32 0x32 0x43 0x44 0x39 0x37 0x35 0x45 0x31 0x31 0x41 0x00 0x00 length: 18
12:52:28.249 -> 
12:52:28.249 -> Serial number : 6B19E22CD975E11A
12:52:28.249 -> I2C Sending:  0xD0 0x02 _**(Read Product Type)**_
12:52:28.249 -> I2C Received: 0x30 0x30 0x30 0x38 0x30 0x30 0x30 0x30 length: 8
12:52:28.249 -> 
12:52:28.249 -> Product name  : 00080000
12:52:28.249 -> I2C Sending:  0xD1 0x00 **_(Read Firmware Version)_**
12:52:28.249 -> I2C Received: 0x01 0x00 length: 2
12:52:28.249 -> 
12:52:28.249 -> Firmware level: 1.0
12:52:28.249 -> Library level : 1.4
12:52:28.249 -> I2C Sending:  0x00 0x10 0x03 0x00 0xAC **_(0010 = Start Measurement, 0300 = Read Measured Values)_**
12:52:29.265 -> Measurement started
12:52:29.265 -> 
12:52:29.265 -> Hit <enter> to continue reading.

12:52:45.252 -> I2C Sending:  0x02 0x02 **_(Read Data-Ready Flag)_**
12:52:45.252 -> I2C Received: 0x00 0x01 length: 2
12:52:45.252 -> 
12:52:45.252 -> I2C Sending:  0x03 0x00 **_(Read Measured Values)_**
12:52:45.252 -> I2C Received: 0x3F 0xD8 0xD4 0x62 0x40 0x11 0x7D 0xB9 0x40 0x24 0x3D 0xFE 0x40 0x2E 0x03 0x99 0x41 0x22 0x3A 0x97 0x41 0x47 0x5A 0xC2 0x41 0x4E 0x60 0x57 0x41 0x4F 0x31 0x39 0x41 0x4F 0x59 0x37 0x3F 0x44 0xE7 0x4B length: 40
12:52:45.286 -> 
12:52:45.286 -> -------------Mass -----------    ------------- Number --------------   -Average-
12:52:45.286 ->      Concentration [μg/m3]             Concentration [#/cm3]             [μm]
12:52:45.286 -> P1.0    P2.5    P4.0    P10 P0.5    P1.0    P2.5    P4.0    P10 PartSize
12:52:45.323 -> 
12:52:45.323 -> 1.69    2.27    2.57    2.72    10.14   12.46   12.90   12.95   12.96   0.77
12:52:48.319 -> I2C Sending:  0x02 0x02
12:52:48.319 -> I2C Received: 0x00 0x01 length: 2
12:52:48.319 -> 
12:52:48.319 -> I2C Sending:  0x03 0x00
12:52:48.319 -> I2C Received: 0x3F 0xE4 0xC6 0x40 0x40 0x0E 0x39 0xA1 0x40 0x18 0x67 0xC7 0x40 0x1F 0x0D 0x2B 0x41 0x31 0xF5 0x23 0x41 0x55 0x64 0x8C 0x41 0x59 0xC7 0xB9 0x41 0x5A 0x3A 0x07 0x41 0x5A 0x50 0xF1 0x3F 0x2F 0x3D 0x7C length: 40
12:52:48.319 -> 
12:52:48.319 -> 1.79    2.22    2.38    2.49    11.12   13.34   13.61   13.64   13.64   0.68
12:52:51.306 -> I2C Sending:  0x02 0x02
12:52:51.306 -> I2C Received: 0x00 0x01 length: 2
12:52:51.306 -> 
12:52:51.306 -> I2C Sending:  0x03 0x00
12:52:51.343 -> I2C Received: 0x3F 0xF5 0x80 0x2E 0x40 0x16 0x41 0x3D 0x40 0x1F 0x29 0xAC 0x40 0x25 0x86 0x7E 0x41 0x40 0x65 0x0B 0x41 0x65 0xA2 0xDE 0x41 0x69 0xB5 0xC0 0x41 0x6A 0x1A 0x24 0x41 0x6A 0x2E 0xAF 0x3F 0x2A 0x15 0xAD length: 40
12:52:51.343 -> 
12:52:51.343 -> 1.92    2.35    2.49    2.59    12.02   14.35   14.61   14.63   14.64   0.66
matthijsberg commented 2 years ago

I think I may have found it.

I compared both I2C traffic against each other and the only major difference I found is the I2C bus scan. This scan happens between "Start Measurement" and "Read Data-Ready Flag". My log of the flow:

  1. D304 |   | Reset
  2. -- | -- | --
  3. 0202 |   | Read Product Type
  4. D100 |   | Read Firmware Version
  5. D033 |   | Read Serial Number
  6. 00100300AC |   | 0010 = Start Measurement, 0300 = Read Measured Values 7. TX |   | I2C Bus Scan
  7. 0202 |   | Read Data-Ready Flag
  8.   | No Ack! |  
  9. D304 |   | Reset
  10.   | No Ack! |  

When I add scan: False to the I2C part of the config it seams to work fine in my first tests.

Not sure what is send to detect the devices on the I2C bus during scan, but perhaps this "bit" is in the way of other commands.