devices.esphome.io
Tinxy 4N with Fan Regulator
Tinxy 4N with Fan Regulator
Device Type: relayElectrical Standard: inBoard: esp8266
Tinxy 4 Node Retrofit Module with Fan Regulator
Amazon Link
      
  
        
        
Preparing the device for flashing
Start by carefully removing the heat shrink sleeve. Next, desolder the W2 and W3 bridges located on the backside of the Tinxy board, as shown in the provided image. Connect wires from the Tinxy board's RXD, TXD, 3.3V, and GND pads to a USB TTL adapter, making sure to swap the connections for RXD and TXD.
Press and hold the Tinxy reset button while connecting the TTL adapter to your computer. Flash the firmware as soon as the esp8266 is detected, as the soldered on esp8266 tends to reboot if it didnt detect pwm signal from the MCU on GPIO14.
Once the flashing is complete, resolder the W2 and W3 bridges as before, remove the TTL wires, and reapply the heat shrink sleeve to complete the modification.
Note: Unlike other devices, Tinxy Esp8266 communicates with the MCU using serial data to activate the relay. So its neccessry to disconnect the W2 and W3 serial bridge between Esp and MCU to ensure no intereference while flashing and reconnecting it is crucial to esnsure proper functioning.
      
  
        
As of 10/2024, Tinxy 4N with fan regulator devices failed flashing with the esphome web flasher because it uses a baud rate of 115200. If flashing doesn't work, try flashing via esptool.py where the baud rate can be set. The baud rate was identified to be 460800. If this fails in the future try other baud rates.
esptool.py Code
python3 -m esptool --port /dev/ttyUSB0 --baud 460800 --before no_reset --after hard_reset write_flash -fm dio 0x00000 firmware.binEsp Code
esphome:  name: tinxy-4node  friendly_name: tinxy-4node  on_boot:    - priority: 200.0      then:        - output.turn_on: gen_pwm_test        - output.set_level:            id: gen_pwm_test            level: 50%  includes:    - uart_read_line_sensor.houtput:  - platform: esp8266_pwm    id: gen_pwm_test    pin: GPIO14    frequency: 1000 Hz  - platform: template    id: fanoutput    type: float    write_action:    - uart.write: ""esp8266:  board: esp01_1m# Enable logginglogger:  baud_rate: 0  level: verbose# Enable Home Assistant APIapi:  encryption:    key: ""ota:  password: ""wifi:  ssid: ""  password: !secret wifi_password  power_save_mode: none  fast_connect: truestatus_led:  pin:    number: GPIO12    inverted: yesuart:  id: uart_bus  tx_pin: 1  rx_pin: 3  baud_rate: 9600text_sensor:  - platform: custom    lambda: |-      auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));      App.register_component(my_custom_sensor);      return {my_custom_sensor};    text_sensors:      id: "uart_readline"      name: "UART Feedback"      on_value:        then:          - lambda: |-              ESP_LOGD("main", "The current value is %s", x.c_str());              if (id(uart_readline).state == "41") {                id(relay4_wall_switch).publish_state(true);                id(relay4).publish_state(true);              } if(id(uart_readline).state == "40") {                id(relay4_wall_switch).publish_state(false);                id(relay4).publish_state(false);              }              if (id(uart_readline).state == "31") {                id(relay3_wall_switch).publish_state(true);                id(relay3).publish_state(true);              } if(id(uart_readline).state== "30") {                id(relay3_wall_switch).publish_state(false);                id(relay3).publish_state(false);              }              if (id(uart_readline).state == "21") {                id(relay2_wall_switch).publish_state(true);                id(relay2).publish_state(true);              } if(id(uart_readline).state== "20") {                id(relay2_wall_switch).publish_state(false);                id(relay2).publish_state(false);              }              if (id(uart_readline).state == "11") {                id(relay1_wall_switch).publish_state(true);                auto call = id(fan_1).turn_on();                call.perform();              } if(id(uart_readline).state== "10") {                id(relay1_wall_switch).publish_state(false);                auto call = id(fan_1).turn_off();                call.perform();              }binary_sensor:  - platform: template    name: "Relay4 Wall Switch"    id: relay4_wall_switch  - platform: template    name: "Relay3 Wall Switch"    id: relay3_wall_switch  - platform: template    name: "Relay2 Wall Switch"    id: relay2_wall_switch  - platform: template    name: "Relay1 Wall Switch"    id: relay1_wall_switchswitch:  - platform: template    name: "Relay2"    id: relay2    optimistic: true    restore_mode: RESTORE_DEFAULT_OFF    turn_on_action:      - uart.write: '#2100#'    turn_off_action:      - uart.write: '#2000#'  - platform: template    name: "Relay3"    id: relay3    optimistic: true    restore_mode: RESTORE_DEFAULT_OFF    turn_on_action:      - uart.write: '#3100#'    turn_off_action:      - uart.write: '#3000#'  - platform: template    name: "Relay4"    id: relay4    optimistic: true    restore_mode: RESTORE_DEFAULT_OFF    turn_on_action:      - uart.write: '#4100#'    turn_off_action:      - uart.write: '#4000#'fan:  - platform: speed    output: fanoutput    id: fan_1    speed_count: 3    name: "Fan"    on_turn_on:      - uart.write: !lambda |-          static std::string myUartStringsOn[4] = {"#1100#", "#1033#", "#1066#", "#1100#"};          if(id(fan_1).speed == 0)            id(fan_1).speed = 1;          std::string chosenString = myUartStringsOn[id(fan_1).speed];          std::vector<uint8_t> vec(chosenString.begin(), chosenString.end());          return vec;    on_turn_off:      - uart.write: '#1000#'    on_speed_set:    - if:        condition:          lambda: return (id(fan_1).state);        then:          - uart.write: !lambda |-              static std::string myUartStringsOn[4] = {"#1100#", "#1033#", "#1066#", "#1100#"};              std::string chosenString = myUartStringsOn[id(fan_1).speed];              std::vector<uint8_t> vec(chosenString.begin(), chosenString.end());              return vec;number:  - platform: template    name: "Switch Delay"    id: "switchdelay"    optimistic: true    restore_value: true    initial_value: "60"    min_value: 5    max_value: 100    step: 1    set_action:      then:        - uart.write: !lambda |-            int multiplexer = 625 + static_cast<int>((x - 5) * 25);            String uartValue = "(";            if (multiplexer < 1000) {              uartValue += "0";            }            uartValue += String(multiplexer, DEC) + ")";            std::vector<unsigned char> uartBytes(uartValue.begin(), uartValue.end());              return uartBytes;Uart reading library
Place the uart_read_line_sensor.h library under esphome directory
#include "esphome.h"class UartReadLineSensor : public Component, public UARTDevice, public TextSensor { public:  UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}  void setup() override {    // nothing to do here  }  int readline(int readch, char *buffer, int len)  {    static int pos = 0;    int rpos;    if (readch > 0) {      switch (readch) {        case ';': // Return on CR          rpos = pos;          pos = 0;  // Reset position index ready for next time          return rpos;        default:          if (pos < len-1) {            buffer[pos++] = readch;            buffer[pos] = 0;          }      }    }    // No end of line has been found, so return -1.    return -1;  }  void loop() override {    const int max_line_length = 20;    static char buffer[max_line_length];    while (available()) {      if(readline(read(), buffer, max_line_length) > 0) {        publish_state(buffer);      }    }  }};