IR transmitter/receiver

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
ajocius
Posts: 81
Joined: Mon Feb 19, 2018 6:31 am

Re: IR transmitter/receiver

Post by ajocius » Tue Jan 07, 2020 12:02 pm

IR module is like this I assume:
https://www.aliexpress.com/item/32692872340.html

Looking for logic level converted I find many different types. Would this work?
https://www.aliexpress.com/item/32308637728.html

User avatar
Roberthh
Posts: 2020
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: IR transmitter/receiver

Post by Roberthh » Tue Jan 07, 2020 12:14 pm

These ones should work, since the signal is active-low. The two channel model is sufficient; just the labeling is confusing.

User avatar
mcauser
Posts: 453
Joined: Mon Jun 15, 2015 8:03 am

Re: IR transmitter/receiver

Post by mcauser » Tue Jan 07, 2020 7:48 pm

Hi @ajocius, yes to both of those.
I’m using the 4ch blue logic level converter in your link.

The YS module does not support all IR protocols.
It specifically listens for and transmits the NEC protocol.

If you want to RX any remote, you can with a TL1838 IR receiver LED, but you’ll need to decode the protocol yourself by watching/counting edges/timings. The ESP32 RMT module will be able to handle this, but it’s not finished yet.
https://a.aliexpress.com/eCJIcsgs

To TX any remote, you can send pulses to an IR TX LED, however, the timings are tight and if you are using a slow/busy microcontroller, might be glitchy. The ESP32 RMT module solves this by offloading the TX pulsing to dedicates hardware. The RMT module so far can TX, but it’s still a work in progress.

Online
User avatar
pythoncoder
Posts: 4253
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: IR transmitter/receiver

Post by pythoncoder » Wed Jan 08, 2020 8:20 am

mcauser wrote:
Tue Jan 07, 2020 7:48 pm
...
To TX any remote, you can send pulses to an IR TX LED, however, the timings are tight and if you are using a slow/busy microcontroller, might be glitchy...
I have wondered whether this might be done (e.g. on the Pyboard) by using a PWM output to produce a constant 38KHz signal, with two MOSFETs driving the IR LED configured as a simple gate. This would enable another pin to drive the bitstream which is slower and less time critical.

One of those things I keep meaning to play with.
Peter Hinch

OutoftheBOTS_
Posts: 783
Joined: Mon Nov 20, 2017 10:18 am

Re: IR transmitter/receiver

Post by OutoftheBOTS_ » Wed Jan 08, 2020 9:05 am

I have wondered whether this might be done (e.g. on the Pyboard) by using a PWM output to produce a constant 38KHz signal, with two MOSFETs driving the IR LED configured as a simple gate. This would enable another pin to drive the bitstream which is slower and less time critical.

One of those things I keep meaning to play with.
I would think that you wouldn't need a mosfet as you can just enable and disable the timer which is just flicking the EN bit in the CR1 register which is as fast as turning a pin on/off (flicking a bit in the ODR)

I did build a IR transmitter that I drove with the RPi, because the RPi doesn't have hardware timers that are accessible in Python I used a 555 timer to create the 38KHz PWM then used a python script to turn the PWM on/off by flicking the EN pin on the 555 timer on/off

Ivan de Almeida
Posts: 2
Joined: Tue Dec 10, 2019 11:40 am

Re: IR transmitter/receiver

Post by Ivan de Almeida » Thu Feb 06, 2020 8:50 pm

I simply need the infrared transmission signal to turn an air conditioner on and off, in which case would there be something simple that works?

Online
User avatar
pythoncoder
Posts: 4253
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: IR transmitter/receiver

Post by pythoncoder » Wed Feb 12, 2020 10:30 am

I've done a quick test with this script on a Pyboard 1.1 to check the accuracy and stability of timings:

Code: Select all

from pyb import Pin, Timer
from time import ticks_diff, ticks_us
import micropython

p = Pin('X1')
tim = Timer(2, freq=38000)
ch = tim.channel(1, Timer.PWM, pin=p)
ch.pulse_width_percent(50)

def wait(bit):
    tw = 1687 if bit else 563
    t = ticks_us()
    while ticks_diff(ticks_us(), t) < tw:
        pass

def send(bit):
    ch.pulse_width_percent(50)
    wait(1)
    ch.pulse_width_percent(0)
    wait(bit)

def test():
    while True:
        for bit in [1,0,1,1,0]:
            send(bit)
Before running test() it produced a rock steady squarewave which I measured at 37.88KHz.

The test() function produces the modulation required by the NEC protocol - just a few data bits, I haven't bothered with the start sequence. Data bits comprise a 562.5µs mark followed by a space whose length determines the bit value. 562.5µs denotes 0 and 1.6875ms denotes 1. Actual periods were 580µs and 1720µs, but these could obviously be tweaked by adjusting the values. Waveforms looked stable and the approach looks promising. Alas a solution based on this approach would block for the period of a burst transmission (up to 76.5ms in extended address mode).

It might be possible to concoct a nonblocking solution using timer callbacks to switch the pulse width, but this might affect precision which I believe is fairly critical.
Peter Hinch

Online
User avatar
pythoncoder
Posts: 4253
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: IR transmitter/receiver

Post by pythoncoder » Wed Feb 12, 2020 12:07 pm

On the face of it a blocking solution looks very easy. The following produces a waveform matching that in this reference. Of course the acid test is to attach an IR LED, find a valid address/data pair, and fire it at a device. I haven't yet done this. Tested on a Pyboard 1.1.

Code: Select all

from pyb import Pin, Timer
from time import sleep_us, sleep
from micropython import const

_SPACE = const(0)  # Or 100 depending on wiring
_TBURST = const(563)
_T_ONE = const(1687)
_TSTART = const(9000)

p = Pin('X1')
tim = Timer(2, freq=38000)
ch = tim.channel(1, Timer.PWM, pin=p)
ch.pulse_width_percent(_SPACE)

def send(bit):
    ch.pulse_width_percent(50)
    sleep_us(_TBURST)
    ch.pulse_width_percent(_SPACE)
    sleep_us(_T_ONE if bit else _TBURST)

def sendbyte(b):  # Send byte followed by 1's complement
    for x in range(8):
        send((b >> x) & 1)
    b ^= 0xff
    for x in range(8):
        send((b >> x) & 1)

# Send preamble, address, data, stop
def transmit(addr, data):
    ch.pulse_width_percent(50)  # Start
    sleep_us(_TSTART)
    ch.pulse_width_percent(_SPACE)
    sleep_us(4500)
    sendbyte(addr)  # Now send address and data
    sendbyte(data)
    ch.pulse_width_percent(50)
    sleep_us(_TBURST)
    ch.pulse_width_percent(_SPACE)

# Repeat code sent when a button is held down.
# Send 108 ms after transmit start, optionally again at 108ms intervals
def repeat():
    ch.pulse_width_percent(50)
    sleep_us(_TSTART)
    ch.pulse_width_percent(_SPACE)
    sleep_us(2250)
    ch.pulse_width_percent(50)
    sleep_us(_TBURST)
    ch.pulse_width_percent(_SPACE)

def test():
    while True:
        transmit(0, 0xad)
        sleep(1)
Peter Hinch

Marius
Posts: 16
Joined: Fri Nov 30, 2018 2:08 pm

Re: IR transmitter/receiver

Post by Marius » Wed Feb 19, 2020 8:26 pm

Ive done it. Works great. Im just saving the timing values and replaying them with pwm 38khz and an ir led.

Online
User avatar
pythoncoder
Posts: 4253
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: IR transmitter/receiver

Post by pythoncoder » Thu Feb 20, 2020 7:09 am

Thanks for the report. I am currently working on a nonblocking solution compatible with uasyncio which I will publish shortly. It also handles the RC-5 protocol.
Peter Hinch

Post Reply