esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 36 forks source link

Remote Transmitter only works with a arduino sketch, not with esphome #1370

Open Tiim opened 4 years ago

Tiim commented 4 years ago

Operating environment/Installation (Hass.io/Docker/pip/etc.): Connected to hass.io

ESP (ESP32/ESP8266, Board/Sonoff): ESP8266 NodeMCU board

ESPHome version (latest production, beta, dev branch) v1.14.5

Affected component: https://esphome.io/components/remote_transmitter.html

Description of problem:

I'm trying to use esphome to send 433mhz commands to my wall plugs to turn them on/off (old intertechno wallplugs). But it seems like my 433mhz transmitter doesn't send any signals. I also have a arduino uno running with a receiver that logs any received rf messages using the RCSwitch library and it doesn't receive anything as well. (Transmitter/Receiver: STX882 SRX882)

Problem-relevant YAML-configuration entries:

...
# Send rf packet every 5 seconds or when a switch in hass.io is switched
remote_transmitter:
  pin:
    number: D4
  carrier_duty_percent: 100%

interval:
  - interval: 5sec
    then:
      - remote_transmitter.transmit_rc_switch_raw:
           code: '000000000000000000010101'
           protocol: 1
           repeat: 
             times: 20
             wait_time: 35ms
switch:
  - platform: template
    name: "Test Socket"
    optimistic: True
    turn_on_action:
     - remote_transmitter.transmit_rc_switch_raw:
         code: '000000000000000000010101'
         protocol: 1
         repeat: 
           times: 20
           wait_time: 35ms

    turn_off_action:
     - remote_transmitter.transmit_rc_switch_raw:
         code: '000000000000000000010100'
         protocol: 1
         repeat:
           times: 40
           wait_time: 35ms

Logs (if applicable):

[20:31:43][D][remote_transmitter:066]: Sending remote code...
[20:31:45][D][remote_transmitter:066]: Sending remote code...
[20:31:50][D][remote_transmitter:066]: Sending remote code...
...

Additional information and things you've tried: At first I thought I had the wiring wrong, or a defective transmitter, so I tested it with the following platformio sketch:

#include <Arduino.h>
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup()
{
  Serial.begin(9600);
  mySwitch.enableTransmit(D4);
  mySwitch.setProtocol(1);
  mySwitch.setRepeatTransmit(3);
  //pinMode(LED_BUILTIN, OUTPUT);
  Serial.print("Starting.. ");
}

void loop()
{
  //delay(1000);
  mySwitch.send(21, 24);
  Serial.println("on");
  //digitalWrite(LED_BUILTIN, HIGH);
  delay(2000);
  mySwitch.send(20, 24);
  Serial.println("off");
  //digitalWrite(LED_BUILTIN, LOW);
  delay(2000);
}

This not only registers in the receiver but also successfully controlls the wall plugs. Therefore the wiring and transciever must be correct and working. I also tested if the active ESP8266 wifi would jam the signal by connecting it to the wifi which also was not the case.

I tried to look at what the RCSwitch library and esphome do different but since it looks like completely different code bases I didn't really find any clues.

To detect if the commands were successfully sent I had (besides the intertechno wall plug) an arduino uno with a receiver and the following code on it running, which binks an internal LED and logs to serial if it detects any rf packet.


#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

unsigned long ledLightOn = 0;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  Serial.begin(9600);
  mySwitch.enableReceive(digitalPinToInterrupt(PD2));
  Serial.println("rf_sniffer started");
}

void output(unsigned int length, unsigned int *raw);

void loop()
{
  if (ledLightOn + 1500 > millis()) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }

  if (mySwitch.available())
  {
    Serial.println("Found signal");
    int value = mySwitch.getReceivedValue();
    ledLightOn = millis();
    if (value == 0)
    {
      Serial.print("Unknown encoding");
    }
    else
    {
      Serial.print("Received ");
      Serial.print(mySwitch.getReceivedValue());
      Serial.print(" / ");
      Serial.print(mySwitch.getReceivedBitlength());
      Serial.print("bit Delay: ");
      Serial.print(mySwitch.getReceivedDelay());
      Serial.print(" Protocol: ");
      Serial.println(mySwitch.getReceivedProtocol());
      //output(mySwitch.getReceivedBitlength(), mySwitch.getReceivedRawdata());

    }

    mySwitch.resetAvailable();
  }
}

void output(unsigned int length, unsigned int *raw)
{
  Serial.print("Raw data: ");
  for (unsigned int i = 0; i <= length * 2; i++)
  {
    Serial.print(raw[i]);
    Serial.print(",");
  }
  Serial.println();
}
Tiim commented 4 years ago

I found a workaround to this problem by using a custom switch that uses the "real" rcswitch library. For future reference to anyone who might have the same problem or maybe to replicate the difference to the above approach here is the code:

mysensor.yaml

esphome:
  ...
  # include a custom switch from the file 'custom_433_switch.h' see code below
  includes:
    - custom_433_switch.h
  # include the "real" rcswitch library
  libraries:
    - "rc-switch"

switch:
  # see https://esphome.io/components/switch/custom.html
  - platform: custom
    # TODO: find out if there is a better way to insert configuration to custom component
    # Replace the following values: pin, code_on, code_off, length, protocol
    lambda: |-
      auto customSwitch = new Custom433Switch(D4, 21, 20, 24, 1);
      App.register_component(customSwitch);
      return {customSwitch};

    switches:
      name: "Test Switch"

custom_433_switch.h in the same directory as the yaml file above

#include "esphome.h"
#include "RCSwitch.h"

class Custom433Switch : public Component, public Switch {
 public:
  Custom433Switch(int pin, unsigned long code_on, unsigned long code_off, unsigned int bit_length, int protocol):
  pin{pin}, code_on{code_on}, code_off{code_off}, bit_length{bit_length}, protocol{protocol}
  {
  }

  void setup() override {
    mySwitch.enableTransmit(pin);
    mySwitch.setProtocol(protocol);
    mySwitch.setRepeatTransmit(20);
  }

  void write_state(bool state) override {
    if (state) {
      mySwitch.send(code_on, bit_length);
      ESP_LOGD("Custom433Switch", "Send on rf signal");
    } else {
      mySwitch.send(code_off, bit_length);
      ESP_LOGD("Custom433Switch", "Send off rf signal");
    }
    publish_state(state);
  }

 private:
  int pin;
  unsigned long code_on;
  unsigned long code_off;
  unsigned long bit_length;
  int protocol;
  RCSwitch mySwitch = RCSwitch();
};

It would be pretty interesting to see what the difference in the exact output is from the native esphome rcswitch comonent and the "real" rcswitch library. Unfortunately I don't own a scope or similar equipment to compare that myself.

kbx81 commented 4 years ago

@Tiim thank you for the detail! Have you experimented with pulse lengths or any of the other options? See https://next.esphome.io/components/remote_transmitter.html#remote-transmitter-rc-switch-protocol

Tiim commented 4 years ago

I have not. Since both the receiver connected to esphome as well as the receiver with the arduino sketch decoded the signal with protocol 1 I am assuming the pulse length should be defined in the protocol.

tymzang commented 4 years ago

Hi @Tiim, for code_on, code_off... where did you get these codes? I means on ESPhome or arduino... then put these code on ESPhome?

Tiim commented 4 years ago

@tymzang I think I got the code with ESPHome with the remote receiver component.

tymzang commented 4 years ago

@Tiim Would you please take photo of your RF Transmitter module? I want to see your antenna. I think my problem is antenna from kit is not good enough.

Tiim commented 3 years ago

@tymzang I can't take a photo of it right now, but this is the product photo from where I bought it. The one I got looks exactly like that too.

grafik

tymzang commented 3 years ago

@Tiim : thanks... Then the antennas are same as mine... I have a question about your code

"auto customSwitch = new Custom433Switch(D4, 21, 20, 24, 1);"

your code_on = 21 your code_off = 20

and you said these codes from ESPhome RF receiver... But the following are my code for Plug turn On

1) ESPHome: '00101101000110010110110110010011'

2) Arduino: Decimal: 2105146067 (32Bit) Binary: 01111101011110011111101011010011 PulseLength: 718 microseconds Protocol: 2 Raw data: 7212,460,1576,1480,572,1468,576,1464,580,1460,580,1464,572,452,1608,1452,576,448,1592,1468,580,1460,584,1456,592,1448,584,440,1612,432,1588,1472,588,1452,584,1460,584,1456,584,1456,596,1444,596,428,1616,1448,588,436,1612,1448,592,1448,592,432,1604,1456,584,436,1612,432,1596,1464,580,1464,600,

I tried both official code from ESPHome and Tasmota, but no hope... I am going to try last hope with your modified code, then help me figure out your "code_on, code_off"

Many thanks

Erriez commented 3 years ago

@Tiim @tymzang I had a similar issue where the timing of my RF device is critical: It must be <5%. I connected a protocol analyzer to measure and adjust the correct timing.

Note: The STX882 transmitter and SRX882 with antennas from NiceRF (Tiim's previous post) works reliable with my devices.

See related issue #1718.

sam9032 commented 3 years ago

@Tiim thanks a lot! Your idea works for me. I have the same problem with the normal esphome remote_transmitter and the rc-switch software works like a charm. Additionally, the rc-switch software has a few more ways to send the rf commands and i used this one as inspiration: https://github.com/sui77/rc-switch/blob/master/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino

My code for the esphome:

esp.yaml:

esphome:
  name: esp
  platform: ESP8266
  board: nodemcuv2
    # include a custom switch from the file 'custom_433_switch.h' see code below
  includes:
    - custom_433_switch.h
wifi:
...

switch:
  - platform: gpio
    pin: D1
    name: "lamp1"
    inverted: true
  - platform: gpio
    pin: D2
    name: "lamp2"
    inverted: true
  - platform: custom
    lambda: |-
      auto customSwitch = new Custom433Switch(13, 0b1111000100);
      App.register_component(customSwitch);
      return {customSwitch};
    switches:
      name: "switch1"
  - platform: custom
    lambda: |-
      auto customSwitch = new Custom433Switch(13, 0b1111001000);
      App.register_component(customSwitch);
      return {customSwitch};
    switches:
      name: "switch2"

custom_433_switch.h:

#include "esphome.h"

class Custom433Switch : public Component, public Switch {
 public:
  Custom433Switch(int pin, uint16_t code):
  pin{pin}, code{code}
  {
  }

  void setup() override {
    pinMode(pin, OUTPUT);
  }

  void write_state(bool state) override {
    if (state) {
      uint16_t RCL_code = (code<<2)+0b10;
      RCLswitch(RCL_code);
      ESP_LOGD("Custom433Switch", "Send on rf signal");
    } else {
      uint16_t RCL_code = (code<<2)+0b01;
      RCLswitch(RCL_code);
      ESP_LOGD("Custom433Switch", "Send off rf signal");
    }
    publish_state(state);
  }

void RCLtransmit(int nHighPulses, int nLowPulses) {
    digitalWrite(pin, HIGH);
    delayMicroseconds( 350 * nHighPulses);
    digitalWrite(pin, LOW);
    delayMicroseconds( 350 * nLowPulses);
}

void RCLswitch(uint16_t RCLcode) {
    for (int nRepeat=0; nRepeat<6; nRepeat++) {
        for (int i=4; i<16; i++) {
            RCLtransmit(1,3);
            if (((RCLcode << (i-4)) & 2048) > 0) {
                RCLtransmit(1,3);
            } else {
                RCLtransmit(3,1);
            }
        }
        RCLtransmit(1,31);    
    }
}
 private:
  int pin;
  uint16_t code;
};
stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

david-sawatzke commented 3 years ago

This is still an issue.

Hoeby commented 3 years ago

Like tymzang asked, how to work with binary code. A little instruction I noticed, that ESPhome puts an extra 0 before the binary code. Why i don't know. But with the extra code it doens't work. With the code like the Arduino discripes it works.

  1. ESPHome: '00101101000110010110110110010011'
  2. Arduino: Decimal: 2105146067 (32Bit) Binary: 01111101011110011111101011010011 PulseLength: 718 microseconds Protocol: 2

I am using the code from Tiim, which opened this issue, which is commented on 24 Jul 2020 The code uses decimal codes. Therefor search online for a binary -> decimal convert. Put your binary code in and copy the decimal output

Modify this line

"auto customSwitch = new Custom433Switch(D4, 21, 20, 24, 1);"

Where 21 is your decimal ON code Where 20 is your decimal OFF code

This worked for me.

========================================================

I needed a custom protocol, which was not in the rcswitch library. First do an install with a fault protocol number, but which is between 1 and 12 The library will be installed.

After that go to directory, where rcscanne needs to be replaced by your esphome name which is written in the .yaml file /home/pi/config/rfscanne/.piolibdeps/rfscanne/rc-switch

the .piolibdeps is a hidden directory After modication, run a new install but now with the right protocol number

I added protocol 13, which looks like this these lines are in RCSwitch.cpp line 93

{ 270, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 11 (HT12E) { 320, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 12 (SM5212) { 500, { 6, 1 }, { 1, 2 }, { 2, 1 }, true } // protocol 13 (Byron BY37)

OnurbHartmann commented 2 years ago

Dear all, just want to highligt that this is still an open issue. Using the workaround from @Tiim and @sam9032 I got my 433Mhz rf sender working. Thanks guys.

However, hope some can pick up and fix.

Chears

patfelst commented 2 years ago

I wanted to add that this is also an issue for me. I will try the custom component workaround from @Tiim and @sam9032. I've alerted the ESPHome devs on discord to see if they can take a look at this.

patfelst commented 2 years ago

To help diagnose the problem, I've done the following using 3x TTGO T-display ESP32 boards.

  1. On one TTGO, run an arduino program with the rc-switch library and a 433Mhz transmitter + receiver connected. Caputre RF codes from a 433MHz fan remote control. Result (after pressing the fan's light control button):
    
    Decimal: 10296346, binary 100111010001110000011010
    Code bit length: 24 bits
    Tri-State: not applicable
    PulseLength: 450 microseconds
    Protocol: 6
    Raw data: 10354,341,770,343,356,756,360,753,772,342,774,339,774,339,365,747,774,339,364,749,362,750,364,749,775,338,774,340,775,338,362,750,361,752,363,750,363,750,360,752,778,335,777,336,362,751,776,338,360,

Decimal: 10296346, binary 100111010001110000011010 Code bit length: 24 bits Tri-State: not applicable PulseLength: 450 microseconds Protocol: 6 Raw data: 10351,345,768,345,353,760,354,758,771,343,766,348,769,344,357,755,772,343,355,757,355,757,357,756,769,344,771,342,771,342,357,756,358,755,356,756,355,757,356,757,771,342,771,342,357,756,773,340,358,

Decimal: 10296346, binary 100111010001110000011010 Code bit length: 24 bits Tri-State: not applicable PulseLength: 450 microseconds Protocol: 6 Raw data: 10346,347,765,347,352,761,352,761,765,347,767,346,767,347,352,763,766,345,352,761,353,759,352,760,770,344,768,345,769,344,354,759,353,760,355,757,355,757,358,755,769,345,769,343,354,758,772,341,356,

There are never incomplete codes received (see step 2 below), the codes reported are always 100% repeatable. Using the same TTGO to transmit the binary code with 24-bits, protocol 6 with a pulse length of 450us works perfectly to emulate the fan remote control, the physical fan light turns on and off as exptected. The transmit code is:
```c++
#define TX_FAN_LIGHT 10296346

setup() {
  mySwitch.enableTransmit(21);  // Transmitter on GPIO21
  mySwitch.setProtocol(6);
  mySwitch.setPulseLength(450);
  mySwitch.setRepeatTransmit(3);
}

loop() {
  if (digitalRead(35) == 0) {
    delay(100);
    Serial.printf("Tx: Fan LIGHT [%d]\n", TX_FAN_LIGHT);
    mySwitch.send(TX_FAN_LIGHT, 24);
    // mySwitch.send("100111010001110000011010");
  }
}
  1. On another TTGO, install ESPHome with the following yaml to receive codes from the fan remote. The tolerance of 50% instead of default of 25% basically eliminates the occasional incomplete codes that are sometimes seen in the logs.

    remote_receiver:
    pin: GPIO27
    tolerance: 50%
    dump: rc_switch
    # dump: raw

    Result, ESPHome correctly identifies protocol 6, and the binary code has 24-bits, both as the arduino library did in step 1:

    [17:18:55][D][remote.rc_switch:261]: Received RCSwitch Raw: protocol=6 data='100111010001110000011010'
    [17:18:55][D][remote.rc_switch:261]: Received RCSwitch Raw: protocol=6 data='100111010001110000011010'
    [17:18:55][D][remote.rc_switch:261]: Received RCSwitch Raw: protocol=6 data='100111010001110000011010'
    [17:18:55][D][remote.rc_switch:261]: Received RCSwitch Raw: protocol=6 data='100111010001110000011010'
    [17:18:55][D][remote.rc_switch:261]: Received RCSwitch Raw: protocol=6 data='100111010001110000011010'
    [17:18:55][D][remote.rc_switch:261]: Received RCSwitch Raw: protocol=6 data='100111010001110000011010'
  2. On a third TTGO, install ESPHome to transmit codes to the fan, emulating the fan remote:

    
    remote_transmitter:
    pin: GPIO21
    carrier_duty_percent: 100%

button: