]> vault307.fbx.one Git - micorpython_ir.git/blobdiff - TRANSMITTER.md
Add MCE. Fix bug with RC5X.
[micorpython_ir.git] / TRANSMITTER.md
index 88c3ed794b8b53e973565784d0398e3a348aa279..4f15c656e190e56494ff0a6f3f76593f7a3bf445 100644 (file)
@@ -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.  
@@ -31,22 +31,46 @@ The transistor type is not critical.
 
 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.
+3.3V, the class variable `active_high` should be set `False`.
 
-# 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; the transistor type is not
+critical.  
+![Image](images/gate.png)
 
-Copy the following to the target filesystem:
- 1. `ir_tx` Directory and contents.
+This simpler alternative uses MOSFETS, but the device type needs attention. The
+chosen type has a low gate-source threshold voltage and low Rdson.  
+![Image](images/gate_mosfet.png)
+
+# 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. Clone the repository to
+the current directory of your PC with:
+```bash
+$ git clone https://github.com/peterhinch/micropython_ir
+```
 
+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,10 +85,6 @@ 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 args:  
@@ -86,8 +106,18 @@ occurs as a background process, on the Pyboard 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.
 
+Class variable:
+ 1. `active_high=True` Normally the IR LED drive circuit turns the LED on if
+ the pin goes high. If it works with the opposite polarity the variable should
+ be set `False` before instantiating.
+
 #### NEC class
 
+Class `NEC`. Example invocation:
+```python
+from ir_tx.nec import NEC
+```
+
 This has an additional method `.repeat` (no args). This causes a repeat code to
 be transmitted. Should be called every 108ms if a button is held down.
 
@@ -101,6 +131,11 @@ A value passed in `toggle` is ignored.
 
 #### Sony classes
 
+Classes `SONY_12`, `SONY_15` and `SONY_20`. Example invocation:
+```python
+from ir_tx.sony import SONY_15
+```
+
 The SIRC protocol supports three sizes, supported by the following classes:
  1. 12 bit (7 data, 5 address) `SONY_12`
  2. 15 bit (7 data, 8 address) `SONY_15`
@@ -112,8 +147,10 @@ value.
 
 #### Philips classes
 
-These are only supported on Pyboard hosts. An `RuntimeError` will be thrown on
-an attempt to instantiate a Philips class on an ESP32.
+Classes `RC5` and `RC6_M0`. Example invocation:
+```python
+from ir_tx.philips import RC5
+```
 
 The RC-5 protocol supports a 5 bit address and 6 or 7 bit (RC5X) data. The
 driver uses the appropriate mode depending on the `data` value provided.
@@ -124,17 +161,51 @@ 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
+#### Microsoft MCE class
+
+Class `MCE`. Example invocation:
+```python
+from ir_tx.mce import MCE
+# MCE.init_cs = 3
+```
+There is a separate demo for the `MCE` class because of the need to send a
+message on key release. It is run by issuing:
+```python
+from ir_tx.mcetest import test
+```
+Instructions will be displayed at the REPL.
+
+I have been unable to locate a definitive specification: the protocol was
+analysed by a mixture of googling and experiment. Behaviour may change if I
+acquire new information. The protocol is known as OrtekMCE and the remote
+control is sold on eBay as VRC-1100.
 
-# 5. Principle of operation
+The remote was designed for Microsoft Media Center and is used to control Kodi
+on boxes such as the Raspberry Pi. With a suitable PC driver it can emulate a
+PC keyboard and mouse. The mouse emulation uses a different protocol: the class
+does not currently support it. Pressing mouse buttons and pad will cause the
+error function (if provided) to be called.
 
-## 5.1 Pyboard
+This supports a 4 bit address, 6 bit data and 2 bit toggle. The latter should
+have a value of 0 for the first message, 1 for repeat messages, and 2 for a
+final message sent on button release.
+
+The remaining four bits are a checksum which the driver creates. The algorithm
+requires an initial 'seed' value which my testing proved to be 4. However the
+only [documentation](http://www.hifi-remote.com/johnsfine/DecodeIR.html#OrtekMCE)
+I could find stated that the value should be 3. I implemented this as a class
+variable `MCE.init_cs=4`. This enables it to be changed if some receivers
+require 3.
+
+# 4. Principle of operation
+
+## 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.
 
@@ -148,50 +219,23 @@ 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 Sony and Philips ones to 30%.
+the pulse width from 0 to a duty ratio passed to the constructor.
 
 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.
-
-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 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.
-
-# 6. References
+## 4.2 ESP32
 
-[General information about IR](https://www.sbprojects.net/knowledge/ir/)
+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 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)
+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.
 
-Philips protocols:  
-[RC5](https://en.wikipedia.org/wiki/RC-5)  
-[RC5](https://www.sbprojects.net/knowledge/ir/rc5.php)  
-[RC6](https://www.sbprojects.net/knowledge/ir/rc6.php)
+## 4.3 Duty ratio
 
-Sony protocol:  
-[SIRC](https://www.sbprojects.net/knowledge/ir/sirc.php)
+In every case where I could find a specified figure it was 30%. I measured
+that from a variety of remotes, and in every case it was close to that figure.