Shelly Plus 2PM with ESPHome Configuration Issues

Hi
As with all shelly’s in the house this one was flashed with ESPHome. I bought this new Shelly Plus 2PM to replace a Shelly 2.5 with two channels (They seem to fail after a year or two). I have configured the device according to the example on esp devices but have trouble with some things.

Whats working well:

  • Relays
  • WiFi

Whats not working:

  • Temperature reads 166 deg at cold boot and jumps up to 174 and then stays there. Documentation says its not perfectly calibrated but this very far off
  • Getting No readings at all (Unknown) from current and voltage sensors
  • The button on the device does not work. In fact it reports that it is pressed all the time. Every 30s it quickly reports off and then back to on. I tried changing the update_interval for the ADC and that affected this behaviour on the input button. (Setting it to 5s made the input flip quickly every 5s instead) Strange!

What I have not tried yet:

  • Switch Inputs

There seems to be very little info about this device with ESPHome out there and I’m wondering if maybe there is some updated hardware as the configuration seems to work so badly for me. Any ideas / Any more of you out there using this device with ESPHome?

I guess that you programmed your shelly according to this ?

Correct! Same link I posted. Any thoughts? :slight_smile:

Oh, sorry, i overlooked your link…
Well, only faulty shelly comes to my mind, since i have 5 shelly 2.5 (covers) and one shelly plus 1PM on esphome and all work perfectly…

A little update for you guys here on my problem. Not a faulty device. I got myself another shelly plus 2pm and backed up the stock firmware on it and then flashed it on the device I tried with ESPHome. The shelly now works reporting current, voltage etc. So… what conclusion should one draw from that then! :smiley:

1 Like

Can you paste the config you used for flashing ?
When looking at the config from esphomedevices site I don’t understand the calibration part

Please calibrate the NTC and the voltage / power measurements, the values below are just a rough estimate!

I didn’t calibrate any of NTC’s. “Rough estimate” is ok for me, as i need only coarse information and i think that it shows pretty ok - it showed 50-70 without any power save, with power save to light temp is some 10 degrees lower.

Here’s my complete code. i use “common” yaml’s - inside i have code, which is common for all my models (also included below). file “common_led_inverse.yaml” is only for LED indication of connetion status: lit when no connection, slow equal flashing when connected only to wifi and only short pulse every 5s when connected to HA.

buttons SW1 and SW2 work in a way: up-stop-up-stop…, or down-stop-down-stop…, while on-case button works open-stop-close-stop…

Name strings (and comments) are in Slovenian, i translated all major things to english…

esphome:
  name: dnevna-roleta-desno

esp8266:
  board: esp01_1m
  restore_from_flash: true
  
packages:
  device_settings: !include common/common.yaml 
# WiFI connected STATUS
<<: !include common/common_led_inverse.yaml
  
substitutions:
  device_name: dnevna_roleta_desno
  prijazno_ime: Dnevna soba roleta desno 
  wifi_ip_modula: 192.168.0.87
  connected_pin: GPIO0
  
globals:
  - id: pozicija
    type: int
    initial_value: '0'  
    
wifi:
  power_save_mode: light  
#***************************** DEFINICIJE ************************************************************ DEFINICIJE *******
i2c:
  sda: GPIO12
  scl: GPIO14
  
#****************************** SENZORJI ************************************************************* SENZORJI *********     
button: 
  - platform: template
    id: ${device_name}_dvig
    name: ${prijazno_ime} dvigni
    on_press: 
      then:
        - cover.open: ${device_name}
        
  - platform: template
    id: ${device_name}_spust
    name: ${prijazno_ime} spusti
    on_press: 
      then:
        - cover.close: ${device_name}  
        
  - platform: template
    id: ${device_name}_stop
    name: ${prijazno_ime} stop
    on_press: 
      then:
        - cover.stop: ${device_name}  
        
sensor:
  - platform: ade7953
    irq_pin: GPIO16
    voltage:
      name: Shelly 2.5 Mains Voltage
      internal: true
      filters:
        - throttle: 5s
    current_a:
      name: Shelly 2.5 Open Current
      id: open_current
      internal: true
    current_b:
      name: Shelly 2.5 Close Current
      id: close_current
      internal: true
    update_interval: 0.5s

  # NTC Temperature
  - platform: ntc
    sensor: temp_resistance_reading
    name: ${prijazno_ime} temperatura Shelly
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    calibration:
      b_constant: 3350
      reference_resistance: 10kOhm
      reference_temperature: 298.15K
    on_value_range:
      above: 90
      then: # Security shutdown by overheating
        - switch.turn_on: _shutdown

  - platform: resistance
    id: temp_resistance_reading
    sensor: temp_analog_reading
    configuration: DOWNSTREAM
    resistor: 32kOhm
    internal: true
  - platform: adc
    id: temp_analog_reading
    pin: A0
    update_interval: 30s
    internal: true

binary_sensor:
    # button SW1 - UP
  - platform: gpio
    pin:
      number: GPIO13
    id: dnevna_soba_roleta_desno_preklop_s1
    filters:
      - delayed_on: 10ms
      - delayed_off: 100ms
    on_press:
      then:
        # logic for cycling through movements: open->stop->close->stop->...
        - lambda: |
            if (id(dnevna_roleta_desno).current_operation == COVER_OPERATION_IDLE) {
                auto call = id(dnevna_roleta_desno).make_call();
                call.set_command_open();
                call.perform();
            }
            else {
              // Cover is opening/closing. Stop it
              auto call = id(dnevna_roleta_desno).make_call();
              call.set_command_stop();
              call.perform();                
            }
            
    # button SW2 - DOWN
  - platform: gpio
    pin:
      number: GPIO5
    id: dnevna_soba_roleta_desno_preklop_s2
    filters:
      - delayed_on: 10ms
      - delayed_off: 100ms
    on_press:
      then:
        # logic for cycling through movements: open->stop->close->stop->...
        - lambda: |
            if (id(dnevna_roleta_desno).current_operation == COVER_OPERATION_IDLE) {
                auto call = id(dnevna_roleta_desno).make_call();
                call.set_command_close();
                call.perform();
              }
             else {
              // Cover is opening/closing. Stop it.
              auto call = id(dnevna_roleta_desno).make_call();
              call.set_command_stop();
              call.perform();
            }
            
    # button on shelly case
  - platform: gpio
    pin:
      number: GPIO2
      inverted: true
    id: dnevna_soba_roleta_desno_preklop
    filters:
      - delayed_on: 10ms
      - delayed_off: 100ms    
    on_press:
      then:
        # logic for cycling through movements: open->stop->close->stop->...
        - lambda: |
            if (id(dnevna_roleta_desno).current_operation == COVER_OPERATION_IDLE) {
              if (id(pozicija) == 0) {
                auto call = id(dnevna_roleta_desno).make_call();
                id(pozicija) = 1;
                call.set_command_open();
                call.perform();
              } else {
                id(pozicija) = 0;
                auto call = id(dnevna_roleta_desno).make_call();
                call.set_command_close();
                call.perform();                
              }

              }
             else {
              // Cover is opening/closing. Stop it.
              auto call = id(dnevna_roleta_desno).make_call();
              call.set_command_stop();
              call.perform();
            }
  

switch:
  - platform: shutdown
    id: _shutdown
    name: Shelly 2.5 Shutdown

    # relay definition
  - platform: gpio
    id: ${device_name}_odpiranje
    name: ${prijazno_ime} odpiranje
    pin: GPIO15
    restore_mode: RESTORE_DEFAULT_OFF
    interlock: &interlock [dnevna_roleta_desno_odpiranje, dnevna_roleta_desno_zapiranje]
    interlock_wait_time: 200ms
    

  - platform: gpio
    id: ${device_name}_zapiranje
    name: ${prijazno_ime} zapiranje
    pin: GPIO4
    restore_mode: RESTORE_DEFAULT_OFF
    interlock: *interlock
    interlock_wait_time: 200ms

# Example configuration entry
cover:
  - platform: current_based
    name: ${prijazno_ime}
    id: ${device_name}

    open_sensor: open_current
    open_moving_current_threshold: 0.2
    open_obstacle_current_threshold: 1
    open_duration: 30s
    open_action:
      - switch.turn_on: ${device_name}_odpiranje
      
    close_sensor: close_current
    close_moving_current_threshold: 0.2 # minimum current of motor - below this module thinks motor is disconnected and stops movement
    close_obstacle_current_threshold: 1 #current where module thinks motor is jammed (broken)
    close_duration: 28s
    close_action:
      - switch.turn_on: ${device_name}_zapiranje
      
    stop_action:
      - switch.turn_off: ${device_name}_zapiranje
      - switch.turn_off: ${device_name}_odpiranje
      
    obstacle_rollback: 20%
    start_sensing_delay: 1.5s
    malfunction_detection: true
    malfunction_action:
      then:
        - logger.log: "ERROR! Relay or motor defect!"

common.yaml:

globals:
  - id: stevec
    type: int
    initial_value: "0"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  #power_save_mode: none
  manual_ip:
    static_ip: ${wifi_ip_modula}
    gateway: 192.168.0.1
    subnet: 255.255.255.0
    dns1: 192.168.0.1
    dns2: 192.168.0.1

logger:
  tx_buffer_size: 256
  logs:
    switch: info

#API povezava s HA aplikacijo
api:
  password: !secret ota_password

#OTA posodobitev FW na daljavo
ota:
  password: !secret ota_password

web_server:
  port: 80
  auth:
    username: !secret ota_username
    password: !secret ota_password

  # preverjanje povezave API --> HA in samodejni RESET modula
interval:
  - interval: 60s
    then:
      if:
        condition:
          not:
            api.connected:
        then:
          - logger.log: HA prekinjen(2)!
          - delay: 50s
          - if:
              condition:
                api.connected:
              then:
                logger.log: HA povezan(3)!
              else:
                button.press: ${device_name}_reboot

button:
  - platform: template
    name: "${prijazno_ime} WiFi rescan"
    on_press:
      lambda: |-
        if (wifi::global_wifi_component->wifi_rssi() < -50) {
          // PATCH: Reset old priorities for known networks
          for (auto &scan : wifi::global_wifi_component->get_scan_result()) {
            if (wifi::global_wifi_component->has_sta_priority(scan.get_bssid())) {
              wifi::global_wifi_component->set_sta_priority(scan.get_bssid(), 0);
            }
          }
          // Rescan
          wifi::global_wifi_component->start_scanning();
        }

  - platform: restart
    id: ${device_name}_reboot
    name: "${device_name} reboot "
sensor:
  # PAZI! NE obračaj, ker drugače ne dela monitoring!!------------------------ WiFi
  - platform: wifi_signal
    name: ${prijazno_ime} WiFi
    update_interval: 60s
    internal: false

  # interni senzor za generacijo prijaznega prikaza UPTIME časa,
  # senzor za prikaz je pri "text_sensor"
  - platform: uptime
    id: ${device_name}_uptime_internal
    update_interval: 60s
    internal: true
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: ${device_name}_uptime
            state: !lambda |-
              int seconds = round(id(${device_name}_uptime_internal).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 ? String(days) + "d " : "") +
                (hours ? String(hours) + "h " : "") +
                (minutes ? String(minutes) + "m " : "") +
                (String(seconds) + "s")
              ).c_str();
switch:
  #Switch WiFi connected LED
  - platform: gpio
    pin: ${connected_pin}
    id: ${device_name}_wifi_api_connected
    internal: true

text_sensor:
  #---------------------------------------------------------------- WIFI info
  - platform: wifi_info
    ip_address:
      name: ${prijazno_ime} IP
      internal: false
    mac_address:
      name: ${prijazno_ime} MAC
      internal: false
    bssid:
      name: ${prijazno_ime} BSSID
      internal: false

  #senzor za prikaz prijaznega UPTIME časa
  - platform: template
    name: ${prijazno_ime} Uptime
    id: ${device_name}_uptime
    icon: mdi:clock-start

finally, common/common_led_inverse.yaml. Here it depends how led is connected (positive or negative). If flashing is reversed all “on” and “off” commands must be reversed.

# in order this to work SWITCH sensor MUST be defined in common.yaml file!!
interval: # verzija wifi=on: 500ms, api=on: 5s pulz
  - interval: 1s
    then:
      if:
        condition:
          wifi.connected:
        then:
          - switch.turn_on: ${device_name}_wifi_api_connected
          - if:
              condition:
                api.connected:
              then:
                - lambda: |-
                    id(stevec) +=1;
                    if (id(stevec) > 4) {
                      id(stevec) = 0;
                      id(${device_name}_wifi_api_connected).turn_off();}
                - delay: 50ms
                - switch.turn_on: ${device_name}_wifi_api_connected
              else:
                - delay: 500ms
                - switch.turn_off: ${device_name}_wifi_api_connected
        else:
          - switch.turn_off: ${device_name}_wifi_api_connected

Are sure this for the plus 2PM. That device runs a single core esp32 and you have specified an esp8266

Thx alot for this, I am Croatian so I understand a bit of Slovenian:)
Did you use USB UART for flashing or OTA?

This is for Shelly 2.5PM, which i also mentioned in my above post…
but, even if your model is esp32 can’t be much different, just initial lines (first couple) are to be replaced with ones for esp32, all other is pretty much same, except check if gpio’s are at different numbers.

@djlujo : first i flashed via USB UART, yes. All other updates go via OTA.
shelly 2.5PM module has pins on the back for UART connection. Just DON’T connect to 230V at first flashing via UART!!! Use external 3.3V for first flashing.

@Protoncek Can you share config for Shelly Plus 1PM aswell pls?

1PM is still running “as test” for now and has configuration like THIS.

EDIT: i’m lying… i have one shelly plus 1PM (not shelly 1PM, but PLUS version) installed, code attached:

esphome:
  name: biodom
  platformio_options:
    board_build.f_cpu: 160000000L

esp32:
  board: esp32doit-devkit-v1
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_FREERTOS_UNICORE: y
      CONFIG_ESP32_DEFAULT_CPU_FREQ_160: y
      CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ: "160"

# ***************************** DEFINICIJE ************************************************************ DEFINICIJE *******
packages:
#  device_settings: !include common/common.yaml #-------------------------------- vključeno je vse
#  device_settings: !include common/common_noled.yaml #-------------------------- brez ledice
#  device_settings: !include common/common_nolog.yaml #-------------------------- brez LOGiranja
  device_settings: !include common/common_noweb.yaml #-------------------------- brez WEB strežnika
#  device_settings: !include common/common_nowifi.yaml #------------------------- brez WIFI definicij (za Ethernet)
  
# ------------------------------------------------------------------------------ utripanje LEDice: stanje povezave WiFi & HA
#  interval: !include common/common_led_true.yaml 
#  interval: !include common/common_led_true_fast.yaml
#  interval: !include common/common_led_true_fast_long.yaml
#  interval: !include common/common_led_inverse.yaml
#  interval: !include common/common_led_inverse_fast.yaml
  interval: !include common/common_led_inverse_fast_long.yaml
# ------------------------------------------------------------------------------ SUBSTITUTIONS
substitutions:
# uporaba: ${device_name}_... in ${prijazno_ime} ...
  device_name: biodom 
  prijazno_ime: biodom
  wifi_ip_modula: 192.168.0.97 #------------------------------------------------ zakomentirati pri "nowifi" verziji!!!
  connected_pin: GPIO0 #-------------------------------------------------------- zakomentirati pri "noled"  verziji!!!
  # Higher value gives lower watt readout
  current_res: "0.001"
  # Lower value gives lower voltage readout
  voltage_div: "1925"
  
# wifi:
#   use_address: 192.168.0.97
 
# ------------------------------------------------------------------------------ I2C definicija      
# i2c:
#   sda: GPIO4
#   scl: GPIO5
#   scan: True
#   id: bus_a

time:
  - platform: homeassistant

# ****************************** SENZORJI ************************************************************* SENZORJI *********   

#binary_sensor: # --------------------------------------------------------------- BINARY sensors
  # - platform: gpio
  #   name: "${prijazno_ime} stikalo SW"
  #   pin: GPIO4
  #   on_press:
  #     then:
  #       - switch.toggle: "relay"
  #   filters:
  #     - delayed_on_off: 50ms
      
  # - platform: gpio
  #   name: "${prijazno_ime} tipka"
  #   pin:
  #     number: GPIO25
  #     inverted: yes
  #     mode:
  #       input: true
  #       pullup: true
  #   on_press:
  #     then:
  #       - switch.toggle: "relay"
  #   filters:
  #     - delayed_on_off: 5ms

#button: # ---------------------------------------------------------------------- BUTTONs


#light: # ----------------------------------------------------------------------- LIGHTs


# output: # ---------------------------------------------------------------------- OUTPUTs
#   - platform: gpio
#     id: "relay_output"
#     pin: GPIO26
    
sensor: # ---------------------------------------------------------------------- SENSORs  
  - platform: ntc
    sensor: temp_resistance_reading
    name: "${prijazno_ime} temperatura modula"
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    icon: "mdi:thermometer"
    calibration:
      b_constant: 3350
      reference_resistance: 10kOhm
      reference_temperature: 298.15K
    on_value_range:
      - above: "80.0"
        then:
          - switch.turn_off: ${device_name}_shutdown
          
  - platform: resistance
    id: temp_resistance_reading
    sensor: temp_analog_reading
    configuration: DOWNSTREAM
    resistor: 6kOhm
    
  - platform: adc
    id: temp_analog_reading
    pin: GPIO32
    attenuation: 11db

  - platform: adc
    name: "${prijazno_ime} napetost releja"
    pin: GPIO33
    attenuation: 11db
    filters:
      - multiply: 8

  - platform: hlw8012
    model: BL0937
    sel_pin:
      number: GPIO23
      inverted: true
    cf_pin: GPIO5
    cf1_pin: GPIO18
    current_resistor: ${current_res}
    voltage_divider: ${voltage_div}
    current:
      name: "${prijazno_ime} tok"
      unit_of_measurement: A
      accuracy_decimals: 3
      icon: mdi:flash-outline
    voltage:
      name: "${prijazno_ime} napetost"
      unit_of_measurement: V
      accuracy_decimals: 1
      icon: mdi:flash-outline
    power:
      name: "${prijazno_ime} moč"
      unit_of_measurement: W
      id: power
      icon: mdi:flash-outline
      # on_value_range:
      #   - above: "3600"
      #     then:
      #       - switch.turn_off: "relay"
    change_mode_every: 2
    update_interval: 10s
    
  - platform: total_daily_energy
    name: "${prijazno_ime} dnevna poraba energije"
    power_id: power
    filters:
        - multiply: 0.001
    unit_of_measurement: kWh
    icon: mdi:clock-alert

switch: # ---------------------------------------------------------------------- SWITCHes
#   - platform: output
#     id: "relay"
#     name: "${device_name} Relay"
#     output: "relay_output"
#     restore_mode: ALWAYS_ON

  - platform: shutdown
    id: ${device_name}_shutdown
    name: ${prijazno_ime} Shutdown
#text_sensor: # ------------------------------------------------------------------------------ TEXT sensors 


@Protoncek Aha gotcha thx I ordered mine now I am waiting so I can start hacking:)

anyone got wifi channel working on the shelly 2pm plus? I seem to be getting compilation errors:

/config/esphome/shelly-plus-2pm.yaml:191:14: error: 'WiFi' was not declared in this scope
lambda: return WiFi.channel();
^~~~
*** [/[data/shelly-plus-2pm/.pioenvs/shelly-plus-2pm/src/main.o](http://data/shelly-plus-2pm/.pioenvs/shelly-plus-2pm/src/main.o)] Error 1

I’m suspecting this potentially has to do with the board type (esp32doit-devkit-v1) somehow?

Hi,

I spend countless hours/days to figure out how to use ESPHome on Shelly single core ESP32 devices (yes there is a solution using ESP-IDF as mentioned above but without the Arduino framework).
Here is the solution for those who are strugling to have ESPhome running using the Arduino framework on single core ESP32 using the Transmota plafromio fork for Arduino:

#####

esphome:
   name: ${device_name}
   friendly_name: ${friendly_name}
   platformio_options:
      board_build.f_cpu: 160000000L
      platform: https://github.com/tasmota/platform-espressif32/releases/download/2023.02.00/platform-espressif32.zip
      framework: arduino
      platform_packages:
         - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
      build_flags:
         - "-DCONFIG_FREERTOS_UNICORE=1"
         - "-DFRAMEWORK_ARDUINO_SOLO1"
      board: esp32-solo1


esp32:
  board: esp32doit-devkit-v1

####

Hope it helps other people not lose hours and go into the plarformio/Arduino rabbit hole.

Felix

1 Like

don’t know if this is the reason. But after using this at the top of my yaml. my issue described here appears to be fixed.

Do you think that could be what solved it? I’m slightly hesitant to put the shelly device back in the socket, since it’s quite a hassle.

Hi Phisson, how did you backup stok firmware form shelly plus 2pm? I need to revert one of mine to 0.14.1

I did, here is a link (valid to the end of the month). Backed up using esptool.

Hi Phisson!
Do you mind sharing the info how to backup the Shelly Plus 2PM stock firmware again?
I just bought one and like to have a backup before start playing with Esphome on it.

It was no info but rather the firmware. To backup yourself just read on how to do so with esptool. Is the same tool you would need to restore.