diff --git a/src/docs/devices/Sonoff-THR320/index.md b/src/docs/devices/Sonoff-THR320/index.md new file mode 100644 index 000000000..edec9b5b5 --- /dev/null +++ b/src/docs/devices/Sonoff-THR320/index.md @@ -0,0 +1,152 @@ +--- +title: Sonoff THR320 +date-published: 2026-02-19 +type: relay +standard: global +board: esp32 +difficulty: 3 +--- + +## Bootloop Workaround + +Some people experience a boot loop when trying to flash esphome directly. +Here's a workaround: +[https://community.home-assistant.io/t/bootloop-workaround-for-flashing-sonoff-th-elite-thr316d-thr320d-and-maybe-others-with-esphome-for-the-first-time/498868](https://community.home-assistant.io/t/bootloop-workaround-for-flashing-sonoff-th-elite-thr316d-thr320d-and-maybe-others-with-esphome-for-the-first-time/498868) + +## GPIO Pinout + +(Source: [https://templates.blakadder.com/sonoff_THR320D.html](https://templates.blakadder.com/sonoff_THR320D.html)) +Some GPIO are active-low, meaning they're "on" when they're pulled low. In ESPHome that's often called "inverted". +The relays GPIO are active-high. + +The main relay is bistable/latching, meaning a pulse on pin 1 switches the +relay ON, and a pulse on pin 2 switches the relay OFF. +These two pins should never be active at the same time, or the device will become dangerously hot in a few minutes. + +Note that until Feb 2026 there was an error in this page causing a safety issue: +The code was considering the relays GPIO as being active-low, when they are actually active-high. So the two main relay +pins were stay simultaneously active most of the time, making the device dangerously hot. +If you copied the old version of the code from here, please update your devices as soon as possible. + +| Pin | Function | +| ------ | -------------------------------------------------------- | +| GPIO0 | Push Button (HIGH = off, LOW = on) | +| GPIO19 | Large/Main Relay pin 1, pull high briefly for relay OFF | +| GPIO22 | Large/Main Relay pin 2, pull high briefly for relay ON | +| GPIO16 | Left LED (Red) | +| GPIO15 | Middle LED (Blue) | +| GPIO13 | Right LED (Green) | + +## Basic Configuration + +Internal momentary switches are used to pulse the ON/OFF pins on the main relay. +A template switch is used to hide the complexity of controlling the two internal +momentary switches. + +One shortcoming here is we don't have any way to confirm the true state of the +main relay, and so there is a possibility that our main relay switch could get out +of sync with the true state of the relay. It is advised to force the relay to a +known state on power up, rather than leave it in an unknown state until some +switching operation is performed. + +```yaml + +esp32: + board: nodemcu-32s + framework: + type: esp-idf + +binary_sensor: + # single button that also puts device into flash mode when held on boot + - platform: gpio + pin: + number: GPIO0 + mode: INPUT_PULLUP + inverted: True + ignore_strapping_warning: true + id: button_ + filters: + - delayed_on_off: 50ms + +switch: + - platform: hbridge + id: main_relay + on_pin: + number: GPIO22 + off_pin: + number: GPIO19 + pulse_length: 100ms + wait_time: 100ms + +output: + - platform: ledc + id: red_led_output + pin: + number: GPIO16 + inverted: true + + - platform: ledc + id: green_led_output + pin: + number: GPIO13 + inverted: true + + # This is needed to power the external sensor. + # It receives 3v3 from this pin, which should be activated appropriately. + - platform: gpio + pin: GPIO27 + id: sensor_power + +# The middle (blue) LED is used as wifi status indicator. +status_led: + pin: + number: GPIO15 + inverted: true + ignore_strapping_warning: true + +light: + # Leftmost (red) LED that's used to indicate the relay being on/off + - platform: binary + id: red_led + output: red_led_output + + # Rightmost (green) LED + - platform: binary + id: green_led + output: green_led_output + +``` + +The THR320 can be used with either a 1-wire bus, or else using a +uart-based sensor like the WTS01. + +1-wire: + +```yaml + +one_wire: + platform: gpio + pin: GPIO25 + +``` + +Then you can add `sensor: platform: dallas_temp` entities as appropriate, or whatever other 1-wire devices you choose. + +WTS01: + +```yaml + +# You need to have a UART bus setup in your configuration +uart: + - id: sensor_uart + rx_pin: GPIO25 + baud_rate: 9600 + +# Then you can add the WTS01 sensor +sensor: + - platform: wts01 + id: wts01_sensor + uart_id: sensor_uart + +``` + diff --git a/src/docs/devices/Sonoff-THR320D/index.md b/src/docs/devices/Sonoff-THR320D/index.md index 5df779d9e..3d25c5da8 100644 --- a/src/docs/devices/Sonoff-THR320D/index.md +++ b/src/docs/devices/Sonoff-THR320D/index.md @@ -234,244 +234,3 @@ text_sensor: name: "${friendly_name} IP Address" disabled_by_default: true ``` - -Here is an alternative configuration, set up to control a geyser, with an -ATTiny85 acting as a DS18B20 1-wire probe, using OneWireHub. The intent is -to use excess solar power to heat the geyser in Boost mode, revert to Eco -overnight, and default to Home in case there is no external controller. - -```yaml -substitutions: - name: "geyser" - friendly_name: "Geyser Thermostat" - project_name: "thermostats" - project_version: "1.0" - -packages: - # contains basic setup, WiFi, etc - common: !include .common.yaml - -esphome: - name: "${name}" - friendly_name: "${friendly_name}" - on_boot: - - priority: 90 - then: - # supply the external sensor with 3v power by pulling this GPIO high - - output.turn_on: sensor_power - # make sure the relay is in a known state at startup - - switch.turn_off: main_relay - # Default to running the geyser in Home mode - - climate.control: - id: geyser_climate - preset: "Home" - -esp32: - variant: esp32 - -logger: - # It's in the ceiling, nobody is listening to the UART - baud_rate: 0 - level: DEBUG - -web_server: - port: 80 - -captive_portal: - -binary_sensor: - # single main button that also puts device into flash mode when held on boot - # For someone in the ceiling, this can be used to turn the climate control - # into OFF or HEAT modes. It does NOT directly control the relay. - - platform: gpio - pin: - number: GPIO0 - mode: INPUT_PULLUP - inverted: True - id: button0 - filters: - - delayed_on_off: 50ms - on_press: - then: - - if: - condition: - lambda: |- - return id(geyser_climate).mode != CLIMATE_MODE_OFF; - then: - - logger.log: "Button deactivates climate control" - - climate.control: - id: geyser_climate - mode: "OFF" - else: - - logger.log: "Button activates climate control" - - climate.control: - id: geyser_climate - mode: "HEAT" - -switch: - # template switch to represent the main relay - # this is synchronised with the RED LED - # Note: this is controlled by the climate entity, and is not exposed - # for direct manipulation, otherwise it could be left on permanently - - platform: template - id: main_relay - turn_on_action: - - button.press: main_relay_on - - light.turn_on: onoff_led - turn_off_action: - - button.press: main_relay_off - - light.turn_off: onoff_led - assumed_state: True - optimistic: True - restore_state: True - -output: - # Ideally, these two relay GPIOs should be interlocked to prevent - # simultaneous operation. ESPHome currently does not support - # interlocks at an output: level, or even at a button: level - # BE CAREFUL! - - platform: gpio - id: main_relay_on_output - pin: - number: GPIO19 - - - platform: gpio - id: main_relay_off_output - pin: - number: GPIO22 - - - platform: ledc - id: red_led_output - pin: - number: GPIO16 - inverted: true - - - platform: ledc - id: green_led_output - pin: - number: GPIO13 - inverted: true - - # This is needed to power the external sensor. - # It receives 3v3 from this pin, which is pulled up on boot. - - platform: gpio - pin: GPIO27 - id: sensor_power - -button: - # See note above about interlocks! - - platform: output - id: main_relay_on - output: main_relay_on_output - duration: 100ms - - - platform: output - id: main_relay_off - output: main_relay_off_output - duration: 100ms - -# The middle (blue) LED is used as wifi status indicator. -status_led: - pin: - number: GPIO15 - inverted: true - -light: - # Leftmost (red) LED that's used to indicate the relay being on/off - - platform: binary - id: onoff_led - output: red_led_output - internal: true - - # Rightmost (green) LED used to indicate climate control being active - - platform: binary - id: auto_led - output: green_led_output - internal: true - -sensor: - # Geyser temperature - # Has some failsafes to disable climate control if the temperature - # being reported is unreasonable. Below 10C suggests that the ATTiny85 - # is either not connected to the thermistor, or is otherwise reporting - # incorrect values, and should be investigated. - # - # NOTE: This can be overridden, but care should be taken when doing so - # because these only apply when the temperature ENTERS these ranges - # If it REMAINS in the range, and climate is turned on manually, these - # failsafes will not apply! - - platform: dallas_temp - address: 0x1e11223344550028 - id: temp - name: "Temperature" - on_value_range: - - below: 10.0 - then: - - logger.log: "Temperature too low, disabling climate!" - - climate.control: - id: geyser_climate - mode: "OFF" - - above: 70.0 - then: - - logger.log: "Temperature too high, disabling climate!" - - climate.control: - id: geyser_climate - mode: "OFF" - - # The THR320 appears to run quite hot, let's just keep an eye on it - - platform: internal_temperature - name: "Internal Temperature" - -climate: - - platform: thermostat - id: geyser_climate - name: "Climate" - sensor: temp - visual: - min_temperature: 45C - max_temperature: 70C - temperature_step: - target_temperature: 1 - current_temperature: 1 - default_preset: Home - preset: - - name: Home - default_target_temperature_low: 55C - mode: heat - - name: Boost - default_target_temperature_low: 65C - mode: heat - - name: Eco - default_target_temperature_low: 45C - mode: heat - min_heating_off_time: 0s - min_heating_run_time: 60s - min_idle_time: 30s - heat_action: - - switch.turn_on: main_relay - idle_action: - - switch.turn_off: main_relay - heat_deadband: 2 # how many degrees can we go under the temp before starting to heat - heat_overrun: 0.5 # how many degrees can we go over the temp before stopping - off_mode: - - switch.turn_off: main_relay - on_state: - - if: - condition: - lambda: |- - return id(geyser_climate).mode == CLIMATE_MODE_OFF; - then: - - logger.log: "Climate control OFF" - - light.turn_off: auto_led - - if: - condition: - lambda: |- - return id(geyser_climate).mode == CLIMATE_MODE_HEAT; - then: - - logger.log: "Climate control ON" - - light.turn_on: auto_led - -one_wire: - pin: GPIO25 - update_interval: 10s -```