]> vault307.fbx.one Git - micorpython_ir.git/blobdiff - README.md
Merge pull request #8 from jetannenbaum/master
[micorpython_ir.git] / README.md
index d90a74f0145a9d61606ef4f60022ab529fc7badd..48259c5f25034e06ae3c675d27b87bae22be717c 100644 (file)
--- a/README.md
+++ b/README.md
 
 This repo provides a driver to receive from IR (infra red) remote controls and
 a driver for IR "blaster" apps. The device drivers are nonblocking. They do not
-require `uasyncio` but are compatible with it.
+require `uasyncio` but are compatible with it, and are designed for standard
+firmware builds.
+
+The receiver is cross platform and has been tested on Pyboard, ESP8266, ESP32
+and Raspberry Pi Pico.
+
+In a typical use case the receiver is employed at the REPL to sniff the address
+and data values associated with buttons on a remote control. The transmitter is
+then used in an application to send those codes, emulating the remote control.
+
+Other use cases involve running the receiver in an application. This enables an
+IR remote to control a device such as a robot. This may be problematic on some
+platforms. Please see [section 4](./README.md#4-receiver-limitations).
+
+## Raspberry Pi Pico note
+
+Early firmware has [this issue](https://github.com/micropython/micropython/issues/6866)
+affecting USB communication with some PC's. This is now fixed. Please ensure
+you are using up to date firmware.
+
+#### [Receiver docs](./RECEIVER.md)
+
+The transmitter driver is compatible with Pyboard (1.x and D series) and ESP32.
+ESP8266 is unsupported; it seems incapable of generating the required signals.
+
+#### [Transmitter docs](./TRANSMITTER.md)
 
 # 1. IR communication
 
 IR communication uses a carrier frequency to pulse the IR source. Modulation
 takes the form of OOK (on-off keying). There are multiple protocols and at
-least two options for carrier frequency, namely 36KHz and 38KHz.
+least three options for carrier frequency: 36, 38 and 40KHz.
 
-The drivers support the NEC protocol and two Philips protocols, namely RC-5 and
-RC-6 mode 0. In the case of the transmitter the carrier frequency is a runtime
-parameter: any value may be specified. The receiver uses a hardware demodulator
-which must be specified for the correct frequency. The receiver device driver
-sees the demodulated signal and is hence carrier frequency agnostic.
+In the case of the transmitter the carrier frequency is a runtime parameter:
+any value may be specified. The receiver uses a hardware demodulator which
+should be purchased for the correct frequency. The receiver device driver sees
+the demodulated signal and is hence carrier frequency agnostic.
+
+Remotes transmit an address and a data byte, plus in some cases an extra value.
+The address denotes the physical device being controlled. The data defines the
+button on the remote. Provision usually exists for differentiating between a
+button repeatedly pressed and one which is held down; the mechanism is protocol
+dependent.
+
+# 2. Supported protocols
+
+The drivers support NEC and Sony protocols plus two Philips protocols, namely
+RC-5 and RC-6 mode 0. There is also support for the OrtekMCE protocol used on
+VRC-1100 remotes. These originally supported Microsoft Media Center but can be
+used to control Kodi and (with a suitable receiver) to emulate a PC keyboard.
 
 Examining waveforms from various remote controls it is evident that numerous
 protocols exist. Some are doubtless proprietary and undocumented. The supported
 protocols are those for which I managed to locate documentation. My preference
-is for the NEC version. It has conservative timing and ample scope for error
+is for the NEC version. It has conservative timing and good provision for error
 detection. RC-5 has limited error detection, and RC-6 mode 0 has rather fast
-timing: I doubt that detection can be accomplished on targets slower than a
-Pyboard.
+timing.
 
 A remote using the NEC protocol is [this one](https://www.adafruit.com/products/389).
 
-Remotes normally transmit an address and a data byte. The address denotes the
-physical device being controlled. The data is associated with the button on the
-remote. Provision exists for differentiating between a button repeatedly
-pressed and one which is held down; the mechanism is protocol dependent.
+# 3. Hardware Requirements
 
-# 2. Hardware Requirements
+These are discussed in detail in the relevant docs; the following provides an
+overview.
 
 The receiver is cross-platform. It requires an IR receiver chip to demodulate
 the carrier. The chip must be selected for the frequency in use by the remote.
 For 38KHz devices a receiver chip such as the Vishay TSOP4838 or the
 [adafruit one](https://www.adafruit.com/products/157) is required. This
 demodulates the 38KHz IR pulses and passes the demodulated pulse train to the
-microcontroller. The tested chip returns a 0 level on carrier detect, but the
-driver design should ensure operation regardless of sense.
+microcontroller.
 
-The pin used to connect the decoder chip to the target is arbitrary but the
-test programs assume pin X3 on the Pyboard, pin 13 on the ESP8266 and pin 23 on
-ESP32.
-
-The transmitter requires a Pyboard 1.x (not Lite) or a Pyboard D. Output is via
-an IR LED which will normally need a transistor to provide sufficient current.
-Typically these need 50-100mA of drive to achieve reasonable range and data
-integrity. A suitable LED is [this one](https://www.adafruit.com/product/387).
-
-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.
-
-# 3. Installation
+In my testing a 38KHz demodulator worked with 36KHz and 40KHz remotes, but this
+is obviously neither guaranteed nor optimal.
 
-On import, demos print an explanation of how to run them.
-
-## 3.1 Receiver
-
-Copy the following files to the target filesystem:
- 1. `ir_rx.py` The receiver device driver.
- 2. `ir_rx_test.py` Demo of a receiver.
-
-There are no dependencies.
-
-The demo can be used to characterise IR remotes. It displays the codes returned
-by each button. This can aid in the design of receiver applications. When the
-demo runs, the REPL prompt reappears: this is because it sets up an ISR context
-and returns. Press `ctrl-d` to cancel it. A real application would run code
-after initialising reception so this behaviour would not occur.
+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
+current. The ESP32 requires an extra transistor to work as a transmitter.
 
-## 3.2 Transmitter
+## 3.1 Carrier frequencies
 
-Copy the following files to the Pyboard filesystem:
- 1. `ir_tx.py` The transmitter device driver.
- 2. `ir_tx_test.py` Demo of a 2-button remote controller.
+These are as follows. The Samsung and Panasonic remotes appear to use
+proprietary protocols and are not supported by these drivers.
 
-The device driver has no dependencies. The test program requires `uasyncio`
-from the official library and `aswitch.py` from
-[this repo](https://github.com/peterhinch/micropython-async).
-
-# 4. Receiver
-
-This implements a class for each supported protocol, namely `NEC_IR`, `RC5_IR`
-and `RC6_M0`. Applications should instantiate the appropriate class with a
-callback. The callback will run whenever an IR pulsetrain is received.
-
-Constructor:  
-`NEC_IR` args: `pin`, `callback`, `extended=True`, `*args`  
-`RC5_IR` and `RC6_M0`: args `pin`, `callback`, `*args`  
-Args:  
- 1. `pin` is a `machine.Pin` instance configured as an input, connected to the
- IR decoder chip.  
- 2. `callback` is the user supplied callback (see below).
- 3. `extended` is an NEC specific boolean. Remotes using the NEC protocol can
- send 8 or 16 bit addresses. If `True` 16 bit addresses are assumed - an 8 bit
- address will be correctly received. Set `False` to enable extra error checking
- for remotes that return an 8 bit address.
- 4. `*args` Any further args will be passed to the callback.  
-
-The callback takes the following args:  
- 1. `data` Integer value fom the remote. A negative value indicates an error
- except for the value of -1 which signifies an NEC repeat code (see below).
- 2. `addr` Address from the remote
- 3. `ctrl` 0 in the case of NEC. Philips protocols toggle this bit on repeat
- button presses. If the button is held down the bit is not toggled. The
- transmitter demo implements this behaviour.
- 4. Any args passed to the constructor.
-
-Class variable:  
- 1. `verbose=False` If `True` emits debug output.
-
-# 4.1 Errors
-
-IR reception is inevitably subject to errors, notably if the remote is operated
-near the limit of its range, if it is not pointed at the receiver or if its
-batteries are low. So applications must check for, and usually ignore, errors.
-These are flagged by data values < `REPEAT` (-1).
-
-On the ESP8266 there is a further source of errors. This results from the large
-and variable interrupt latency of the device which can exceed the pulse
-duration. This causes pulses to be missed. This tendency is slightly reduced by
-running the chip at 160MHz.
-
-In general applications should provide user feedback of correct reception.
-Users tend to press the key again if the expected action is absent.
-
-Data values passed to the callback are normally positive. Negative values
-indicate a repeat code or an error.
-
-`REPEAT` A repeat code was received.
-
-Any data value < `REPEAT` denotes an error. In general applications do not
-need to decode these, but they may be of use in debugging. For completeness
-they are listed below.
-
-`BADSTART` A short (<= 4ms) start pulse was received. May occur due to IR
-interference, e.g. from fluorescent lights. The TSOP4838 is prone to producing
-200µs pulses on occasion, especially when using the ESP8266.  
-`BADBLOCK` A normal data block: too few edges received. Occurs on the ESP8266
-owing to high interrupt latency.  
-`BADREP` A repeat block: an incorrect number of edges were received.  
-`OVERRUN` A normal data block: too many edges received.  
-`BADDATA` Data did not match check byte.  
-`BADADDR` Where `extended` is `False` the 8-bit address is checked
-against the check byte. This code is returned on failure.  
-
-# 4.2 Receiver platforms
-
-The NEC protocol has been tested against Pyboard, ESP8266 and ESP32 targets.
-The Philips protocols - especially RC-6 - have tighter timing constraints. I
-have not yet tested these, but I anticipate problems.
-
-# 4.3 Principle of operation
-
-Protocol classes inherit from the abstract base class `IR_RX`. This uses a pin
-interrupt to store in an array the start and end times of pulses (in μs).
-Arrival of the first pulse triggers a software timer which runs for the
-expected duration of an IR block (`tblock`). When it times out its callback
-(`.decode`) decodes the data and calls the user callback. The use of a software
-timer ensures that `.decode` and the user callback can allocate.
-
-The size of the array and the duration of the timer are protocol dependent and
-are set by the subclasses. The `.decode` method is provided in the subclass.
-
-CPU times used by `.decode` (not including the user callback) were measured on
-a Pyboard D SF2W at stock frequency. They were NEC 1ms for normal data, 100μs
-for a repeat code. Philips codes: RC-5 900μs, RC-6 mode 0 5.5ms.
-
-# 5 Transmitter
-
-This is specific to Pyboard D and Pyboard 1.x (not Lite).
-
-It implements a class for each supported protocol, namely `NEC`, `RC5` and
-`RC6_M0`. The application instantiates the appropriate class and calls the
-`transmit` method to send data.
-
-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.
- 2. `freq=default` The carrier frequency in Hz. The default for NEC is 38000,
- and for Philips is 36000.
- 3. `verbose=False` If `True` emits debug output.
-
-Method:
- 1. `transmit(addr, data, toggle=0)` Integer args. `addr` and `data` are
- normally 8-bit values and `toggle` is 0 or 1.  
- In the case of NEC, if an address < 256 is passed, normal mode is assumed and
- the complementary value is appended. 16-bit values are transmitted as extended
- addresses.  
- In the case of NEC the `toggle` value is ignored. For Philips protocols it
- should be toggled each time a button is pressed, and retained if the button is
- held down. The test program illustrates a way to do this.
-
-The `transmit` method is synchronous with rapid return. Actual transmission
-occurs as a background process, controlled by timers 2 and 5. Execution times
-on a Pyboard 1.1 were 3.3ms for NEC, 1.5ms for RC5 and 2ms for RC6.
-
-# 5.1 Wiring
-
-I use the following circuit which delivers just under 40mA to the diode. R2 may
-be reduced for higher current.  
-![Image](images/circuit.png)
-
-This alternative delivers a constant current of about 53mA if a higher voltage
-than 5V is available. R4 determines the current value and may be reduced to
-increase power.  
-![Image](images/circuit2.png)
-
-The transistor type is not critical.
-
-These circuits assume 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.py` should be changed to 100.
-
-# 5.2 Principle of operation
-
-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 in the subclass which populates this
-array. On completion `transmit` appends a special `STOP` value and initiates
-physical transmission which occurs in an interrupt context.
-
-This is performed by two hardware timers initiated in the constructor. Timer 2,
-channel 1 is used to configure the output pin as a PWM channel. Its frequency
-is set in the constructor. The OOK is performed by dynamically changing the
-duty ratio using the timer channel's `pulse_width_percent` method: this varies
-the pulse width from 0 to a duty ratio passed to the constructor. The NEC
-protocol defaults to 50%, the Philips ones to 30%.
-
-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.
-
-The `IR.append` enables times to be added to the array, keeping track of the
-notional carrier on/off state for biphase generation. The `IR.add` method
-facilitates lengthening a pulse as required in the biphase sequences used in
-Philips protocols.
-
-# 6. References
-
-The NEC protocol is described in these references:  
-[altium](http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol)  
-[circuitvalley](http://www.circuitvalley.com/2013/09/nec-protocol-ir-infrared-remote-control.html)
+| Protocol  | F KHz | How found     | Support |
+|:---------:|:-----:|:-------------:|:-------:|
+| NEC       | 38    | Measured      | Y       |
+| RC-5 RC-6 | 36    | Spec/measured | Y       |
+| Sony      | 40    | Spec/measured | Y       |
+| MCE       | 38    | Measured      | Y       | 
+| Samsung   | 38    | Measured      | N       |
+| Panasonic | 36.3  | Measured      | N       |
 
-The Philips protocols may be found in these refs:  
-[RC5](https://en.wikipedia.org/wiki/RC-5)  
-[RC6](https://www.sbprojects.net/knowledge/ir/rc6.php)
+# 4. Receiver limitations
 
-Sony protocol (future use):  
-[SIRC](https://www.sbprojects.net/knowledge/ir/sirc.php)
+The receiver uses a pin interrupt and depends on a quick response to a state
+change on the pin. This is guaranteed on platforms which support hard IRQ's
+such as the Pyboard and the RP4 Pico. The ESP32 and ESP8266 only support soft
+IRQ's. This means that, if code such as WiFi communication is running
+concurrently, reliable reception may be problematic.
 
-# Appendix 1 NEC Protocol description
+# 5. References
 
-A normal burst comprises exactly 68 edges, the exception being a repeat code
-which has 4. An incorrect number of edges is treated as an error. All bursts
-begin with a 9ms pulse. In a normal code this is followed by a 4.5ms space; a
-repeat code is identified by a 2.25ms space. A data burst lasts for 67.5ms.
+Sources of information about IR protocols. The `sbprojects.net` site is an
+excellent resource.  
+[General information about IR](https://www.sbprojects.net/knowledge/ir/)
 
-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.
+The NEC protocol:  
+[altium](http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol)  
+[circuitvalley](http://www.circuitvalley.com/2013/09/nec-protocol-ir-infrared-remote-control.html)
+[sbprojects.net](https://www.sbprojects.net/knowledge/ir/nec.php)
 
-In 8 bit address mode the complement of the address and data values is sent to
-provide error checking. This also ensures that the number of 1's and 0's in a
-burst is constant, giving a constant burst length of 67.5ms. In extended
-address mode this constancy is lost. The burst length can (by my calculations)
-run to 76.5ms.
+Philips protocols:  
+[RC5 Wikipedia](https://en.wikipedia.org/wiki/RC-5)  
+[RC5 sbprojects.net](https://www.sbprojects.net/knowledge/ir/rc5.php)  
+[RC6 sbprojects.net](https://www.sbprojects.net/knowledge/ir/rc6.php)
 
-A pin interrupt records the time of every state change (in µs). The first
-interrupt in a burst sets an event, passing the time of the state change. A
-coroutine waits on the event, yields for the duration of a data burst, then
-decodes the stored data before calling the user-specified callback.
+Sony protocol:  
+[SIRC sbprojects.net](https://www.sbprojects.net/knowledge/ir/sirc.php)
 
-Passing the time to the `Event` instance enables the coro to compensate for
-any asyncio latency when setting its delay period.
+MCE protocol:  
+[OrtekMCE](http://www.hifi-remote.com/johnsfine/DecodeIR.html#OrtekMCE)
 
-The algorithm promotes interrupt handler speed over RAM use: the 276 bytes used
-for the data array could be reduced to 69 bytes by computing and saving deltas
-in the interrupt service routine.
+IR decoders (C sourcecode):  
+[in the Linux kernel](https://github.com/torvalds/linux/tree/master/drivers/media/rc)