This is an infrared remote control send / receive library by micropython.
Fans, TVs, and even air conditioners with long data lengths operate stably regardless of the manufacturer.
The microcomputer supports only the ESP32 chip and the RP2040 chip (Raspberry Pi Pico). It works on the original micropython. The supported version is v1.17 or higher.
The send process uses a board-specific experimental micropython API. There is a risk that it will not work due to changes in specifications in the future. I have confirmed the operation up to v1.19.(2022/07)
A sample program is also available for immediate use. You can try infrared remote control data acquisition / transmission with GUI application software for PC.
Micropython firmware for ESP32
Micropython firmware for RP2040 (Raspberry Pi Pico)
Demo micropython main firmware
Demonstration PC side python application software
Infrared LEDs with an appropriate wavelength (wavelength around 950 nm) are controlled on and off with a microcomputer. The following circuits are ofte Connect the TxPin to the pins of the microcomputer.
For the on section of the signal, a PWM wave with 38kHz and a duty ratio of 1/3 is used. The LED is off during the signal off section. Therefore, the sender has the following three parameters. This is specified in the constructor argument of the infrared transmission library UpyIrTx.py. (However, in the case of the RP2040 chip, You need to modify UpyIrTx.py directly.)
Use the infrared remote control light receiving module. Connect the output RxPin of the light receiving module to the pin of the microcomputer. Depending on the light receiving module, it may have an open collector output, in which case a pull-up resistor is installed.
The receiver has the following one parameter. This is specified in the constructor argument of the infrared transmission library UpyIrRx.py.
If it is difficult to build a circuit with individual parts, it is a good idea to purchase a ready-made module. The IR REMOTE UNIT, which can be connected with the Grove connector, is very convenient. In combination with M5Stack, infrared signals can reach distances of several meters.
The UpyIrRx class controls the reception process. The output voltage of the infrared remote control light receiving module is a digital signal as shown below. Record the time length of this digital signal in list format. This recorded data can be used in the infrared remote control transmission library below.
The output level of the infrared remote control light receiving module is generally High (= 1) when no light is received (called idle_level). When this output switches to Low, remote control signal reception starts. If the output level does not change for a certain period of time (blank_time [msec]), it is regarded as the end of the remote control signal and the received data is confirmed.
__ ____ _________ ___________________ If idle_level = 1
|_______| |_____| |_____|
start <- blank time -> End of signal
<- t0 ->< t1 >< t2 ><-- t3 -->< t4 > ... [usec]
Waveform data list = [t0, t1, t2, t3, t4]
( The unit is usec, and the number of elements is odd. )
__init__(pin, max_size=0, idle_level=1)
Parameters
pin
It is a pin object (machine.Pin object) of the pin that is the input of
the received signal.
It is a microcomputer pin connected to RxPin in the above circuit.
max_size: int
Maximum length that can store the received signal (If the default value is 0, the data length is 1023.)
idle_level: int
Output level of infrared remote control light receiving module when there is no light receiving 0/1 (High = 1 by default)
record(wait_ms=0, blank_ms=0, stop_size=0) -> int
After waiting for wait_ms[msec], the remote control reception signal data is recorded in the internal variable. When this method is called, the previously recorded data will be discarded. The newly recorded data will be overwritten with internal variables. If it cannot be received normally, the recorded data will be invalid. Whether or not it was recorded normally is judged by the return value.
Parameters
wait_ms: int
It is time [msec] to wait for the remote control reception signal. During this time, processing will be blocked. If the default value is 0, it will be 5000 [msec].
blank_ms: int
When the stationary section of the remote control received signal exceeds this time [msec], it is considered to be the end of the remote control signal. If the default value is 0, it will be 200 [msec].
stop_size: int
The part that exceeds this signal length is excluded from recording. If the default value is 0, no constraint is applied. However, if the max_size length of the constructor is exceeded, an overflow error will occur.
Return
get_mode() -> int
Acquires the remote control signal reception status.
get_record_size() -> int
Acquires the signal length of the remote control reception signal recorded in the internal variable. It corresponds to the number of elements of the waveform data acquired by get_calibrate_list() below.
get_calibrate_list() -> list
Acquires the remote control received signal data recorded internally by the previous record() method. This list is used when sending remote control signals. If there is no normal recorded data, an empty list will be acquired.
Return
A one-dimensional list of int type with an odd number of elements. Empty list if there is no normal recorded data. Even if this method is called, the internal recorded data is not destroyed and is retained.
Waveform data that has been calibrated to exclude the influence of the delay characteristics of the infrared remote control light receiving module is acquired.
A sister version of the method is get_record_list(). This is not recommended as it will capture uncalibrated raw data. Sending uncalibrated remote control signals is often misidentified.
The UpyIrTx class is responsible for the send process. The infrared remote control signal is transmitted based on the remote control reception signal data acquired by the above UpyIrRx object.
LED OFF time _______ _____ _____ LED OFF time
_____________| |____| |_________| |_________
If idle_level = 1
_____________ ____ _________ _________
|_______| |_____| |_____|
<- t0 ->< t1 >< t2 ><-- t3 -->< t4 > ... [usec]
ON time ON time ON time
signal_tuple = (t0, t1, t2, t3, t4)
The ON section is the PWM waveform. You can specify the PWM frequency and duty ratio.
__init__(ch, pin, freq=38000, duty=30, idle_level=0))
Parameters
ch: int
The channel number is 0-7. On the ESP32, this is the RMT peripheral channel number. On the RP2040, this is the state machine number of the PIO peripheral. Specify an unused number. If you haven't used it elsewhere, 0 is fine.
pin
A pin object (machine.Pin object) for the pin that outputs the transmitted signal. It is a microcomputer pin connected to TxPin in the above circuit.
freq: int *1
PWM frequency [Hz] in the ON section. The default value is 38000 [Hz].
duty: int *1
Duty ratio of PWM waveform in ON section 1-100 [%]. The default value is 30 [%].
idle_level: int *1
Logic level corresponding to infrared LED OFF 0/1 (Low with default 0)。 In the general transmission circuit example above, it will be Low (=0).
*1: In the case of RP2040 chip, this argument is invalid. If you want to change it, change the following constants in the source code UpyIrTx.py.
def pio_wave():
T = const(26) # Period: 1/38kHz*1M [us] (= OF_TIM + ON_TIM)
OF_TIM = const(18) # Duty(30%) off time [us]
OF_POR = const(0) # Idle level
ON_TIM = const(8) # Duty(30%) on time [us]
ON_POR = const(1) # not Idle level
send(signal_tuple: tuple) -> bool
The transmission signal is output according to the time list of the argument. It will be blocked until the transmission is completed.
Parameters
signal_tuple: tuple or list
Specify a tuple or list of time information. Use the remote control received signal data acquired by the above UpyIrRx object. The number of elements is limited to odd numbers.
Return
This is a program example when M5Stack ATOM and IR REMOTE UNIT are connected with a Grove connector. Although the M5Stack ATOM main unit contains an infrared transmission circuit, it is not practical because it can fly only a very short distance.
from machine import Pin
from UpyIrTx import UpyIrTx
from UpyIrRx import UpyIrRx
rx_pin = Pin(32, Pin.IN) # Pin No.32
rx = UpyIrRx(rx_pin)
tx_pin = Pin(26, Pin.OUT) # Pin No.26
tx = UpyIrTx(0, tx_pin) # 0ch
...
# If the remote control is transmitted to the receiving circuit
# within 3000 msec, the remote control signal is acquired.
rx.record(3000)
if rx.get_mode() == UpyIrRx.MODE_DONE_OK:
signal_list = rx.get_calibrate_list()
# ex) [430, 1290, 430, 430, 430, 860, ...]
else:
signal_list = []
...
if signal_list:
tx.send(signal_list)
...
In the attached demo application, along with the application software on the PC side, You can easily collect signals from the infrared remote controller and test the transmission.
--- caution ---
The main.py written to the microcomputer is automatically executed after the power is turned on. Inside main.py, the keystroke input () is in an infinite loop. In this state, writing the program to the microcomputer will be blocked. If you want to return to the REPL environment, use the terminal software for serial communication and enter a line feed after the q key. (Or Ctrl+c)
The demo program runs on a system with M5Stack ATOM and IR REMOTE UNIT connected via a Grove connector. Write the three files "main.py", "UpyIrRx.py", and "UpyIrTx.py" to the microcomputer. As in the REPL environment, connect the PC side and M5Stack with a USB cable.
If you want to use another ESP32 module, modify the source code as shown in main.py below.
Write the three files "main.py", "UpyIrRx.py", and "UpyIrTx.py" to the microcomputer. An external infrared transmitter / receiver circuit can be connected to any GPIO pin. In this example, Connect the output of the infrared remote control light receiving module to GPIO Pin.18, The infrared remote control transmission signal is connected to GPIO Pin.19.
If you want to use other pins, rewrite the following pin layout in the source code.
Modifications of main.py
_GROVE_PIN = {'ATOM': (32, 26),
'CORE2': (33, 32),
'BASIC': (22, 21),
'GRAY': (22, 21),
'FIRE': (22, 21),
'GO': (22, 21),
'Stick': (33, 32),
'Else': (18, 19)} # Rewrite (RxPin Number, TxPin Number)
_DEVICE = 'Else' # Rewrite 'Else'
_TX_IDLE_LEVEL = const(0) # Sender idle_level(Invalid when using RP2040)
_TX_FREQ = const(38000) # Sender modulation frequency(Invalid when using RP2040)
_TX_DUTY = const(30) # Sender duty ratio(Invalid when using RP2040)
_RX_IDLE_LEVEL = const(1) # Receiver idle_level
The application on the PC side is written in python. It has been confirmed to work on windows, Ubuntu, and Raspbian OS. It uses the GUI framework Tkinter.
Install python 3.8 or above.
Install serial communication library pySerial.
$ pip install pyserial
The python program consists of 6 files.
If you want to use a microcomputer board other than the sample example, modify the following part of communication.py. Specify the vendor ID (VID) and product ID (PID) of the USB device. These IDs can be easily found from your PC.
class Communication():
_DEFAULT_VID = 1027 # A unique USB VID is assigned to each microcomputer board.
_DEFAULT_PID = 24577 # Also USB PID
Type | VID | PID |
---|---|---|
M5Stack ATOM | 1027 | 24577 |
M5Stack Core2 | 4292 | 60000 |
Raspberry Pi Pico | 11914 | 5 |
Start the program $ python main.py
__sysytem__
key. Use it to comment on files.This is a json format text file. In dictionary format, the key is the key name of the remote control signal. Value is in dictionary format.
The value dictionary format consists of two keys, "signal" and "comment". A sample is illustrated below.
{"vol_up": {"signal": [430, 1290, 430, ...], "comment": "volume up"},
"ch1": {"signal": [430, 1290, 860, ...], "comment": "CH 1"},
...
}
Due to the limit of processing speed, sending and receiving remote control signals using micropython was difficult.
Especially for the generation of the transmission signal, the jitter is too severe for the waveform generation using the sleep process, and it is not practical. This library is limited to ESP32 and RP2040 chips, but is board-specific. I overcame it by using the function. Considering the convenience of micropython, even if you have such a hard time, it is worth making it into a library.
You can also use Home IoT in combination with WIFI. An automated system for air conditioning by timer processing is also practical. Make use of this library and have a fun electronic work life!