Help config sonoff POWR320D that works on tasmota but not in ESPhome

Hello,

I’ve recently purchased a Sonoff POWR320D and flashed the esphome firmware with the template hosted on this site https://www.esphome-devices.com/devices/Sonoff-POW-Elite-20a

# Basic Config
substitutions:
  friendly_name: POW Elite 20A
  device_name: pow-elite-20a

esphome:
  name: $device_name

esp32:
  board: nodemcu-32s

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: $device_name
    password: !secret wifi_failover

captive_portal:

logger:
  level: INFO
  baud_rate: 0

api:
  encryption:
    key: !secret api_enc

ota:
  password: !secret ota_pwd

esp32_ble_tracker:
  scan_parameters:
    interval: 1100ms
    window: 1100ms
    active: true

bluetooth_proxy:
  active: true

uart:
  rx_pin: GPIO16
  baud_rate: 4800

time:
  - platform: homeassistant
    id: homeassistant_time

sensor:
  - platform: cse7766
    update_interval: 2s
    current:
      name: $friendly_name Current
      id: a_sensor
    voltage:
      name: $friendly_name Voltage
      id: v_sensor
    power:
      name: $friendly_name Power
      id: w_sensor
      on_value_range:
        - above: 4.0
          then:
            - light.turn_on: switch_led
        - below: 3.0
          then:
            - light.turn_off: switch_led
    energy:
      name: $friendly_name Energy
      id: wh_sensor

  - platform: total_daily_energy
    name: $friendly_name Total Daily Energy
    power_id: w_sensor

  - platform: wifi_signal
    name: $friendly_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();

  - platform: template
    name: $friendly_name ESP32 Internal Temp
    device_class: temperature
    unit_of_measurement: °C
    id: esp32_temp
    lambda: return temperatureRead();

  - platform: template
    name: $friendly_name Power Factor
    device_class: power_factor
    id: power_factor
    lambda: return id(w_sensor).state / id(v_sensor).state / id(a_sensor).state;

  - platform: esp32_hall
    name: $friendly_name ESP32 Hall Sensor
    update_interval: 60s

binary_sensor:
  - platform: gpio
    pin: GPIO00
    id: reset
    internal: true
    filters:
      - invert:
      - delayed_off: 10ms
    on_click:
      - max_length: 350ms # short press to toggle the relay
        then:
          switch.toggle: relay_1
      - min_length: 360ms # long press to cycle display info
        max_length: 3s
        then:
          - if:
              condition:
                binary_sensor.is_on: page
              then:
                binary_sensor.template.publish:
                  id: page
                  state: OFF
              else:
                binary_sensor.template.publish:
                  id: page
                  state: ON
  - platform: template # this is a fake sensor to tell the screen which info to show on display
    id: page
    publish_initial_state: true
    internal: true

display:
  platform: tm1621
  id: tm1621_display
  cs_pin: GPIO25
  data_pin: GPIO14
  read_pin: GPIO26
  write_pin: GPIO27
  lambda: |-
    if (id(page).state) {
      it.display_voltage(true);
      it.display_kwh(false);
      it.printf(0, "%.1f", id(v_sensor).state);
      it.printf(1, "%.1f", id(a_sensor).state);
    } else {  
      it.display_voltage(false);
      it.display_kwh(true);
      it.printf(0, "%.1f", id(wh_sensor).state);
      it.printf(1, "%.1f", id(w_sensor).state);
    }

output:
  - platform: ledc
    id: led
    pin:
      number: GPIO18
      inverted: True

switch:
  - platform: template
    name: $friendly_name
    optimistic: true
    id: relay_1
    lambda: |-
      if (isnan(id(w_sensor).state)) {
        return {};
      } else if (id(w_sensor).state > 4) {
        // Running
        return true;
      } else {
        // Not running
        return false;
      }
    turn_off_action:
      - switch.turn_on: relay_off
    turn_on_action:
      - switch.turn_on: relay_on
  - platform: gpio
    restore_mode: ALWAYS_OFF
    internal: true
    id: relay_off
    pin: GPIO04
    on_turn_on:
      - delay: 500ms
      - switch.turn_off: relay_off  //bi-stable relay so no need to keep on.
      - light.turn_off: switch_led
    interlock: [relay_on]
  - platform: gpio
    restore_mode: ALWAYS_OFF
    internal: true
    id: relay_on
    pin: GPIO02
    on_turn_on:
      - delay: 500ms
      - switch.turn_off: relay_on  //bi-stable relay so no need to keep on.
      - light.turn_on: switch_led
    interlock: [relay_off]
  - platform: restart
    name: $friendly_name Restart

text_sensor:
  - platform: template
    name: $friendly_name Uptime
    id: uptime_human
    icon: mdi:clock-start
  - platform: wifi_info
    ip_address:
      name: $friendly_name IP
    ssid:
      name: $friendly_name SSID
    bssid:
      name: $friendly_name BSSID

light:
  - platform: monochromatic
    id: switch_led
    output: led
    internal: True
  - platform: status_led
    id: wifi_status_led
    internal: True
    pin:
      number: GPIO05
      inverted: True

interval:
  - interval: 30s
    then:
      if:
        condition:
          wifi.connected:
        then:
          - light.turn_on: wifi_status_led
        else:
          - light.turn_off: wifi_status_led

All seems to work without problem but the relay doesn’t. POWR320D (POWR316D only have 1 pin relay) have the relay shared between GPIO02 On and GPIO04 Off as you can see on the pinout:

Pin Function
GPIO00 Push Button (HIGH = off, LOW = on)
GPIO02 Relay1 (320D - bi-stable - On)
GPIO04 Relay1 (320D - bi-stable - Off)
GPIO05 Wifi_LED
GPIO14 TM1621 DA
GPIO16 CSE7766 Rx
GPIO18 Status LED (HIGH = off, LOW = on)
GPIO25 TM1621 CS
GPIO26 TM1621 RD
GPIO27 TM1621 WR

With tasmota I’ve no problem, but I prefer ESPhome because the integration with HA and versatibility

Tasmota Config for POWR320D

Can someone help with the config? I have very low knowledge on programing ESPhome

Thanks

Hey @GenGT, did you end up figuring this out?
I’m thinking about using ESPHome for my POWR320D as well, but obviously need the relay to work.

Hi Simon,

Yes, I’ve finally found the problem. It’s on the code “lambda” without this code all is working correctly.
Look at this post:

Regards

1 Like

Hi, You can share the final config, I have same issue.

api: [source config.yaml:35]
encryption:

Invalid key format, please check it's using base64.
key: !secret api_enc

sensor.cse7766: [source config.yaml:59]
platform: cse7766

[update_interval] is an invalid option for [sensor.cse7766]. Please check the indentation.
update_interval: 2s
current:
name: POW Elite 20A Current
id: a_sensor
voltage:
name: POW Elite 20A Voltage
id: v_sensor
power:
name: POW Elite 20A Power
id: w_sensor

[on_value_range] is an invalid option for [sensor.cse7766]. Please check the indentation.
on_value_range:
- above: 4.0
then:
- light.turn_on: switch_led
- below: 3.0
then:
- light.turn_off: switch_led
energy:
name: POW Elite 20A Energy
id: wh_sensor

Thanks