esphome / issues

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

Sonoff TH Origin 16A (THR316D) + Sonoff Temp and Humidity Sensor THS01 (SI7021) Invalid Readings #4189

Open paulguru opened 1 year ago

paulguru commented 1 year ago

The problem

Hi ESPHome team,

I'm struggling to get the Sonoff Temp and Humidity Sensor THS01 (SI7021) working on the Sonoff TH Origin 16A (THR316D).

I used the yaml configuration of the Sonoff THR320D (https://www.esphome-devices.com/devices/Sonoff-THR320D) as the base for the configuration of the THR316D with some changes (since the THR316D uses a slightly different GPIO's).

I ruled out hardware issues as the sensor works when using Tasmota32.bin firmware.

FYI - I tried compiling using various board and framework options i.e. nodemcu-32s/esp32dev and esp-idf/arduino but this does not seem to have an effect.

Which version of ESPHome has the issue?

2023.2.1

What type of installation are you using?

Home Assistant Add-on

Which version of Home Assistant has the issue?

Home Assistant 2023.2.5

What platform are you using?

ESP32-IDF

Board

nodemcu-32s

Component causing the issue

DHT

Example YAML snippet

substitutions:
  device_name: sonoffth316d
  location: Garage

esphome:
  name: "${device_name}"
  friendly_name: Sonoff Elite TH 1
  # supply the external temp/hum sensor with 3v power by pulling this GPIO high
  on_boot:
    - priority: 90
      then:
      - switch.turn_on: TH_sensor_power

esp32:
  board: nodemcu-32s
  #board: esp32dev
  framework:
    type: esp-idf
  #  type: arduino

# Enable logging
logger:
  baud_rate: 0
#  level: VERBOSE
#  level: VERY_VERBOSE

# Enable Home Assistant API
api:
  encryption:
    key: "XXXXX"

ota:
  password: "XXXXX"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: XXXXX
    gateway: XXXXX
    subnet: XXXXX

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${device_name}"
    password: !secret wifi_debug

#captive_portal:

#### TIME ####

time:
  - platform: homeassistant
    id: homeassistant_time

### BUTTON ###

button:
  - platform: restart
    name: $device_name Restart
    device_class: restart
    entity_category: diagnostic

### DISPLAY ###

display:
  platform: tm1621
  id: tm1621_display
  cs_pin: GPIO17
  data_pin: GPIO5
  read_pin: GPIO23
  write_pin: GPIO18
  lambda: |-
    it.printf(0, "%.1f", id(${device_name}_temp).state);
    it.display_celsius(true);
    it.printf(1, "%.1f", id(${device_name}_humi).state);
    it.display_humidity(true);

### BINARY SENSOR ###

binary_sensor:
  # single main button that also puts device into flash mode when held on boot
  - platform: gpio
    pin:
      number: GPIO0
      mode: INPUT_PULLUP
      inverted: True
    name: "${device_name} Button"
    on_press:
      then:
        - switch.toggle: relay_1

  - platform: status
    name: "${device_name} Status"

### SWITCH ###

switch:

# Main Relay GPIO21

  - platform: gpio
    name: ${device_name}_relay
    pin: GPIO21
    id: relay_1
    # after reboot, keep the relay off. this prevents light turning on after a power outage
    restore_mode: ALWAYS_OFF
    on_turn_on:
      light.turn_on: power_led
    on_turn_off:
      light.turn_off: power_led

  # dry contact relay switch
  - platform: gpio
    id: dryContRelay
    name: "Dry Contact Relay"
    pin:
      number: GPIO4
      inverted: true
    on_turn_on:
      light.turn_on: green_led
    on_turn_off:
      light.turn_off: green_led

  - platform: gpio
    pin:
      number: GPIO27
    #  inverted: false 
    id: TH_sensor_power
    restore_mode: ALWAYS_ON

### OUTPUT ###

# LEDs need gpio output defined
output:
  # Power LED
  - id: power_led_output
    platform: gpio
    pin: 16
    inverted: True

  # GREEN LED 
  - id: green_led_output
    platform: gpio
    pin: 13
    inverted: True

### LIGHT ###

light:
  # Power LED
  - platform: binary
    id: power_led
    name: "Power LED"
    output: power_led_output
    internal: true

  # Green LED
  - platform: binary
    id: green_led
    name: "Green LED"
    output: green_led_output
    internal: true

  # Blue LED (middle). Used as wifi status indicator.
  - platform: status_led
    name: "${device_name} Wifi LED"
    pin:
      number: GPIO15
      inverted: true
    id: wifi_led  
    internal: true   

### INTERVAL ###

interval:
  - interval: 60s
    then:
      if:
        condition:
          wifi.connected:
        then:
          - light.turn_on: wifi_led
        else:
          - light.turn_off: wifi_led

### SENSOR ###

sensor:
  # "Sonoff THS01 - SI7021"
  - platform: dht
    pin: GPIO25
    model: SI7021
    temperature:
      name: "${location} Temperature"
      id: ${device_name}_temp
    humidity:
      name: "${location} Humidity"
      id: ${device_name}_humi
    update_interval: 60s

  - platform: wifi_signal
    name: $device_name Wifi RSSI
    update_interval: 60s

  - platform: uptime
    id: uptime_sensor
    internal: True
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human
            state: !lambda |-
              int seconds = round(id(uptime_sensor).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? to_string(days) + "d " : "") +
                (hours ? to_string(hours) + "h " : "") +
                (minutes ? to_string(minutes) + "m " : "") +
                (to_string(seconds) + "s")
              ).c_str();

#### TEXT SENSOR ####

text_sensor:
  - platform: version
    name: "ESPHome Version"
    hide_timestamp: true

  - platform: template
    name: $device_name Uptime
    id: uptime_human
    icon: mdi:clock-start

  - platform: wifi_info
    ip_address:
      name: $device_name IP
    mac_address:
      name: $device_name MAC Address

Anything in the logs that might be useful for us?

Log file snippets:
1) Sensor startup messages
2) Sensor Error messages

1) Sensor startup messages // ########################
[11:02:44][C][dht:017]: DHT:
[11:02:44][C][dht:018]:   Pin: GPIO25
[11:02:44][C][dht:024]:   Model: DHT22 (or equivalent)
[11:02:44][C][dht:027]:   Update Interval: 60.0s
[11:02:44][C][dht:029]:   Temperature 'Garage Temperature'
[11:02:44][C][dht:029]:     Device Class: 'temperature'
[11:02:44][C][dht:029]:     State Class: 'measurement'
[11:02:44][C][dht:029]:     Unit of Measurement: '°C'
[11:02:44][C][dht:029]:     Accuracy Decimals: 1
[11:02:44][C][dht:030]:   Humidity 'Garage Humidity'
[11:02:44][C][dht:030]:     Device Class: 'humidity'
[11:02:44][C][dht:030]:     State Class: 'measurement'
[11:02:44][C][dht:030]:     Unit of Measurement: '%'
[11:02:44][C][dht:030]:     Accuracy Decimals: 0

2) Sensor Error messages // ######################

[11:03:43][W][dht:169]: Requesting data from DHT failed!
[11:03:43][W][dht:060]: Invalid readings! Please check your wiring (pull-up resistor, pin number).
[11:03:43][D][sensor:127]: 'Garage Temperature': Sending state nan °C with 1 decimals of accuracy
[11:03:43][D][sensor:127]: 'Garage Humidity': Sending state nan % with 0 decimals of accuracy

Additional information

No response

Jenda987 commented 1 year ago

Maybe it's necessary to turn on power ...


  - platform: gpio
    id: power
    pin: GPIO27
    restore_mode: ALWAYS_ON
paulguru commented 1 year ago

Maybe it's necessary to turn on power ...

  - platform: gpio
    id: power
    pin: GPIO27
    restore_mode: ALWAYS_ON

Thanks @Jenda987, I have tried turning on the power (both as switch and as an outout). Neither seems to work.

Beungoud commented 1 year ago

There seems to be a timing problem in the dht component when running on an ESP32. Looking at tasmota source code, they have a slightly different timing for ESP32 when using SI7021: https://github.com/arendst/Tasmota/blob/e80d053aa0bfb12ce1d4d6a2884be6c886d3669d/tasmota/tasmota_xsns_sensor/xsns_06_dht_v7.ino#L47

I tried this on a custom built dht component in esphome and it works. Currently working on a PR for this.

I miss an information: Does any one know how to detect if running on ESP32 or ESP8266 (#ifdef) in CPP code?

popolite commented 1 year ago

There seems to be a timing problem in the dht component when running on an ESP32. Looking at tasmota source code, they have a slightly different timing for ESP32 when using SI7021: https://github.com/arendst/Tasmota/blob/e80d053aa0bfb12ce1d4d6a2884be6c886d3669d/tasmota/tasmota_xsns_sensor/xsns_06_dht_v7.ino#L47

I miss an information: Does any one know how to detect if running on ESP32 or ESP8266 (#ifdef) in CPP code?

in esphome/components/dht/dht.cpp

else if (this->model_ == DHT_MODEL_SI7021) {
#ifdef USE_ESP8266
    delayMicroseconds(500);
#else
    delayMicroseconds(400);
#endif
    this->pin_->digital_write(true);
    delayMicroseconds(40);
}

Instead of:

delayMicroseconds(500);

And

#ifdef USE_ESP8266
    delayMicroseconds(70);
#else
    delayMicroseconds(30);
#endif

instead of

delayMicroseconds(70);
erdembey commented 1 year ago

Thank you @popolite for your recommendation my issues are also seems to be related with this. If it's possible to generate a new bin files based on this modification i can try on my THR320 devices. May be you can create a pull request.

There seems to be a timing problem in the dht component when running on an ESP32. Looking at tasmota source code, they have a slightly different timing for ESP32 when using SI7021: https://github.com/arendst/Tasmota/blob/e80d053aa0bfb12ce1d4d6a2884be6c886d3669d/tasmota/tasmota_xsns_sensor/xsns_06_dht_v7.ino#L47

I tried this on a custom built dht component in esphome and it works. Currently working on a PR for this.

I miss an information: Does any one know how to detect if running on ESP32 or ESP8266 (#ifdef) in CPP code?

erdembey commented 1 year ago

@popolite status update, i've applied the updates you mentioned. It's started working. I will be closely watching the results. Thanks

ilyagry commented 1 year ago

I have Sonoff THR316D + THS01 (exactly as this topic is) So, I changed dht.cpp as @popolite said Yes - It works, but with some trouble Log file:

[20:32:43][W][dht:177]: Requesting data from DHT failed!
[20:32:43][W][dht:060]: Invalid readings! Please check your wiring (pull-up resistor, pin number).
[20:32:43][D][sensor:127]: 'Boiler Temperature': Sending state nan °C with 1 decimals of accuracy
[20:32:43][D][sensor:127]: 'Boiler Humidity': Sending state nan % with 0 decimals of accuracy
[20:32:52][D][sensor:127]: 'Boiler Uptime': Sending state 595.69299 s with 0 decimals of accuracy
[20:33:02][D][sensor:127]: 'Boiler WiFi Signal': Sending state -36.00000 dBm with 0 decimals of accuracy
[20:33:43][D][dht:048]: Got Temperature=26.2°C Humidity=35.7%
[20:33:43][D][sensor:127]: 'Boiler Temperature': Sending state 26.20000 °C with 1 decimals of accuracy
[20:33:43][D][sensor:127]: 'Boiler Humidity': Sending state 35.70000 % with 0 decimals of accuracy
[20:33:52][D][sensor:127]: 'Boiler Uptime': Sending state 655.69098 s with 0 decimals of accuracy

I still have some errors in log (Requesting data from DHT failed!), but the data from the sensor is finally received

Stay tuned

UPD errors statistic (update_interval: 60s - about 6% of requests completed with an error)

[20:53:43][W][dht:177]: Requesting data from DHT failed!
[21:07:43][W][dht:177]: Requesting data from DHT failed!
[21:31:43][W][dht:177]: Requesting data from DHT failed!
[21:56:43][W][dht:177]: Requesting data from DHT failed!
[22:07:43][W][dht:177]: Requesting data from DHT failed!
[22:27:43][W][dht:177]: Requesting data from DHT failed!
phazard commented 1 year ago

I tried the workaround from @popolite , but it looks like i'm not changing the correct dht.cpp. could you please provide me with the correct path. Thanks

erdembey commented 1 year ago

I tried the workaround from @popolite , but it looks like i'm not changing the correct dht.cpp. could you please provide me with the correct path. Thanks

\esphome\components\dht\dht.cpp

ilyagry commented 1 year ago

I guess the problem is in interrupts lock

Tasmota code:

// Turn off interrupts temporarily because the next sections
  // are timing critical and we don't want any interruptions.
#ifdef ESP32
  {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
  portENTER_CRITICAL(&mux);
#else
  noInterrupts();
#endif

and ESPHOME (dht.cpp)

InterruptLock lock;

Probably ESP32 requires special interrupt lock commands (but I'm not C++ guru)

Beungoud commented 1 year ago

I just changed the timing here, and it works (some read failure, but ok most of the time). You can try it by adding to your esphome configuration yaml:

external_components:
  source:
    type: git
    url: https://github.com/Beungoud/esphome
    ref: fix-esp32-dht-SI7021
  components: ["dht"]
phazard commented 1 year ago

@Beungoud ,I implemented your workaround and it looks good for me.

dwildstr commented 10 months ago
external_components:
  source:
    type: git
    url: https://github.com/Beungoud/esphome
    ref: fix-esp32-dht-SI7021
  components: ["dht"]

This fix worked great for me until I upgraded to ESPHome 8.2, after which communication with my SI7021 became extremely sporadic. It's not obvious at all to me which of the (fairly minor-seeming) changes in 8.2 could have broken it, but rolling back my build to 8.1 made my SI7021 start working again.

erdembey commented 10 months ago
external_components:
  source:
    type: git
    url: https://github.com/Beungoud/esphome
    ref: fix-esp32-dht-SI7021
  components: ["dht"]

This fix worked great for me until I upgraded to ESPHome 8.2, after which communication with my SI7021 became extremely sporadic. It's not obvious at all to me which of the (fairly minor-seeming) changes in 8.2 could have broken it, but rolling back my build to 8.1 made my SI7021 start working again.

Thank you for the heads up. I've just planned an upgrade for today. We have to find a correct implementation for this error and commit it to the official repo. Can you give us a detail about the readings ? Btw. @jesserockz can you review the fix ?

jlazkano commented 4 months ago

Hello,

I have a THR316D device, is it officially supported? Couls you provide some basic stepts to flash with esphone?

Kind regards.

erdembey commented 4 months ago

I just changed the timing here, and it works (some read failure, but ok most of the time). You can try it by adding to your esphome configuration yaml:

external_components:
  source:
    type: git
    url: https://github.com/Beungoud/esphome
    ref: fix-esp32-dht-SI7021
  components: ["dht"]

Will you please propose your fix to new release ? It seems your fix still not included in the master. Thanks

mihaimdinca commented 2 months ago

I apologize for off topic question, but is it normal for the esp on this device to have a almost steady internal temperature of 80 degrees Celsius?

JanX2 commented 2 months ago

@mihaimdinca The temperature sensor needs to calibrated.

You can use something like:

    filters:
     - multiply: 0.18

The factor will vary, of course.

mihaimdinca commented 2 months ago

I hope I was not misunderstood, I was referring to the internal esp32 temperature sensor

JanX2 commented 2 months ago

I hope I was not misunderstood, I was referring to the internal esp32 temperature sensor

https://www.danielmartingonzalez.com/en/calibrate-sensors-esphome/

mihaimdinca commented 2 months ago

I will look into it a bit more closely. Thank you very much.

erdembey commented 3 weeks ago

Can someone share a updated configuration for this setup. I can not use without fix-esp32-dht-SI7021 even though it's merged in latest version.