adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.02k stars 1.19k forks source link

pulseio.PulseIn not working as expected #4300

Open caternuson opened 3 years ago

caternuson commented 3 years ago

The goal here was to read a standard hobby servo input signal.

Here's the general hardware setup, blue box is the receiver generating the signal (transmitter not shown): pulseio_test

Here's what the signal looks like at the voltage divider (1k/2k resistors) which is what goes to the input pin: rigol_capture

Here's the basic test code:

import time
import board
import pulseio

rx = pulseio.PulseIn(board.A3)

while True:
    if rx.paused:
        print(rx[0], rx[1])
        rx.clear()
        rx.resume()
    time.sleep(0.1)

And here's the output:

Adafruit CircuitPython 6.1.0 on 2021-01-21; Adafruit ItsyBitsy M4 Express with 
samd51g19
>>> import test
20104 1852
1852 20106
20103 1851
20106 1852
20106 1851
1852 20101
20107 1852

A similar behavior was seen using the QT Py also shown above. The values appear to be OK. Really good actually when compared to measured scope values. But note how the active/idle positions sometimes get swapped.

jposada202020 commented 3 years ago

In a different application of the PulseIn object. This is used to get the values from the DHT11/22 sensors using CircuitPython instead of Bitbang the sensor. Issue https://github.com/adafruit/Adafruit_CircuitPython_DHT/issues/53 as the library was having different behavior depending on the board used. For the Metro Express ESP32S2 the first pulse read was a Low so the first lecture was a checksum fail, after this initial failure the rest of the first pulse readings are High (in DHT therms). The DHT library is expecting the first pulse as a high and work like a charm https://github.com/adafruit/Adafruit_CircuitPython_DHT/blob/7c81737eff2b2fcaf399dfc7afee61d12867ca58/adafruit_dht.py#L82

        binary = 0
        hi_sig = False
        for bit_inx in range(start, stop):
            if hi_sig:

It was noted by @dgriswo that for the featherS2 this behavior was the opposite and changing the value for hi_sig = True DHT library will solve the issue. having the first read wrong and the rest of them good.I confirm this testing the propose solution in a featherS2. However, in doing this now the METRO ESP32S2 will not read work

Investigating the issue I tried to understand why the two board where generating two different things. MY train of tought was, maybe if I destroy and create the object every reading, I will get the same (Low Pulse in DHT therms), however, this was not the case, according to my findings, you will have a low pulse or high pulse and you cannot predict this. I can provide test result but is as @caternuson mentioned and showed in their test results. you will have sometimes a low and sometimes a high, For me it was around 50% each. For more information please see mentioned.

tannewt commented 3 years ago

@jposada202020 I suspect that is a different issue that is specific to the S2.

jposada202020 commented 3 years ago

@tannewt do I open a new one for the S2?

tannewt commented 3 years ago

@tannewt do I open a new one for the S2?

Yes please.

kevinjwalters commented 3 years ago

FYI, I don't know if there's any shared code here but I've just spotted some problems with pulseio.PulseOut timing on 6.x which breaks IR sending - see #4602.

mwisslead commented 2 years ago

It seems to me that this isn't a bug but a limitation as noted in the documentation PulseIn.maxlen: When len() is equal to maxlen, it is unclear which pulses are active and which are idle. Making maxlen greater than the number of pulses to be received should make the code work as hoped.