]> vault307.fbx.one Git - micorpython_ir.git/blob - TRANSMITTER.md
Prior to merge.
[micorpython_ir.git] / TRANSMITTER.md
1 # IR Transmitter
2
3 ##### [Main README](./README.md#1-ir-communication)
4
5 # 1. Hardware Requirements
6
7 The transmitter requires a Pyboard 1.x (not Lite), a Pyboard D or an ESP32.
8 Output is via an IR LED which will need a transistor 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).
11
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.
15
16 On ESP32 pin 23 is used for IR output and pins 18 and 19 for pushbuttons. The
17 ESP32 solution has limitations discussed in [section 5.2](./TRANSMITTER.md#52-esp32).
18
19 ## 1.1 Wiring
20
21 I use the following circuit which delivers just under 40mA to the diode. R2 may
22 be reduced for higher current.
23 ![Image](images/circuit.png)
24
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
27 increase power.
28 ![Image](images/circuit2.png)
29
30 The transistor type is not critical.
31
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 constant `_SPACE` in `ir_tx.__init__.py` should be changed to 100.
35
36 # 2. Installation
37
38 The transmitter is a Python package. This minimises RAM usage: applications
39 only import the device driver for the protocol in use.
40
41 Copy the following to the target filesystem:
42 1. `ir_tx` Directory and contents.
43
44 The device driver has no dependencies.
45
46 The demo program requires `uasyncio` from the official library and `aswitch.py`
47 from [this repo](https://github.com/peterhinch/micropython-async). The demo is
48 of a 2-button remote controller with auto-repeat. It may be run by issuing:
49
50 ```python
51 from ir_tx.test import test
52 ```
53 Instructions will be displayed at the REPL.
54
55 # 3. The driver
56
57 This is specific to Pyboard D, Pyboard 1.x (not Lite) and ESP32.
58
59 It implements a class for each supported protocol, namely `NEC`, `SONY_12`,
60 `SONY_15`, `SONY_20`, `RC5` and `RC6_M0`. Each class is subclassed from a
61 common abstract base class in `__init__.py`. The application instantiates the
62 appropriate class and calls the `transmit` method to send data.
63
64 The ESP32 platform is marginal in this application because of imprecision in
65 its timing. The Philips protocols are unsupported as they require unachievable
66 levels of precision. Test results are discussed [here](./TRANSMITTER.md#52-esp32).
67
68 Constructor
69 All constructors take the following args:
70 1. `pin` An initialised `pyb.Pin` instance supporting Timer 2 channel 1: `X1`
71 is employed by the test script. Must be connected to the IR diode as described
72 below.
73 2. `freq=default` The carrier frequency in Hz. The default for NEC is 38000,
74 Sony is 40000 and Philips is 36000.
75 3. `verbose=False` If `True` emits debug output.
76
77 Method:
78 1. `transmit(addr, data, toggle=0)` Integer args. `addr` and `data` are
79 normally 8-bit values and `toggle` is normally 0 or 1; details are protocol
80 dependent and are described below.
81
82 The `transmit` method is synchronous with rapid return. Actual transmission
83 occurs as a background process, on the Pyboard controlled by timers 2 and 5.
84 Execution times on a Pyboard 1.1 were 3.3ms for NEC, 1.5ms for RC5 and 2ms
85 for RC6.
86
87 #### NEC class
88
89 This has an additional method `.repeat` (no args). This causes a repeat code to
90 be transmitted. Should be called every 108ms if a button is held down.
91
92 The NEC protocol accepts 8 or 16 bit addresses. In the former case, a 16 bit
93 value is transmitted comprising the 8 bit address and its one's complement,
94 enabling the receiver to perform a simple error check. The `NEC` class supports
95 these modes by checking the value of `addr` passed to `.transmit` and sending
96 the complement for 8 bit values.
97
98 `toggle` is ignored.
99
100 #### Sony classes
101
102 The SIRC protocol supports three sizes, supported by the following classes:
103 1. 12 bit (7 data, 5 address) `SONY_12`
104 2. 15 bit (7 data, 8 address) `SONY_15`
105 3. 20 bit (7 data, 5 addresss, 8 extended) `SONY_20`
106
107 The `.transmit` method masks `addr` and `data` values to the widths listed
108 above. `toggle` is ignored except by `SONY_20` which treats it as the extended
109 value.
110
111 #### Philips classes
112
113 The RC-5 protocol supports a 5 bit address and 6 or 7 bit (RC5X) data. The
114 driver uses the appropriate mode depending on the `data` value provided.
115
116 The RC-6 protocol accepts 8 bit address and data values.
117
118 Both send a `toggle` bit which remains constant if a button is held down, but
119 changes when the button is released. The application should implement this
120 behaviour, setting the `toggle` arg of `.transmit` to 0 or 1 as required.
121
122 # 4. Test results
123
124 # 5. Principle of operation
125
126 ## 5.1 Pyboard
127
128 The classes inherit from the abstract base class `IR`. This has an array `.arr`
129 to contain the duration (in μs) of each carrier on or off period. The
130 `transmit` method calls a `tx` method of the subclass which populates this
131 array. This is done by two methods of the base class, `.append` and `.add`. The
132 former takes a list of times (in μs) and appends them to the array. A bound
133 variable `.carrier` keeps track of the notional on/off state of the carrier:
134 this is required for bi-phase (manchester) codings.
135
136 The `.add` method takes a single μs time value and adds it to the last value
137 in the array: this pulse lengthening is used in bi-phase encodings.
138
139 On completion of the subclass `.tx`, `.transmit` appends a special `STOP` value
140 and initiates physical transmission which occurs in an interrupt context.
141
142 This is performed by two hardware timers initiated in the constructor. Timer 2,
143 channel 1 is used to configure the output pin as a PWM channel. Its frequency
144 is set in the constructor. The OOK is performed by dynamically changing the
145 duty ratio using the timer channel's `pulse_width_percent` method: this varies
146 the pulse width from 0 to a duty ratio passed to the constructor. The NEC
147 protocol defaults to 50%, the Sony and Philips ones to 30%.
148
149 The duty ratio is changed by the Timer 5 callback `._cb`. This retrieves the
150 next duration from the array. If it is not `STOP` it toggles the duty cycle
151 and re-initialises T5 for the new duration.
152
153 ## 5.2 ESP32
154
155 This is something of a hack because my drivers work with standard firmware.
156
157 A much better solution will be possible when the `esp32.RMT` class supports the
158 `carrier` option. A fork supporting this is
159 [here](https://github.com/mattytrentini/micropython). You may want to adapt the
160 base class to use this fork: it should be easy and would produce a solution
161 capable of handling all protocols.
162
163 A consequence of this hack is that timing is imprecise. In testing NEC
164 protocols were reliable. Sony delivered some erroneous bitsreams but may be
165 usable. Philips protocols require timing precision which is unachievable; these
166 are unsupported and an exception will be thrown on an attempt to instantiate a
167 Philips class on an ESP32.
168
169 The ABC stores durations in Hz rather than in μs. This is because the `period`
170 arg of `Timer.init` expects an integer number of ms. Passing a `freq` value
171 enables slightly higher resolution timing. In practice timing lacks precision
172 with the code having a hack which subtracts a nominal amount from each value to
173 compensate for the typical level of overrun.
174
175 The carrier is generated by PWM instance `.pwm` with its duty cycle controlled
176 by software timer `._tim` in a similar way to the Pyboard Timer 5 described
177 above. The ESP32 duty value is in range 0-1023 as against 0-100 on the Pyboard.
178
179 # 6. References
180
181 [General information about IR](https://www.sbprojects.net/knowledge/ir/)
182
183 The NEC protocol:
184 [altium](http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol)
185 [circuitvalley](http://www.circuitvalley.com/2013/09/nec-protocol-ir-infrared-remote-control.html)
186
187 Philips protocols:
188 [RC5](https://en.wikipedia.org/wiki/RC-5)
189 [RC5](https://www.sbprojects.net/knowledge/ir/rc5.php)
190 [RC6](https://www.sbprojects.net/knowledge/ir/rc6.php)
191
192 Sony protocol:
193 [SIRC](https://www.sbprojects.net/knowledge/ir/sirc.php)