Sonoff TX-ultimate with ESPHome firmware stucks and vibrating randomly

Hi there!

I installed ESPHome firmware in my sonoff tx-ultimate switch and tonight I faced a bug when vibro started working instantly and switch couldn’t work properly (nothing happend when I touched it).

Sound of vibro was like when I first time flashed this firmware into module.

What could it be? I thought that it couldn’t connect to HomeAssistant (I powered off it for the night) and it sarted to rollback the firmware to last version? I don’t know if it can do such operation, could it?

If it happens one more time, I will try to record a video. Anyway, I need know what it could be and how to fix it, because waking up every night doesen’t sound good))

Waiting for somebodies answer!

PS: for this sonoff device I use custom component (GitHub - SmartHome-yourself/sonoff-tx-ultimate-for-esphome: ESPHome Custom Component for Sonoff TX Ultimate) but it seems, the problem is in ESPHome firmware in common.

PPS:
This is how it looks like: Быстрый обмен файлами

Here is my yaml file:

substitutions:
  nname: LivingRoom_Switch
  friendly_name: LivingRoom Switch

  relay_count: "1"

  toggle_relay_1_on_touch: "true"

  vibra_time: 45ms
  button_on_time: 100ms

  button_brightness: "0.7"
  button_color: "{0,0,100}"

  nightlight: "on"
  nightlight_brightness: "0.9"
  nightlight_color: "{100,65,7}"

  latitude: "50.123456°"
  longitude: "5.654321°"

  touch_brightness: "1"
  touch_color: "{0,100,100}"
  touch_effect: ""

  long_press_brightness: "1"
  long_press_color: "{100,0,0}"
  long_press_effect: ""

  multi_touch_brightness: "1"
  multi_touch_color: "{0,0,0}"
  multi_touch_effect: ""

  swipe_left_brightness: "1"
  swipe_left_color: "{0,100,0}"
  swipe_left_effect: ""

  swipe_right_brightness: "1"
  swipe_right_color: "{100,0,70}"
  swipe_right_effect: ""

  relay_1_pin: GPIO18

  vibra_motor_pin: GPIO21
  pa_power_pin: GPIO26

  led_pin: GPIO13
  status_led_pin: GPIO33

  uart_tx_pin: GPIO19
  uart_rx_pin: GPIO22

  audio_lrclk_pin: GPIO4
  audio_bclk_pin: GPIO2
  audio_sdata_pin: GPIO15

  touchpanel_power_pin: GPIO5

web_server:
  port: 80

esphome:
  name: ultimate-switch
  friendly_name: ultimate-switch

  project:
    name: smarthomeyourself.tx_ultimate
    version: "1.0"

  on_boot:
    priority: -100
    then:
      - binary_sensor.template.publish:
          id: touchfield_1
          state: OFF
      - binary_sensor.template.publish:
          id: multi_touch
          state: OFF
      - binary_sensor.template.publish:
          id: swipe_left
          state: OFF
      - binary_sensor.template.publish:
          id: swipe_right
          state: OFF
      - binary_sensor.template.publish:
          id: long_press
          state: OFF
      - script.execute: refresh_led_default
      - script.execute: refresh_nightlight

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  level: DEBUG
  logs:
    binary_sensor: INFO
    light: INFO
    script: INFO
    switch: INFO
    tx_ultimate_touch: INFO
    uart_debug: INFO

# Enable Home Assistant API
api:
  reboot_timeout: 0s
  encryption:
    key: "baQ2xdKUNa************+0Fn93OkzgfUPd7wBBukC9KfY="

ota:
  password: "********c599d2169ac84ad8d415*****"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Ultimate-Switch Fallback Hotspot"
    password: "11111111"
    
improv_serial:

captive_portal:

external_components:
#  - source: /config/esphome/my_components
  - source:
      type: git
      url: https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome
      ref: main
    components: [tx_ultimate_touch]



globals:
  - id: nightlight_color
    type: int [3]
    restore_value: no
    initial_value: ${nightlight_color}
  - id: button_color
    type: int [3]
    restore_value: no
    initial_value: ${button_color}
  - id: long_press_color
    type: int [3]
    restore_value: no
    initial_value: ${long_press_color}
  - id: multi_touch_color
    type: int [3]
    restore_value: no
    initial_value: ${multi_touch_color}
  - id: swipe_left_color
    type: int [3]
    restore_value: no
    initial_value: ${swipe_left_color}
  - id: swipe_right_color
    type: int [3]
    restore_value: no
    initial_value: ${swipe_right_color}
  - id: touch_color
    type: int [3]
    restore_value: no
    initial_value: ${touch_color}    



binary_sensor:
  - platform: template
    name: "Touchfield 1"
    id: touchfield_1
    on_press:
      - if:
          condition:
            lambda: "return ${toggle_relay_1_on_touch};"
          then:
            - switch.toggle: relay_1
      - delay: ${button_on_time}
      - binary_sensor.template.publish:
          id: touchfield_1
          state: OFF
      - script.execute: refresh_led_default

  - platform: template
    name: "Swipe left"
    id: swipe_left
    on_press:
      - if:
          condition:
            lambda: "return ${toggle_relay_1_on_touch};"
          then:
            - switch.toggle: relay_1
      - delay: ${button_on_time}
      - binary_sensor.template.publish:
          id: swipe_left
          state: OFF
      - script.execute: refresh_led_default

  - platform: template
    name: "Swipe_right"
    id: swipe_right
    on_press:
      - if:
          condition:
            lambda: "return ${toggle_relay_1_on_touch};"
          then:
            - switch.toggle: relay_1
      - delay: ${button_on_time}
      - binary_sensor.template.publish:
          id: swipe_right
          state: OFF
      - script.execute: refresh_led_default

  - platform: template
    name: "Multi Touch"
    id: multi_touch
    on_press:
      - if:
          condition:
            lambda: "return ${toggle_relay_1_on_touch};"
          then:
            - switch.toggle: relay_1
      - delay: ${button_on_time}
      - binary_sensor.template.publish:
          id: multi_touch
          state: OFF
      - script.execute: refresh_led_default

  - platform: template
    name: "Long Press"
    id: long_press
    on_press:
      - if:
          condition:
            lambda: "return ${toggle_relay_1_on_touch};"
          then:
            - switch.toggle: relay_1
      - delay: ${button_on_time}
      - binary_sensor.template.publish:
          id: long_press
          state: OFF
      - script.execute: refresh_led_default

switch:
  - platform: gpio
    id: relay_1
    name: "${friendly_name} L1"
    pin: ${relay_1_pin}
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: gpio
    id: vibra
    pin: ${vibra_motor_pin}
    name: "${friendly_name} Vibration"
    restore_mode: ALWAYS_OFF
    on_turn_on:
      - delay: ${vibra_time}
      - switch.turn_off: vibra

  - platform: gpio
    id: pa_power
    pin: ${pa_power_pin}
    name: "PA Power"
    internal: true
    restore_mode: ALWAYS_ON

  - platform: gpio
    name: "touch panel power"
    pin:
      number: ${touchpanel_power_pin}
      inverted: true
    id: touch_power
    internal: true
    restore_mode: RESTORE_DEFAULT_ON

  - platform: template
    name: "Nightlight"
    id: nightlight_active
    internal: true
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: template
    name: "Nightlight"
    id: nightlight
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: restart
    name: "${friendly_name} Restart"

light:
  - platform: neopixelbus
    type: GRB
    variant: WS2811
    pin: ${led_pin}
    num_leds: 28
    name: "NeoPixel Light"
    id: leds
    default_transition_length: 0s
    effects:
      - addressable_rainbow:
          name: "Rainbow"
          speed: 30
          width: 8
      - pulse:
          name: "Pulse"
          transition_length: 1.4s
          update_interval: 1s

    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: partition
    name: "LEDs Button left"
    id: leds_button_left
    internal: true
    segments:
      - id: leds
        from: 11
        to: 11

  - platform: partition
    name: "LEDs Nightlight"
    id: leds_nightlight
    internal: true
    segments:
      - id: leds
        from: 0
        to: 6
      - id: leds
        from: 8
        to: 8
      - id: leds
        from: 10
        to: 10
      - id: leds
        from: 12
        to: 19
      - id: leds
        from: 27
        to: 27
      - id: leds_top
        from: 0
        to: 6

  - platform: partition
    name: "LEDs Top"
    id: leds_top
    internal: true
    segments:
      - id: leds
        from: 20
        to: 26
    effects:
      - addressable_scan:
          name: "Scan"
      - addressable_rainbow:
          name: "Rainbow"
          speed: 10
          width: 20

media_player:
  - platform: i2s_audio
    id: media_out
    name: ${friendly_name} Player
    dac_type: external
    i2s_dout_pin: ${audio_sdata_pin}
    i2s_audio_id: audio_i2s
    i2s_comm_fmt: lsb    
    mode: mono

i2s_audio:
  id: audio_i2s
  i2s_lrclk_pin: ${audio_lrclk_pin}
  i2s_bclk_pin: ${audio_bclk_pin}

uart:
  tx_pin: ${uart_tx_pin}
  rx_pin: ${uart_rx_pin}
  id: my_uart
  baud_rate: 115200
  data_bits: 8
  stop_bits: 1
  parity: NONE
  debug:
    direction: RX
    dummy_receiver: false
    after:
      timeout: 2s
      bytes: 2048
    sequence:
      - lambda: UARTDebug::log_hex(direction, bytes, ' ');

tx_ultimate_touch:
  id: tx_touch
  uart: my_uart

  on_press:
    - switch.turn_on: vibra
    - script.execute:
        id: handle_release
        pos: !lambda "return touch.x;"
    - script.execute: led_on_touch
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_press", "Touch Position: %d / State: %d", touch.x, touch.state);

  on_release:
    #- script.execute:
    #    id: handle_release
    #    pos: !lambda "return touch.x;"

    #- switch.turn_on: vibra

    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_release", "Release Position: %d / State: %d", touch.x, touch.state);

  on_swipe_left:
    #- script.execute: led_on_swipe_left
    #- switch.turn_on: vibra

    #- binary_sensor.template.publish:
    #    id: swipe_left
    #    state: ON

    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_swipe_left", "Swipe Left Position: %d / State: %d", touch.x, touch.state);

  on_swipe_right:
    #- script.execute: led_on_swipe_right

    #- switch.turn_on: vibra

    #- binary_sensor.template.publish:
    #    id: swipe_right
    #    state: ON

    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_swipe_right", "Swipe Right Position: %d / State: %d", touch.x, touch.state);

  on_full_touch_release:
    #- script.execute: led_on_full_touch

    #- switch.turn_on: vibra

    #- binary_sensor.template.publish:
    #    id: multi_touch
    #    state: ON

    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_full_touch_release", "Full Touch Release Position: %d / State: %d", touch.x, touch.state);

  on_long_touch_release:
    - script.execute: led_on_long_touch
    - switch.turn_on: vibra

    - binary_sensor.template.publish:
        id: long_press
        state: ON

    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_long_touch_release", "Long Touch Release Position: %d / State: %d", touch.x, touch.state);

time:
  - platform: homeassistant
  - platform: sntp
    on_time:
      # Every 1 minutes
      - seconds: 0
        minutes: /30
        then:
          - script.execute: refresh_nightlight

sun:
  latitude: ${latitude}
  longitude: ${longitude}


script:
  - id: refresh_nightlight
    mode: restart
    then:
      - if:
          condition:
            lambda: 'return "${nightlight}" == "on";'
          then:
            - switch.turn_on:
                id: nightlight
          else:
            - switch.turn_off:
                id: nightlight

  - id: refresh_led_default
    mode: restart
    then:
      - light.turn_off: leds_top

      - if:
          condition:
            lambda: "return id(nightlight).state || id(nightlight_active).state;"
          then:
            - script.execute: led_on_nightlight
          else:
            - light.turn_off: leds_nightlight

  - id: led_on_button_left
    mode: restart
    then:
      - light.turn_on:
          id: leds_button_left
          brightness: ${button_brightness}
          red: !lambda "return id(button_color)[0]/100.0;"
          green: !lambda "return id(button_color)[1]/100.0;"
          blue:  !lambda "return id(button_color)[2]/100.0;"

  - id: led_off_button_left
    mode: restart
    then:
      - if:
          condition:
            lambda: "return id(nightlight).state || id(nightlight_active).state;"
          then:
            - light.turn_on:
                id: leds_button_left
                brightness: ${nightlight_brightness}
                red: !lambda "return id(nightlight_color)[0]/100.0;"
                green: !lambda "return id(nightlight_color)[1]/100.0;"
                blue:  !lambda "return id(nightlight_color)[2]/100.0;"
          else:
            - light.turn_off:
                id: leds_button_left

  - id: led_on_nightlight
    mode: restart
    then:
      - light.turn_on:
          id: leds_nightlight
          brightness: ${nightlight_brightness}
          red: !lambda "return id(nightlight_color)[0]/100.0;"
          green: !lambda "return id(nightlight_color)[1]/100.0;"
          blue:  !lambda "return id(nightlight_color)[2]/100.0;"

  - id: led_on_release
    mode: restart
    then:
      - light.turn_off:
          id: leds_top

  - id: led_on_touch
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${touch_brightness}
          red: !lambda "return id(touch_color)[0]/100.0;"
          green: !lambda "return id(touch_color)[1]/100.0;"
          blue:  !lambda "return id(touch_color)[2]/100.0;"
          effect: ${touch_effect}
      - delay: 6s
      - script.execute: refresh_led_default

  - id: led_on_swipe_left
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${swipe_left_brightness}
          red: !lambda "return id(swipe_left_color)[0]/100.0;"
          green: !lambda "return id(swipe_left_color)[1]/100.0;"
          blue:  !lambda "return id(swipe_left_color)[2]/100.0;"
          effect: ${swipe_left_effect}

  - id: led_on_swipe_right
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${swipe_right_brightness}
          red: !lambda "return id(swipe_right_color)[0]/100.0;"
          green: !lambda "return id(swipe_right_color)[1]/100.0;"
          blue:  !lambda "return id(swipe_right_color)[2]/100.0;"
          effect: ${swipe_right_effect}

  - id: led_on_full_touch
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${multi_touch_brightness}
          red: !lambda "return id(multi_touch_color)[0]/100.0;"
          green: !lambda "return id(multi_touch_color)[1]/100.0;"
          blue:  !lambda "return id(multi_touch_color)[2]/100.0;"
          effect: ${multi_touch_effect}


  - id: led_on_long_touch
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${long_press_brightness}
          red: !lambda "return id(long_press_color)[0]/100.0;"
          green: !lambda "return id(long_press_color)[1]/100.0;"
          blue:  !lambda "return id(long_press_color)[2]/100.0;"
          effect: ${long_press_effect}


  - id: handle_release
    mode: restart
    parameters:
      pos: int
    then:
      - if:
          condition:
            lambda: "return ${relay_count}==1;"
          then:
            - binary_sensor.template.publish:
                id: touchfield_1
                state: ON

  - id: touch_led_marker
    mode: restart
    parameters:
      state: int
      pos: int
    then:
      - if:
          condition:
            lambda: "return state==1;"
          then:
            # RELEASE
            - light.turn_off: leds

          else:
            - if:
                condition:
                  lambda: "return state==2;"
                then:
                  # TOUCH
                  - light.turn_on:
                      id: leds
                      red: 1
                      green: 0
                      blue: 0
                  - delay: 6s
                  - light.turn_off: leds

                else:
                  - if:
                      condition:
                        lambda: "return state==11;"
                      then:
                        # FULL-TOUCH RELEASE
                        - light.turn_on:
                            id: leds
                            effect: "Rainbow"
                        - delay: 1s
                        - light.turn_off: leds

                      else:
                        # SWIPE
                        - if:
                            condition:
                              lambda: "return state==13;"
                            then:
                              # SWIPE LEFT
                              - light.turn_on:
                                  id: leds
                                  red: 0
                                  green: 1
                                  blue: 0

                        - if:
                            condition:
                              lambda: "return state==12;"
                            then:
                              # SWIPE RIGHT
                              - light.turn_on:
                                  id: leds
                                  red: 0
                                  green: 0
                                  blue: 1
                        - delay: 1s
                        - light.turn_off: leds

You still having issues? Do you have the square or rectangle version?

It’s funny, but these problems were caused by current-conductive soldering acid, it seems.

When I soldered a pin (3.3v, rxd, txd, gnd) on the board, I didn’t washed the remains of soldering acid and sometimes current passed between random contacts that caused activating vibro, random restarts, hanging and other problems I couldn’t understand and classify.

Now I washed the board with alcohol and problems go away.