Faking an IR remote control using ESPHome

Yes, absolutely!

To call such a set_brightness function from HA and transfer the needed integer value for the target brightness you could use a user-defined service.

The ESPhome coding could use global variables to hold the current brightness level and the steps up or down need to reach a desired target level.

The loop to send the commands to brighten or dim the light would typically be implemented using an interval that regularly checks if there are up or down commands remaining to be sent.

Some of the coding will need lambdas with C++ code. But don’t be afraid of it. You’ll find many examples how to do that. I did all my lambdas without any prior knowledge of C++ with some Googling and experimenting.

1 Like

Thank you so much! I’ll look into it.

I actually already bumped into lambdas when implementing 433MHz control for my sockets. (ESPHome didn’t allow me to set sync values for custom protocol to more than 255 * pulse_length but my sockets actually require 590, so I had to basically rewrite my old arduino code in lambda to make it work.)

1 Like

I have changed Dump: to pioneer and get nothing. I then tried raw and all I get is raw data. Here is my yaml file

esphome:
  name: irtest
  friendly_name: irtest

esp8266:
  board: d1_mini

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

# Enable logging
logger:
  level: VERBOSE

# Enable Home Assistant API
api:
  
ota:

# Enable Web server.
web_server:
  port: 80

remote_receiver:
  pin:
    number: D5
    inverted: true
  dump: all

This is strange. Do you get a lot of “raw” lines, even if you are not sending? Is there any strong source of IR in the room, that might saturate your receiver (sun light, heating,
)? Is your sender too close to your receiver, so it saturates? Is there another IR emitter or IR remote in the room that you are not aware of? Have you tried to move your receiver away from your ESP to reduce WIFI crosstalk into the receiver circuit? Have you tried leaving the “web:” component out (not needed at that point)? Have you tried changing the room?
If none of these solves the puzzle I would tend to try and replace the components one by one. Another IR receiver, another ESP.

Thanks for all the suggestions.
I plugged my ir receiver into my D1-mini that I use to turn my LG tv on and off. This the one that I set up several months ago.
It was exactly the same giving me only pronto codes. Strange, cause it definetly worked before.
I then decided to replace the three Dupont wires to the receiver and would you believe it, it now works.

However, moving it back my iMac, I now get pronto codes received about every three seconds and you can see the led flashing. Even if I cover the receiver it still does it. Weird.

I’ve now set Dump: to pioneer so can capture all the codes I need.

1 Like

I did it! I made a slider to change brightness that simulates repeated button presses.
And I didn’t even need half of the things you mentioned because I discovered Number component, so I made the thing using that, a global variable and a lambda:

globals:
  - id: brightness_prev
    type: int
    restore_value: no
    initial_value: '-1'

remote_transmitter: 
  - id: infra
    pin: GPIO04
    carrier_duty_percent: 50%

button:
  - platform: template
    name: "ir5"
    id: bright_up
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0xFF00
          command: 0xFA05
          command_repeats: 2
          transmitter_id: infra
  - platform: template
    name: "ir4"
    id: bright_down
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0xFF00
          command: 0xFB04
          command_repeats: 2
          transmitter_id: infra

number:
  - platform: template
    name: brightness
    id: brightness_slider
    min_value: 0
    max_value: 9
    initial_value: 0
    step: 1
    optimistic: true
    on_value:
      then:
        - lambda: |-
            int steps = 0;
            //Just booted up? Get the LED strip to known value (0), otherwise get the difference
            if (id(brightness_prev) == -1)
                steps = -9;
            else
                steps = x - id(brightness_prev);
                
            //No difference? Don't do anything.
            if (steps==0)
                return;
            
            //Should we go up or down?
            auto button = steps>0 ? bright_up : bright_down;            
            //How many steps?
            steps = abs(steps);
            
            //Press the button repeatedly
            for (int i=0;i<steps;i++)
            {
                button->press();
                delay(50);
            }
            ESP_LOGI("main", "Brigthness: %d -> %d", id(brightness_prev), id(brightness_slider).state);
            //Save current value for future change
            id(brightness_prev) = x;

The on_value action triggers when device boots up, so it sets the LED strip to minimum brightness and then I can change it however I want.
The strip has few more quirks that I have to account for, but that’ll probable be no problem.

Just one more thing. Is possible to change the value of a component (be it toggling a switch, or changing a number from one value to a different one in this case) without triggering its action?
In a specific circumstances, my LED strip can get reset and it changes its brightness to “9” but its needless to set the value in ESPHome the normal way and then wait until it cycles through 9 command repeats before I can actually lower it to a normal level.

1 Like

This is nice. Congratulations!

But are you sure that your code works as intended if you quickly change the brightness several times, i.e. 0, 9, 0, 9?
I think if you change again while your last change is still being processed your code might fail.

This is exactly the reason why I proposed to use an independent interval loop. This would decouple the counting and sending from any change of the target brightness and it would always work correctly. Your number component would simply store a target value. The interval would compare the target with the current value and would bright_up or bright_down only one step per interval if they differ (and increment/decrement the current value).

Correcting the number without action would be possible too: Simply change the target and the current value at the same time.

I’m trying to get a fireplace/heater set up, I’ve received the following from the included remote:

[I][remote.pronto:233]: Received Pronto: data=
[I][remote.pronto:235]: 0000 006D 0060 0000 0030 0011 0030 0011 0010 0032 002F 0011 0030 0011 000F 0032 000F 0032 000F 0032 000F 0032 000F 0032 000F 0032 002F 0113 0030 0011 0030 0011 000F 0032 002F 0011 0030 0011 0010 0032 000F 0032 000F 0032 000F 0032 
[I][remote.pronto:235]: 000F 0032 000F 0032 002F 0113 0030 0011 0030 0011 000F 0031 0030 0011 0030 0011 000F 0031 000F 0031 000F 0031 000F 0031 000F 0031 0010 0031 0030 0114 002F 0011 0030 0011 000F 0031 0030 0011 0030 0011 000F 0031 000F 0031 000F 0031 
[I][remote.pronto:235]: 000F 0031 000F 0031 000F 0031 0030 0113 0030 0011 0030 0011 000F 0031 0030 0011 0030 0011 000F 0031 000F 0031 000F 0032 000E 0032 000E 0032 000E 0032 002F 0114 002F 0011 002F 0012 000E 0032 002F 0012 002F 0012 000E 0032 000E 0032 
[I][remote.pronto:235]: 000E 0033 000E 0033 000E 0034 000D 0033 002E 0116 002D 0012 002E 0012 000E 0034 002D 0012 002E 0012 000E 0034 000D 0034 000D 0034 000D 0034 000D 0034 000D 0034 002D 0116 002D 0013 002D 0013 000D 0034 002C 0014 002C 0014 000C 0036 
[I][remote.pronto:235]: 000B 0035 000B 0036 000B 0035 000B 0036 000B 0036 002B 0181 06C3
[V][remote.drayton:176]: Decode Drayton: Fail 1, - 0
[I][remote.rc_switch:261]: Received RCSwitch Raw: protocol=1 data='11011000000'

I tried using the RCSwitch Raw with the following:

remote_transmitter:
  pin: GPIO13
  carrier_duty_percent: 50%

button:
  - platform: template
    name: "Toggle_Fireplace"
    on_press:
      - remote_transmitter.transmit_rc_switch_raw:
          code: '11011000000'
          protocol: 1

However I’ve had no luck. I even tried capturing the raw data and using that, but no luck there either. I also tried using JUST the pronto codes, nothing there either (although its possible I didn’t have the codes set up correctly. I wasn’t 100% how to send the multiple lines of codes) I am using this set of transmitter & receiver: (https://www.amazon.com/dp/B08X2MFS6S?psc=1&ref=ppx_yo2ov_dt_b_product_details)

I know I have it wired correctly, as I can see the red light on the transmitter board flash when I attempt to send a signal. I couldn’t find any codes online for my fireplace unit, however, I do know that my fireplace remote also turns on/off my Lasko fan. I tried any Lasko codes I could find online, no luck there either. Any help is greatly appreciated!

Hi,

I’m probably doing something wrong but i cant figure out what!

I have a Freenove ESP32 Wroom board.
I can receive ir codes from my air heat pumps remote in the following formats to my board without any problem:
Coolix, Pronto, RAW, Samsung, Toshiba AC

remote_receiver:
  pin: 
    number: GPIO32
    inverted: true
  dump: all

The problem is sending the different remote codes via remote_transmitter

remote_transmitter:
  pin: 
    number: GPIO19
  carrier_duty_percent: 50%

I started with trying to send Coolix but that gave me nothing in the logs so i moved on to try to send the rest of the codes to test.
I have the following for testning the different codes i my .yaml

button:
  - platform: template
    name: "Toshiba AC"
    id: toshiba_id
    on_press:
      - remote_transmitter.transmit_toshiba_ac:
          rc_code_1: 0xB24DBF4040BF
      - logger.log: "My Log: Toshiba AC"
  - platform: template
    name: "Samsung"
    id: samsung_id
    on_press:
      - remote_transmitter.transmit_samsung:
          data: 0xB946F50A09F6
          nbits: 48
      - logger.log: "My Log: Samsung"
  - platform: template
    name: "Pronto"
    id: pronto_id
    on_press:
      - remote_transmitter.transmit_pronto:
          data: "0000 006D 0010 0000 0008 0020 0008 0046 000A 0020 0008 0020 0008 001E 000A 001E 000A 0046 000A 001E 0008 0020 0008 0020 0008 0046 000A 0046 000A 0046 000A 001E 000A 001E 0008 06C3"
      - logger.log: "My Log: Pronto"
  - platform: template
    name: "RAW"
    id: raw_id
    on_press:
      - remote_transmitter.transmit_raw:
          code: [2000,-1000, 400,-1000, 400, -400,1000,-1000, 400,-1000, 400, -400,1000,-1000, 400,-1000, 400, -400,2000,-5600,
                 2000,-1000, 400,-1000, 400, -400,1000,-1000, 400,-1000, 400, -400,1000,-1000, 400,-1000, 400, -400,2000,-5600,
                 2000,-1000, 400,-1000, 400, -400,1000,-1000, 400,-1000, 400, -400,1000,-1000, 400,-1000, 400, -400,2000,-5600]
          carrier_frequency: 38kHz
          repeat:
            times: 5
            wait_time: 16ms
      - logger.log: "My Log: RAW"

This is what i get in the logs for the respective codes:

Pronto
[19:20:06][D][button:010]: ‘Pronto’ Pressed.
[19:20:06][D][remote.pronto:101]: Send Pronto: frequency=38kHz
[19:20:06][D][remote.pronto:106]: Send Pronto: intros=32
[19:20:06][D][remote.pronto:107]: Send Pronto: repeats=0
[19:20:06][D][main:459]: My Log: Pronto

RAW
[19:20:15][D][button:010]: ‘RAW’ Pressed.
[19:20:15][D][main:561]: My Log: RAW

Samsung
[19:20:16][D][button:010]: ‘Samsung’ Pressed.
[19:20:16][D][main:424]: My Log: Samsung

Toshiba AC
[19:20:17][D][button:010]: ‘Toshiba AC’ Pressed.
[19:20:17][D][main:389]: My Log: Toshiba AC

If i try my code on a different board from another manufacturer i get the same results


But if i use NEC it for some reason seam to work.

button:
  - platform: template
    name: "NEC"
    id: nec_id
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x1234
          command: 0x78AB
          command_repeats: 1
      - logger.log: "My Log: Nec"

[20:02:11][D][button:010]: ‘NEC’ Pressed.
[20:02:11][D][remote.nec:017]: Sending NEC: address=0x1234, command=0x78AB command_repeats=1
[20:02:11][D][main:576]: My Log: Nec

Can someone point me in the right direction of what I’m doing wrong or what the problem could be?

Thanks!
I found this post and was messing around with ESP devboard + IR receiver module + IR send module and got some issues, so went looking on ali for better parts and stumbled on this myself too. Found that pins should be GPIO14 and GPIO4 and theoretically it should be easy.

Today I received the package and was praying it would work. Got all working in 30 minutes without a sweat. Awsome.

I returned here to inform other persons, but found you already got everything described well here.
Better even: I still was breaking my head how to deliver the 5v supply the best and was thinking how to design the 3-d case. You posted it already here.

Many thanks to OP!
Many thanks to all the extra info on this combo card :smiley:

3 Likes

I had hoped that info would help someone. The only thing I forgot to add is that the typical female Dupont connectors are too tall for the case I used/linked. If you bend the pins slightly inward, the case will then close. Some people have also suggested to use a “clear” filament to print the case for better IR transmission.

2 Likes

2 posts were split to a new topic: Binary HA sensor help

I want to thank all for the discussion and assistance on this. This helped me move forward on automating the control of three TVs used in the lobby of a business, to ensure they are turned on as the business opens and off as the business closes for the night.

The TVs are made by Samsung, who only has a power toggle infrared command. That makes it really hard to ensure it’s not confused by peoples’ random interaction with the TVs, blindly turning them off when they should be on and vice-versa.

Thankfully, the TVs have a USB port that can be used to connect a thumb drive, and the port is only powered when the TV is on. I am able to monitor the power output via the USB port to determine if the TV is on or off. Of course, if I want the ESP to turn the TV on, it has to be powered from something other than the TV USB port. I use one GPIO to drive the IR LED and another with internal pulldown to monitor whether it has 5V or high impedance coming from the TV’s USB port. Since I’m using an ESP32, I don’t have to do any voltage conversions.

Just a small eureka moment I had and wanted to share in the hopes it’ll help someone else. This would probably be extensible for many newer (5 to 10 years) stereos, DVD/Blue-Ray players, etc. many of which have USB input options.

1 Like

That’s just the command sent from the remote. Samsung (and other manufacturers) also support individual commands for power on & power off.

You don’t need the usb hack to know if the TV is on. Just send a couple of power on commands in case one is missed.

Enter “Samsung discrete power commands” in your favourite search engine & you should find them pretty quickly.

Hello,
thank you very much for your guide/tutorial. If I can make it work I will resolve a problem that I have from more than 4 years.

I have question.
I am using same IR trasmitter and receiver you are using, but I am using ESP32 NodeMCU WiFi with CP2102 and have different PIN from your ESP8266 D1 Mini.

I am trying to find the way to adapt the connection but I am afraid to brake something. Is it correct to substitute D5 and D7 with G14 and G13?

Thank You very much
Regards
Matteo

That should be fine. G14 is a bit special in that it outputs a PWM signal right after boot before the input/output configuration of your YAML gets activated, but that should not hurt. If you want to really avoid any risks, use pins that do not have any special functions. You can check the GPIO list shown in this site and choose two pins that are marked with OK / OK and without any comment in the fourth column:

Hello,
Thank You very much for your support! I am really to happy to finally find a way to make “smart” something that is not born for.
I resolved with GPIO18 for receiving and GPIO23 for trasmitting. Like you suggest, for my luck, I was able to find the right protol, is a NEC one.

So it works very smooth. Right now I am using this product with single diode (Link) but the range is too short for my porpuse. That one works only if I stay in a range lower than a meter, instead I need about 4/5 meters range.

The one that you suggest in the post from Aliexpress (Link) have this type of range? It says it is “two channel” but I don’t know what it means, I just need to have a longer range and I am safe and sound.

Thank You very much again!!! :partying_face: :partying_face: :partying_face:

Regards
Matteo

Yeah, the “two channel” in the description is just non-sense. The module has one channel and two diodes for it, which extends the range as you expect. Glad i could help.

Hello Jorg,
I just want to update you and everyone else that the new IR trasmitter (the one you cited at the beginning of the post) has just arrived.
I already tested it and
 astonish!! The range is now several meters
 I think more than ten meters (obviously with no obstacles between the tramsitter and the receiver).

You definitely resolved my problem and I want, above all, to say thank you!

I probably, as soon as I will find the time, publish a guide to make controllable by Home Assistant my VMC of ALPAC (the brand of the air change machine).

Thank you again

Regards
Matteo

1 Like

Thanks very much for this excellent How-To.
It helped me very well!

1 Like