From 1c76b13fbbd3284fdc007f8aca140724469e1367 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Mon, 2 Mar 2020 17:32:17 +0000 Subject: [PATCH] Update ir_rx_test and README re ESP8266 iss 5714. --- README.md | 28 ++++++++++++++++------------ ir_rx.py | 9 +++++---- ir_rx_test.py | 16 ++++++++-------- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 2e31090..58cbc9e 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ a driver for IR "blaster" apps. The device drivers are nonblocking. They do not require `uasyncio` but are compatible with it. NOTE: The receiver is intended to be cross-platform. In testing it has proved -problematic on ESP8266 and ESP32 with a tendency to crash and reboot, -especially when repeated pulse trains re received. The cause is under -investigation. +problematic on ESP8266. The cause is +[this firmware issue](https://github.com/micropython/micropython/issues/5714) +which should be fixed in due course. # 1. IR communication @@ -49,7 +49,7 @@ microcontroller. The tested chip returns a 0 level on carrier detect, but the driver design ensures operation regardless of sense. In my testing a 38KHz demodulator worked with 36KHz and 40KHz remotes, but this -is obviously not guaranteed or optimal. +is obviously neither guaranteed nor optimal. The pin used to connect the decoder chip to the target is arbitrary. The test program assumes pin X3 on the Pyboard, pin 23 on ESP32 and pin 13 on ESP8266. @@ -77,10 +77,8 @@ Copy the following files to the target filesystem: 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. +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. ## 3.2 Transmitter @@ -120,7 +118,7 @@ Protocol specific args: value matching your remote improves the timing and reduces the likelihood of errors when handling repeats: in 20-bit mode SIRC timing when a button is held down is tight. A worst-case 20-bit block takes 39ms nominal, yet the repeat - time is 45ms nominal. + time is 45ms nominal. On ESP32 20-bit mode did not work well. The Sony remote tested issues both 12 bit and 15 bit streams. The callback takes the following args: @@ -175,8 +173,14 @@ 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. +The Philips protocols - especially RC-6 - have tighter timing constraints. +Currently the ESP8266 suffers from [this issue](https://github.com/micropython/micropython/issues/5714) +which prevented testing. + +All modes work on the Pyboard. On ESP32 NEC mode works. Sony works for lengths +of 12 and 15 bits, but 20 bit mode was not reliable owing to the rate at which +repeats are transmitted. Philips RC-5 worked, with some "bad block" messages. +Work is ongoing to characterise ESP32 and ESP8266. # 4.3 Principle of operation @@ -191,7 +195,7 @@ 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 +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 diff --git a/ir_rx.py b/ir_rx.py index d73016a..69d2da9 100644 --- a/ir_rx.py +++ b/ir_rx.py @@ -49,11 +49,12 @@ class IR_RX(): self._times = array('i', (0 for _ in range(nedges + 1))) # +1 for overrun if platform == 'pyboard': - ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin) + ei = ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin) elif ESP32: - pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING)) + ei = pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING)) else: - pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True) + ei = pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True) + self._eint = ei # Keep reference?? self.edge = 0 self.tim = Timer(-1) # Sofware timer self.cb = self.decode @@ -129,7 +130,7 @@ class SONY_IR(IR_RX): def decode(self, _): try: nedges = self.edge # No. of edges detected - print(nedges) + self.verbose and print('nedges', nedges) if nedges > 42: raise RuntimeError(OVERRUN) bits = (nedges - 2) // 2 diff --git a/ir_rx_test.py b/ir_rx_test.py index 2785398..b4f1cf9 100644 --- a/ir_rx_test.py +++ b/ir_rx_test.py @@ -8,6 +8,7 @@ from sys import platform import time +import gc from machine import Pin, freq from ir_rx import * @@ -19,7 +20,7 @@ elif platform == 'esp8266': freq(160000000) p = Pin(13, Pin.IN) elif ESP32: - p = Pin(23, Pin.IN) + p = Pin(23, Pin.IN) # was 27 errors = {BADSTART : 'Invalid start pulse', BADBLOCK : 'Error: bad block', BADREP : 'Error: repeat', OVERRUN : 'Error: overrun', @@ -43,8 +44,7 @@ test(3) for Sony SIRC 20 bit, test(5) for Philips RC-5 protocol, test(6) for RC6 mode 0. -Background processing means REPL prompt reappears. -Hit ctrl-D to stop (soft reset).''' +Hit ctrl-c to stop, then ctrl-d to soft reset.''' print(s) @@ -54,13 +54,13 @@ def test(proto=0): elif proto < 4: bits = (12, 15, 20)[proto - 1] ir = SONY_IR(p, cb, bits) - ir.verbose = True + #ir.verbose = True elif proto == 5: ir = RC5_IR(p, cb) elif proto == 6: ir = RC6_M0(p, cb) - ir.verbose = True # A real application would do something here... - #while True: - #time.sleep(5) - #print('running') + while True: + print('running') + time.sleep(5) + gc.collect() -- 2.47.3