3 ##### [Main README](./README.md#1-ir-communication)
5 # 1. Hardware Requirements
7 The transmitter requires a Pyboard 1.x (not Lite), a Pyboard D or an ESP32.
8 Output is via an IR LED which needs a simple circuit to provide sufficient
9 current. Typically these need 50-100mA of drive to achieve reasonable range and
10 data integrity. A suitable 940nm LED is [this one](https://www.adafruit.com/product/387).
12 On the Pyboard the transmitter test script assumes pin X1 for IR output. It can
13 be changed, but it must support Timer 2 channel 1. Pins for pushbutton inputs
14 are arbitrary: X3 and X4 are used. The driver uses timers 2 and 5.
16 On ESP32 the demo uses pins 21 and 23 for IR output and pins 18 and 19 for
17 pushbuttons. These pins may be changed.
21 I use the following circuit which delivers just under 40mA to the diode. R2 may
22 be reduced for higher current.
23 
25 This alternative delivers a constant current of about 53mA if a higher voltage
26 than 5V is available. R4 determines the current value and may be reduced to
28 
30 The transistor type is not critical.
32 The driver assumes circuits as shown. Here the carrier "off" state is 0V,
33 which is the driver default. If using a circuit where "off" is required to be
34 3.3V, the class variable `active_high` should be set `False`.
38 The ESP32 RMT device does not currently support the carrier option. A simple
39 hardware gate is required to turn the IR LED on when both the carrier pin and
40 the RMT pin are high. A suitable circuit is below; the transistor type is not
42 
44 This simpler alternative uses MOSFETS, but the device type needs attention. The
45 chosen type has a low gate-source threshold voltage and low Rdson.
46 
48 # 2. Dependencies and installation
52 The device driver has no dependencies.
54 On ESP32 a firmware version >= V1.12 is required. The Loboris port is not
55 supported owing to the need for the RMT device.
57 The demo program requires `uasyncio` from the official library and `aswitch.py`
58 from [this repo](https://github.com/peterhinch/micropython-async).
62 The transmitter is a Python package. This minimises RAM usage: applications
63 only import the device driver for the protocol in use. Clone the repository to
64 the current directory of your PC with:
66 $ git clone https://github.com/peterhinch/micropython_ir
69 Copy the following to the target filesystem:
70 1. `ir_tx` Directory and contents.
72 The demo is of a 2-button remote controller with auto-repeat. It may be run by
75 from ir_tx.test import test
77 Instructions will be displayed at the REPL.
81 This is specific to Pyboard D, Pyboard 1.x (not Lite) and ESP32.
83 It implements a class for each supported protocol, namely `NEC`, `SONY_12`,
84 `SONY_15`, `SONY_20`, `RC5` and `RC6_M0`. Each class is subclassed from a
85 common abstract base class in `__init__.py`. The application instantiates the
86 appropriate class and calls the `transmit` method to send data.
88 #### Common to all classes
91 1. `pin` A Pin instance instantiated as an output. On a Pyboard this is a
92 `pyb.Pin` instance supporting Timer 2 channel 1: `X1` is employed by the test
93 script. On ESP32 any `machine.Pin` may be used. Must be connected to the IR
94 diode as described below.
95 2. `freq=default` The carrier frequency in Hz. The default for NEC is 38000,
96 Sony is 40000 and Philips is 36000.
97 3. `verbose=False` If `True` emits (a lot of) debug output.
100 1. `transmit(addr, data, toggle=0)` Integer args. `addr` and `data` are
101 normally 8-bit values and `toggle` is normally 0 or 1; details are protocol
102 dependent and are described below.
104 The `transmit` method is synchronous with rapid return. Actual transmission
105 occurs as a background process, on the Pyboard controlled by timers 2 and 5.
106 Execution times on a Pyboard 1.1 were 3.3ms for NEC, 1.5ms for RC5 and 2ms
110 1. `active_high=True` Normally the IR LED drive circuit turns the LED on if
111 the pin goes high. If it works with the opposite polarity the variable should
112 be set `False` before instantiating.
116 Class `NEC`. Example invocation:
118 from ir_tx.nec import NEC
121 This has an additional method `.repeat` (no args). This causes a repeat code to
122 be transmitted. Should be called every 108ms if a button is held down.
124 The NEC protocol accepts 8 or 16 bit addresses. In the former case, a 16 bit
125 value is transmitted comprising the 8 bit address and its one's complement,
126 enabling the receiver to perform a simple error check. The `NEC` class supports
127 these modes by checking the value of `addr` passed to `.transmit` and sending
128 the complement for values < 256.
130 A value passed in `toggle` is ignored.
134 Classes `SONY_12`, `SONY_15` and `SONY_20`. Example invocation:
136 from ir_tx.sony import SONY_15
139 The SIRC protocol supports three sizes, supported by the following classes:
140 1. 12 bit (7 data, 5 address) `SONY_12`
141 2. 15 bit (7 data, 8 address) `SONY_15`
142 3. 20 bit (7 data, 5 addresss, 8 extended) `SONY_20`
144 The `.transmit` method masks `addr` and `data` values to the widths listed
145 above. `toggle` is ignored except by `SONY_20` which treats it as the extended
150 Classes `RC5` and `RC6_M0`. Example invocation:
152 from ir_tx.philips import RC5
155 The RC-5 protocol supports a 5 bit address and 6 or 7 bit (RC5X) data. The
156 driver uses the appropriate mode depending on the `data` value provided.
158 The RC-6 protocol accepts 8 bit address and data values.
160 Both send a `toggle` bit which remains constant if a button is held down, but
161 changes when the button is released. The application should implement this
162 behaviour, setting the `toggle` arg of `.transmit` to 0 or 1 as required.
164 #### Microsoft MCE class
166 Class `MCE`. Example invocation:
168 from ir_tx.mce import MCE
171 There is a separate demo for the `MCE` class because of the need to send a
172 message on key release. It is run by issuing:
174 from ir_tx.mcetest import test
176 Instructions will be displayed at the REPL.
178 I have been unable to locate a definitive specification: the protocol was
179 analysed by a mixture of googling and experiment. Behaviour may change if I
180 acquire new information. The protocol is known as OrtekMCE and the remote
181 control is sold on eBay as VRC-1100.
183 The remote was designed for Microsoft Media Center and is used to control Kodi
184 on boxes such as the Raspberry Pi. With a suitable PC driver it can emulate a
185 PC keyboard and mouse. The mouse emulation uses a different protocol: the class
186 does not currently support it. Pressing mouse buttons and pad will cause the
187 error function (if provided) to be called.
189 This supports a 4 bit address, 6 bit data and 2 bit toggle. The latter should
190 have a value of 0 for the first message, 1 for repeat messages, and 2 for a
191 final message sent on button release.
193 The remaining four bits are a checksum which the driver creates. The algorithm
194 requires an initial 'seed' value which my testing proved to be 4. However the
195 only [documentation](http://www.hifi-remote.com/johnsfine/DecodeIR.html#OrtekMCE)
196 I could find stated that the value should be 3. I implemented this as a class
197 variable `MCE.init_cs=4`. This enables it to be changed if some receivers
200 # 4. Principle of operation
204 The classes inherit from the abstract base class `IR`. This has an array `.arr`
205 to contain the duration (in μs) of each carrier on or off period. The
206 `transmit` method calls a `tx` method of the subclass which populates this
207 array. This is done by two methods of the base class, `.append` and `.add`. The
208 former takes a list of times (in ) and appends them to the array. A bound
209 variable `.carrier` keeps track of the notional on/off state of the carrier:
210 this is required for bi-phase (manchester) codings.
212 The `.add` method takes a single μs time value and adds it to the last value
213 in the array: this pulse lengthening is used in bi-phase encodings.
215 On completion of the subclass `.tx`, `.transmit` appends a special `STOP` value
216 and initiates physical transmission which occurs in an interrupt context.
218 This is performed by two hardware timers initiated in the constructor. Timer 2,
219 channel 1 is used to configure the output pin as a PWM channel. Its frequency
220 is set in the constructor. The OOK is performed by dynamically changing the
221 duty ratio using the timer channel's `pulse_width_percent` method: this varies
222 the pulse width from 0 to a duty ratio passed to the constructor.
224 The duty ratio is changed by the Timer 5 callback `._cb`. This retrieves the
225 next duration from the array. If it is not `STOP` it toggles the duty cycle
226 and re-initialises T5 for the new duration.
230 The carrier is output continuously at the specified duty ratio. A pulse train
231 generated by the RMT instance drives a hardware gate such that the IR LED is
232 lit only when both carrier and RMT are high.
234 The carrier is generated by PWM instance `.pwm` running continuously. The ABC
235 constructor converts the 0-100 duty ratio specified by the subclass to the
236 0-1023 range used by ESP32.
240 In every case where I could find a specified figure it was 30%. I measured
241 that from a variety of remotes, and in every case it was close to that figure.