]> vault307.fbx.one Git - micorpython_ir.git/commitdiff
Doc improvements. Add acquire script.
authorPeter Hinch <peter@hinch.me.uk>
Sun, 15 Mar 2020 18:43:35 +0000 (18:43 +0000)
committerPeter Hinch <peter@hinch.me.uk>
Sun, 15 Mar 2020 18:43:35 +0000 (18:43 +0000)
README.md
RECEIVER.md
TRANSMITTER.md
images/circuits.fzz
images/gate_mosfet.png [new file with mode: 0644]
ir_rx/__init__.py
ir_rx/acquire.py [new file with mode: 0644]

index 371615fbfb08d8fcc035c38773fd8ea9af470e32..44318d546476d17cccac2cbe812d0139d497aead 100644 (file)
--- a/README.md
+++ b/README.md
@@ -6,12 +6,14 @@ 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 and
 firmware builds.
 
 The receiver is cross platform and has been tested on Pyboard, ESP8266 and
-ESP32. The transmitter driver is compatible with Pyboard (1.x and D series) and
-also (subject to limitations) with ESP32. For the transmitter a Pyboard is
-recommended.
+ESP32.
 
 
-The transmitter is documented [here](./TRANSMITTER.md) and the receiver is
-[here](./RECEIVER.md).
+#### [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
 
 
 # 1. IR communication
 
index edd27dc6a607495be5b83e841604853a30cc04a6..12d9577ad02cb1a59ff4e5fb356e4adfba2f6a76 100644 (file)
@@ -21,26 +21,43 @@ On the WeMos D1 Mini the equivalent pin is D7.
 
 A remote using the NEC protocol is [this one](https://www.adafruit.com/products/389).
 
 
 A remote using the NEC protocol is [this one](https://www.adafruit.com/products/389).
 
-# 2. Installation and demo script
+# 2. Installation and demo scripts
 
 The receiver is a Python package. This minimises RAM usage: applications only
 
 The receiver is a Python package. This minimises RAM usage: applications only
-import the device driver for the protocol in use.
-
+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_rx` Directory and contents.
 
 There are no dependencies.
 
 
 Copy the following to the target filesystem:
  1. `ir_rx` Directory and contents.
 
 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. The demo
-prints "running" every 5 seconds and reports any data received from the remote.
+## 2.1 Test scripts
 
 
+The demo can be used to characterise IR remotes where the protocol is known. It
+displays the codes returned by each button. This can aid in the design of
+receiver applications. The demo prints "running" every 5 seconds and reports
+any data received from the remote.
 ```python
 from ir_rx.test import test
 ```
 Instructions will be displayed at the REPL.
 
 ```python
 from ir_rx.test import test
 ```
 Instructions will be displayed at the REPL.
 
+If the protocol in use is unknown, there are two options: trial and error with
+the above script or run the following:
+```python
+from ir_rx.acquire import test
+test()
+```
+This script is under development.
+
+It waits for a single burst from the remote and prints the timing of the pulses
+followed by its best guess at the protocol. It correctly identifies supported
+protocols, but can wrongly identify some unsupported proprietary protocols.
+
 # 3. The driver
 
 This implements a class for each supported protocol. Each class is subclassed
 # 3. The driver
 
 This implements a class for each supported protocol. Each class is subclassed
@@ -92,13 +109,14 @@ The user callback takes the following args:
 Bound variable:  
  1. `verbose=False` If `True` emits debug output.
 
 Bound variable:  
  1. `verbose=False` If `True` emits debug output.
 
-Method:
- 1. `error_function` Arg: a function taking a single `int` arg. If this is
- specified it will be called if an error occurs. The value corresponds to the
- error code (see below). Typical usage might be to provide some user feedback
- of incorrect reception although beware of occasional triggers by external
- events. In my testing the TSOP4838 produces 200µs pulses on occasion for no
- obvious reason. See [section 4](./RECEIVER.md#4-errors).
+Methods:
+ 1. `error_function` Arg: a function taking a single `int` arg. If specified
+ the function will be called if an error occurs. The arg value corresponds to
+ the error code. Typical usage might be to provide some user feedback of
+ incorrect reception although beware of occasional triggers by external events.
+ In my testing the TSOP4838 produces 200µs pulses on occasion for no obvious
+ reason. See [section 4](./RECEIVER.md#4-errors).
+ 2. `close` No args. Shuts down the pin and timer interrupts.
 
 A function is provided to print errors in human readable form. This may be
 invoked as follows:
 
 A function is provided to print errors in human readable form. This may be
 invoked as follows:
index 24cd24423b22c16bcd125372837dba657cbee883..c29a0ddbd840f0a9c924cbe500ee7db3e3365629 100644 (file)
@@ -37,10 +37,13 @@ which is the driver default. If using a circuit where "off" is required to be
 
 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 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 RMT pin are high. A suitable circuit is below; the transistor type is not
+critical.  
 ![Image](images/gate.png)
 
 ![Image](images/gate.png)
 
-The transistor type is not critical.
+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. Dependencies and installation
 
@@ -57,7 +60,11 @@ from [this repo](https://github.com/peterhinch/micropython-async).
 ## 2.2 Installation
 
 The transmitter is a Python package. This minimises RAM usage: applications
 ## 2.2 Installation
 
 The transmitter is a Python package. This minimises RAM usage: applications
-only import the device driver for the protocol in use.
+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.
 
 Copy the following to the target filesystem:
  1. `ir_tx` Directory and contents.
index ad48376633883df0873fd8ea95d6eae757485228..7ecee24c990016c6821d293cd215f0fc1567bb81 100644 (file)
Binary files a/images/circuits.fzz and b/images/circuits.fzz differ
diff --git a/images/gate_mosfet.png b/images/gate_mosfet.png
new file mode 100644 (file)
index 0000000..d2e137c
Binary files /dev/null and b/images/gate_mosfet.png differ
index 4b965245c326565c71ea7dfb816b48ac5222ebe1..0e7ad7f77026eb753c821ab5473a587e21860d2e 100644 (file)
@@ -32,6 +32,7 @@ class IR_RX():
     BADADDR = -7
 
     def __init__(self, pin, nedges, tblock, callback, *args):  # Optional args for callback
     BADADDR = -7
 
     def __init__(self, pin, nedges, tblock, callback, *args):  # Optional args for callback
+        self._pin = pin
         self._nedges = nedges
         self._tblock = tblock
         self.callback = callback
         self._nedges = nedges
         self._tblock = tblock
         self.callback = callback
@@ -41,10 +42,9 @@ class IR_RX():
 
         self._times = array('i',  (0 for _ in range(nedges + 1)))  # +1 for overrun
         if platform == 'esp32' or platform == 'esp32_LoBo':  # ESP32 Doesn't support hard IRQ
 
         self._times = array('i',  (0 for _ in range(nedges + 1)))  # +1 for overrun
         if platform == 'esp32' or platform == 'esp32_LoBo':  # ESP32 Doesn't support hard IRQ
-            ei = pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING))
+            pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING))
         else:
         else:
-            ei = pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True)
-        self._eint = ei  # Keep reference??
+            pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True)
         self.edge = 0
         self.tim = Timer(-1)  # Sofware timer
         self.cb = self.decode
         self.edge = 0
         self.tim = Timer(-1)  # Sofware timer
         self.cb = self.decode
@@ -68,3 +68,7 @@ class IR_RX():
 
     def error_function(self, func):
         self._errf = func
 
     def error_function(self, func):
         self._errf = func
+
+    def close(self):
+        self._pin.irq(handler = None)
+        self.tim.deinit()
diff --git a/ir_rx/acquire.py b/ir_rx/acquire.py
new file mode 100644 (file)
index 0000000..7b492e0
--- /dev/null
@@ -0,0 +1,99 @@
+# acquire.py Acquire a pulse train from an IR remote
+# Supports NEC protocol.
+# For a remote using NEC see https://www.adafruit.com/products/389
+
+# Author: Peter Hinch
+# Copyright Peter Hinch 2020 Released under the MIT license
+
+from machine import Pin, freq
+from sys import platform
+
+from utime import sleep_ms, ticks_us, ticks_diff
+from ir_rx import IR_RX
+
+
+class IR_GET(IR_RX):
+    def __init__(self, pin, nedges=100, twait=100, display=True):
+        self.display = display
+        super().__init__(pin, nedges, twait, lambda *_ : None)
+        self.data = None
+
+    def decode(self, _):
+        def near(v, target):
+            return target * 0.8 < v < target * 1.2
+        nedges = self.edge
+        if nedges < 4:
+            return  # Noise
+        burst = []
+        duration = ticks_diff(self._times[0], self._times[nedges])  # 24892 for RC-5 22205 for RC-6
+        for x in range(nedges - 1):
+            dt = ticks_diff(self._times[x + 1], self._times[x])
+            if x > 0 and dt > 10000:  # Reached gap between repeats
+                break
+            burst.append(dt)
+
+        if self.display:
+            detected = False
+            for x, e in enumerate(burst):
+                print('{:03d} {:5d}'.format(x, e))
+            print()
+            if burst[0] > 5000:
+                print('NEC')
+                detected = True
+            elif burst[0] > 2000:  # Sony or Philips RC-6
+                if burst[1] > 750:  # Probably Philips
+                    if min(burst) < 600:
+                        print('Philips RC-6 mode 0')
+                        detected = True
+                else:
+                    lb = len(burst)
+                    try:
+                        nbits = {25:12, 31:15, 41:20}[len(burst)]
+                    except IndexError:
+                        pass
+                    else:
+                        detected = True
+                    if detected:
+                        print('Sony {}bit'.format(nbits))
+
+            elif burst[0] < 1200:
+                print('Philips RC-5')
+                detected = True
+            if not detected:
+                print('Unknown protocol')
+
+            print()
+        self.data = burst
+        # Set up for new data burst. Run null callback
+        self.do_callback(0, 0, 0)
+
+    def acquire(self):
+        while self.data is None:
+            sleep_ms(5)
+        self.close()
+        return self.data
+
+def test():
+    # Define pin according to platform
+    if platform == 'pyboard':
+        pin = Pin('X3', Pin.IN)
+    elif platform == 'esp8266':
+        freq(160000000)
+        pin = Pin(13, Pin.IN)
+    elif platform == 'esp32' or platform == 'esp32_LoBo':
+        pin = Pin(23, Pin.IN)
+    irg = IR_GET(pin)
+    print('Waiting for IR data...')
+    irg.acquire()
+
+#          RC          Python   Calculated
+# NEC      66          66       66
+# Sony 12: 24       24       26 (2 hdr + 2*(7 data + 5 addr)  RC issues another: detect 26ms gap
+# Sony 15: 75          30
+# Sony 20  n/a         40
+
+# Yamaha NEC 
+# Pi/Vista MCE RC6 mode 0 Din't receive
+# Panasonic TV recorder RC6 mode 0 Didn't receive
+# Virgin RC-5 Receive OK
+# Samsung TV RC6 mode 0  Didn't receive