nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.66k stars 3.12k forks source link

ws2812.write() fails #2936

Closed klauweg closed 2 years ago

klauweg commented 5 years ago

Expected behavior

ws2812.write() function should update a connected led String with 60 Leds reliable.

Actual behavior

In a running script with timer callbacks it does sometimes. From interactive command prompt it does never.

Test code

ws2812.write({pin = 15, data=string.char(255,255,255, 0, 0, 0, 255,255,255,0, 0, 0, 255,255,255,0, 0, 0, 255,255,255)})

The resulting Output on Pin looks like this: grafik

The gap between the two bit bursts shouldn't be there. It varies between 8 and 15 us. There was nothing running on nodemcu. The mentioned ws2312.write() was the only command i've entered after booting.

NodeMCU version

On branch dev-esp32 commit a4fa6c5cd3485a2bfb263e0114e94ae1bd332179

Hardware

ESP32 doit devkit V1.0

klauweg commented 5 years ago

placing the same function call as callback in a timer results in another waveform with later gap:

mytimer:alarm(700, tmr.ALARM_SINGLE, function() ws2812.write({pin = 15, data=string.char(255,255,255, 0, 0, 0, 255,255,255,0, 0, 0, 255,255,255,0, 0, 0, 255,255,255)}) end)

grafik

Intented with the two screenshots we can see that there is not only a gap but there are bits disappeared even before the large gap.

ulab commented 4 years ago

I am experiencing a similar problem. Controlling my WS2812b matrix works fine on NodeMCU on an ESP8266 and with FastLED/Arduino on an ESP32, but the ESP32-dev version just messes with the first two or three LEDs which made me think it's a timing issue.

I don't have scope to check it though.

thornley-david commented 4 years ago

Experienced similar issue trying to drive 5 led's (neopixel - ws2812)

An interesting observation is that release/v3.3 the problem occurs all the time, however tags/v3.3.2 only occurs when wifi is enabled via wifi:start()

thornley-david commented 4 years ago

As far as the change in release/v3.3 is concerned, it looks like this commit (https://github.com/espressif/esp-idf/commit/92a646aa4eb72b41a9c41c35ced364203f0fe222) is the culprit.

thornley-david commented 4 years ago

I'm a little stuck with this, I traced this to a single line of code https://github.com/espressif/esp-idf/commit/92a646aa4eb72b41a9c41c35ced364203f0fe222#diff-b1df72eee4bf4584db9a57c5b0489832R211 which was in the commit mentioned above. Removing the "continue" allows ws2812 module to work with 5 leds (until I enabled wifi:start(). Strangely, tracing the code itself indicates that line of code is never executed.

thornley-david commented 4 years ago

I managed to seemingly work around this, however I am keen to seek advice from the original author of ws2812 @devsaurus. The module itself predates a u8 translate hook added to rmt. Because of this, it sets up a shared isr for injecting encoded rmt data, I guess for speed. I just wanted to know if rmt_write_sample() might be a better way to handle data flow in this module. Since I am green to this, maybe I am missing something obvious about why the shared isr was added in the first place, or the broader implications of approaching it this way.

TerryE commented 4 years ago

This 10-20 uSec period is typical of an interrupt service routine (ISR) firing.

@devsaurus Arnim, does this ws2812 fork predate the latest 8266 version which allows you to use a H/W Tx uart? without some form of H/W output DMA, ISRs firing will cause this sort of data xfer dropout

IS2511 commented 4 years ago

This still doesn't work! Any help? My project kind of relies on this working... :cry:

nwf commented 4 years ago

I believe any software-driven bitbanging is hopeless in the ESP universe and I am vaguely unhappy that we ever permit it in our tree, but that Rubicon lies in the distant past. In any case, I think the best option here is to copy up the 8266 approach to generating the WS2812 waveform: make the UART do the precise timing. A full ESP8266 UART tx buffer keeps the UART busy for about 300 microseconds, which is enough to hide the occasional ISR firing. Strictly speaking, we should cork the UART or disable IRQs until the TX buffer is full so that we don't lose to an ISR during the initial fill.

IS2511 commented 4 years ago

From what I'm reading I assume I need the esp8266 ws2812 module. How can I include it into dev-esp32?

IS2511 commented 4 years ago

So I thought about this for a while and the only thing I could make quickly is a Lua library (a file in SPIFFS), so I made one looking at the esp8266 ws2812.c. It actually works, but it's not the best, it temporarily allocates a string of size LEDs*colors*4 bytes (+ the size of input buffer), which is not ideal. Do I need to publish it? Any ideas on how to write to uart iteratively? (I compose a big string and write it in one uart.write())

TerryE commented 4 years ago

The tx mode needs setting properly, and yes, you could preprocess the RGB stream into a Lua string that you could then write to the TX channel, this is best done in C. Pretty straightforward if you have C development skills. If you haven't, then I suggest that you leave it for someone that has.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.