X-Git-Url: https://vault307.fbx.one/gitweb/micorpython_ir.git/blobdiff_plain/36140aa568d4a538adafb03e575b26de8a0784ef..3618d67b4e6c865ea946e2011acc5dee8b3f8ecb:/TRANSMITTER.md?ds=inline diff --git a/TRANSMITTER.md b/TRANSMITTER.md index 3478ba8..24cd244 100644 --- a/TRANSMITTER.md +++ b/TRANSMITTER.md @@ -5,7 +5,7 @@ # 1. Hardware Requirements The transmitter requires a Pyboard 1.x (not Lite), a Pyboard D or an ESP32. -Output is via an IR LED which will need a transistor to provide sufficient +Output is via an IR LED which needs a simple circuit to provide sufficient current. Typically these need 50-100mA of drive to achieve reasonable range and data integrity. A suitable 940nm LED is [this one](https://www.adafruit.com/product/387). @@ -13,10 +13,10 @@ On the Pyboard the transmitter test script assumes pin X1 for IR output. It can be changed, but it must support Timer 2 channel 1. Pins for pushbutton inputs are arbitrary: X3 and X4 are used. The driver uses timers 2 and 5. -On ESP32 pin 23 is used for IR output and pins 18 and 19 for pushbuttons. The -ESP32 solution has limitations discussed in [section 5.2](./TRANSMITTER.md#52-esp32). +On ESP32 the demo uses pins 21 and 23 for IR output and pins 18 and 19 for +pushbuttons. These pins may be changed. -## 1.1 Wiring +## 1.1 Pyboard Wiring I use the following circuit which delivers just under 40mA to the diode. R2 may be reduced for higher current. @@ -33,20 +33,37 @@ The driver assumes circuits as shown. Here the carrier "off" state is 0V, which is the driver default. If using a circuit where "off" is required to be 3.3V, the constant `_SPACE` in `ir_tx.__init__.py` should be changed to 100. -# 2. Installation +## 1.2 ESP32 Wiring -The transmitter is a Python package. This minimises RAM usage: applications -only import the device driver for the protocol in use. +The ESP32 RMT device does not currently support the carrier option. A simple +hardware gate is required to turn the IR LED on when both the carrier pin and +the RMT pin are high. A suitable circuit is below. +![Image](images/gate.png) -Copy the following to the target filesystem: - 1. `ir_tx` Directory and contents. +The transistor type is not critical. + +# 2. Dependencies and installation + +## 2.1 Dependencies The device driver has no dependencies. +On ESP32 a firmware version >= V1.12 is required. The Loboris port is not +supported owing to the need for the RMT device. + The demo program requires `uasyncio` from the official library and `aswitch.py` -from [this repo](https://github.com/peterhinch/micropython-async). The demo is -of a 2-button remote controller with auto-repeat. It may be run by issuing: +from [this repo](https://github.com/peterhinch/micropython-async). +## 2.2 Installation + +The transmitter is a Python package. This minimises RAM usage: applications +only import the device driver for the protocol in use. + +Copy the following to the target filesystem: + 1. `ir_tx` Directory and contents. + +The demo is of a 2-button remote controller with auto-repeat. It may be run by +issuing: ```python from ir_tx.test import test ``` @@ -61,18 +78,16 @@ It implements a class for each supported protocol, namely `NEC`, `SONY_12`, common abstract base class in `__init__.py`. The application instantiates the appropriate class and calls the `transmit` method to send data. -The ESP32 platform is marginal in this application because of imprecision in -its timing. The Philips protocols are unsupported as they require unachievable -levels of precision. Test results are discussed [here](./TRANSMITTER.md#52-esp32). +#### Common to all classes -Constructor -All constructors take the following args: - 1. `pin` An initialised `pyb.Pin` instance supporting Timer 2 channel 1: `X1` - is employed by the test script. Must be connected to the IR diode as described - below. +Constructor args: + 1. `pin` A Pin instance instantiated as an output. On a Pyboard this is a + `pyb.Pin` instance supporting Timer 2 channel 1: `X1` is employed by the test + script. On ESP32 any `machine.Pin` may be used. Must be connected to the IR + diode as described below. 2. `freq=default` The carrier frequency in Hz. The default for NEC is 38000, Sony is 40000 and Philips is 36000. - 3. `verbose=False` If `True` emits debug output. + 3. `verbose=False` If `True` emits (a lot of) debug output. Method: 1. `transmit(addr, data, toggle=0)` Integer args. `addr` and `data` are @@ -93,9 +108,9 @@ The NEC protocol accepts 8 or 16 bit addresses. In the former case, a 16 bit value is transmitted comprising the 8 bit address and its one's complement, enabling the receiver to perform a simple error check. The `NEC` class supports these modes by checking the value of `addr` passed to `.transmit` and sending -the complement for 8 bit values. +the complement for values < 256. -`toggle` is ignored. +A value passed in `toggle` is ignored. #### Sony classes @@ -119,17 +134,15 @@ Both send a `toggle` bit which remains constant if a button is held down, but changes when the button is released. The application should implement this behaviour, setting the `toggle` arg of `.transmit` to 0 or 1 as required. -# 4. Test results +# 4. Principle of operation -# 5. Principle of operation - -## 5.1 Pyboard +## 4.1 Pyboard The classes inherit from the abstract base class `IR`. This has an array `.arr` to contain the duration (in μs) of each carrier on or off period. The `transmit` method calls a `tx` method of the subclass which populates this array. This is done by two methods of the base class, `.append` and `.add`. The -former takes a list of times (in μs) and appends them to the array. A bound +former takes a list of times (in ) and appends them to the array. A bound variable `.carrier` keeps track of the notional on/off state of the carrier: this is required for bi-phase (manchester) codings. @@ -150,33 +163,17 @@ The duty ratio is changed by the Timer 5 callback `._cb`. This retrieves the next duration from the array. If it is not `STOP` it toggles the duty cycle and re-initialises T5 for the new duration. -## 5.2 ESP32 - -This is something of a hack because my drivers work with standard firmware. - -A much better solution will be possible when the `esp32.RMT` class supports the -`carrier` option. A fork supporting this is -[here](https://github.com/mattytrentini/micropython). You may want to adapt the -base class to use this fork: it should be easy and would produce a solution -capable of handling all protocols. - -A consequence of this hack is that timing is imprecise. In testing NEC -protocols were reliable. Sony delivered some erroneous bitsreams but may be -usable. Philips protocols require timing precision which is unachievable; these -are unsupported and an exception will be thrown on an attempt to instantiate a -Philips class on an ESP32. +## 4.2 ESP32 -The ABC stores durations in Hz rather than in μs. This is because the `period` -arg of `Timer.init` expects an integer number of ms. Passing a `freq` value -enables slightly higher resolution timing. In practice timing lacks precision -with the code having a hack which subtracts a nominal amount from each value to -compensate for the typical level of overrun. +The carrier is output continuously at the specified duty ratio. A pulse train +generated by the RMT instance drives a hardware gate such that the IR LED is +lit only when both carrier and RMT are high. -The carrier is generated by PWM instance `.pwm` with its duty cycle controlled -by software timer `._tim` in a similar way to the Pyboard Timer 5 described -above. The ESP32 duty value is in range 0-1023 as against 0-100 on the Pyboard. +The carrier is generated by PWM instance `.pwm` running continuously. The ABC +constructor converts the 0-100 duty ratio specified by the subclass to the +0-1023 range used by ESP32. -# 6. References +# 5. References [General information about IR](https://www.sbprojects.net/knowledge/ir/)