adafruit / circuitpython

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

pulseio.PulseIn maxlen is limited to 128 in esp32 #9234

Open tkomde opened 5 months ago

tkomde commented 5 months ago

CircuitPython version

Adafruit CircuitPython 9.1.0-beta.1-18-g781c577745-dirty on 2024-05-10; M5Stack AtomS3 with ESP32S3

Code/REPL

import board
import pulseio
import adafruit_irremote

pulsein = pulseio.PulseIn(board.D1, maxlen=1020, idle_state=True)
decoder = adafruit_irremote.GenericDecode()

while True:
    pulses = decoder.read_pulses(pulsein,max_pulse=91000)
    print(len(pulses))

Behavior

prints "128"

Description

It is possible that this is an intended specification, but I am reporting it.

I have a HITACHI air conditioner remote control data (848+6 data length) being read by pulseio.pulseIn. Regardless of the maxlen I gave it, it only read a maximum of 128 data.

I looked into the cause and found the following code in ports/espressif/common-hal/pulseio/PulseIn.c#103 .

self->raw_symbols_size = MIN(64, maxlen / 2 + 1) * sizeof(rmt_symbol_word_t);

When I delete the MIN(64, x) calculation as follows, the behavior differed depending on the CPU. The ESP32S3(M5 AtomS3) and ESP32C6(M5 NanoC6) received all 854 data as desired, but the ESP32-PICO(M5 Matrix) still had 128 data. This seems to reproduce #7352.

self->raw_symbols_size = (maxlen / 2 + 1) * sizeof(rmt_symbol_word_t);

Is MIN(64, x) required by some constraint? If almost esp32 chips can receive more data, I would like to receive it.

Additional information

No response

dhalbert commented 5 months ago

SOC_RMT_MEM_WORDS_PER_CHANNEL, which is used in PulseIn.c, varies per processor. However, on the ESP32, it is 64, and on ESP32-S3 and C6, it is 48. Not sure what to make of that, given your test results above.

tannewt commented 5 months ago

Its been a little while since I wrote this code. I think my intent was to limit the maxlen to the amount the RMT peripheral can buffer. I didn't want to assume PSRAM was accessible when PulseIn was running. (Writing the filesystem will disable it temporarily.)

I think some RMTs can use multiple channels worth of memory if needed. That could improve things.

Note each RMT word stores two "pulses" one active and one inactive. That's why 64 words give a length of 128.

tkomde commented 5 months ago

@dhalbert

Thanks for your comment.

This is a difficult area to understand for me, but I found an article that might be relevant. It seems that chips with the feature SOC_RMT_SUPPORT_RX_PINGPONG can handle more data than buffers.

https://esp32.com/viewtopic.php?t=24484

CircuitFlyer commented 2 months ago

Not to muddle up this topic but I also noticed a maxlen limit of 128 pulses on an ESP32-S3 QTPy no PSRAM. My main issue was that PulseIn doesn't work at all to capture a set of pulses (<128) from a constant pulsed data stream. Details here