Skip to content

esp32/machine_bitstream.c: Replace with RMT-based driver. #7985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

jimmo
Copy link
Member

@jimmo jimmo commented Nov 11, 2021

This aims to solve the reported glitching issues on long neopixel strips.

Although I wasn't able to repro any glitching on the existing firmware (suggestions welcome!), with this RMT driver I'm seeing no issues on a 300-LED SK6812 strip and a 32-LED WS2812 grid. Test setup is just a TinyPico connected directly to the strips (no level shifting).

This aims to solve the glitching issues on long neopixel strips.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
@jimmo
Copy link
Member Author

jimmo commented Nov 11, 2021

If anyone wants to test this compiled firmware for ESP32-GENERIC is here: (updated)
https://drive.google.com/file/d/1aBGok0Nz38AYytti297_4Ch6DLVa7kML/view?usp=sharing

@jimmo
Copy link
Member Author

jimmo commented Nov 12, 2021

Some more background from CircuitPython (which use the exact same RMT code based on the Espressif sample) adafruit#3835

@scoates
Copy link
Contributor

scoates commented Nov 12, 2021

@jimmo It looks like that firmware file is not generally available (Google's asking me to log in)?

@jimmo
Copy link
Member Author

jimmo commented Nov 12, 2021

@jimmo It looks like that firmware file is not generally available (Google's asking me to log in)?

Sorry about that, fixed now.

@scoates
Copy link
Contributor

scoates commented Nov 12, 2021

Hi. Sorry if this is turning into a support call, but I ran into a couple things here.

Here's a log of my firmware install (to be sure I'm not messing that part up):

❯ pipenv run esptool --port /dev/tty.usbserial-230 erase_flash
esptool.py v3.2
Serial port /dev/tty.usbserial-230
Connecting..........
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting.....
Detecting chip type... ESP32
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:ab:95:5d:34:1c
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 71.0s
Hard resetting via RTS pin...
❯ pipenv run esptool --port /dev/tty.usbserial-230 --chip esp32 --baud 460800 write_flash -z 0x1000 esp32-generic-20111112-neopixel-rmt.bin
esptool.py v3.2
Serial port /dev/tty.usbserial-230
Connecting......
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:ab:95:5d:34:1c
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x00173fff...
Compressed 1516288 bytes to 981865...
Wrote 1516288 bytes (981865 compressed) at 0x00001000 in 25.3 seconds (effective 480.4 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Then, via the REPL:

> screen /dev/tty.usbserial-230 115200
…
>>> import os
>>> os.uname()
(sysname='esp32', nodename='esp32', release='1.16.0', version='v1.16-102-g88662c94a-dirty on 2021-07-15', machine='ESP32 module with ESP32')

(I thought I was expecting 1.17 here, but I'm not sure)

Digging into the actual matter, via the REPL again:

> screen /dev/tty.usbserial-230 115200
…
>>> import neopixel, machine
>>> np = neopixel.NeoPixel(machine.Pin(25), 256)
>>> np[0] = (255, 0, 0)
>>> np.write()
>>> np.write()
>>> np.write()
# etc, manually

Yields: https://files.scoat.es/KonwnZlQ.mov

On Twitter you requested:

If you still see glitching, can you also try tweaking the timing.
NeoPixel(pin, N, timing=(400, 850, 800, 450))
is the default, but it looks like FastLED uses (250, 1000, 875, 375) for WS2812 and (300, 900, 600, 600) for SK6812.

Trying this, I get what looks like a bad cast from the tuple:

>>> np = neopixel.NeoPixel(machine.Pin(25), 256, timing=(400, 850, 800, 450))
>>> np[0] = (255, 0, 0)
>>> np.write()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "neopixel.py", line 35, in write
TypeError: can't convert tuple to int

Sorry again if this is turning into much more than you wanted to take on.

Edit: This is Espressif + LOLIN D32 Pro, FWIW.

@jimmo
Copy link
Member Author

jimmo commented Nov 12, 2021

(I thought I was expecting 1.17 here, but I'm not sure)

Sorry @scoates argh this is why I shouldn't do this a 2am. I grabbed the wrong file.

Here's the correct firmware.
https://drive.google.com/file/d/1aBGok0Nz38AYytti297_4Ch6DLVa7kML/view?usp=sharing

This should also fix the ability to set custom timing. Thanks for testing this out!

@scoates
Copy link
Contributor

scoates commented Nov 12, 2021

With that one, I seem to get a reboot loop (and no REPL):

❯ pipenv run esptool --port /dev/tty.usbserial-230 erase_flash && pipenv run esptool --port /dev/tty.usbserial-230 --chip esp32 --baud 460800 write_flash -z 0x1000 esp32-generic-20111112-v117-neopixel-rmt.bin
esptool.py v3.2
Serial port /dev/tty.usbserial-230
Connecting.....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting..........
Detecting chip type... ESP32
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:ab:95:5d:34:1c
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 65.8s
Hard resetting via RTS pin...
esptool.py v3.2
Serial port /dev/tty.usbserial-230
Connecting..........
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:ab:95:5d:34:1c
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x0016afff...
Compressed 1482688 bytes to 982640...
Wrote 1482688 bytes (982640 compressed) at 0x00001000 in 24.9 seconds (effective 477.0 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

@jimmo
Copy link
Member Author

jimmo commented Nov 12, 2021

@scoates sorry it's been a while since I did builds of esp32 firmware and things have changed. I (mistakenly) just gave you the application.bin (which goes in a different location). I should have given you the combined firmware.

Here's a combined firmware.bin, for real this time -- https://drive.google.com/file/d/1TUzZelltMIyObAYdJqphuD1wJWMRolh6/view?usp=sharing

@jimmo
Copy link
Member Author

jimmo commented Nov 12, 2021

Ah I see what's been going wrong -- I've been using make BOARD=x deploy every time (and testing on my esp32). But the deploy target doesn't build the combined binary. So the first link you got a binary from months ago (the last time I did make without deploy, i.e. never). The second time I mistakenly grabbed micropython.bin.

@dpgeorge I think we should make the deploy target also make combined firmware.bin (just so you never have a state where the build dir has a different micropython.bin to firmware.bin).

@scoates
Copy link
Contributor

scoates commented Nov 12, 2021

Great news:

  • Firmware is good; uname even says 1.17 and today (well, tomorrow, but you live in tomorrow)
  • got a REPL
>>> while(True):
...     for i in range(256):
...         np.fill((0, 0, 0))
...         np[i] = (255, 0, 0)
...         np.write()

And: Wonderful! No noise/ghost pixels!

(I didn't [have to] change timings.)

Thank you!

@jimmo
Copy link
Member Author

jimmo commented Nov 12, 2021

And: Wonderful! No noise/ghost pixels!

That's fantastic, thank you very much for testing @scoates !

I'll sort out the idf 4.0.2 compatibility (it's using convenience macros added in a later IDF version) and do more testing on other esp32 family chips and see if we can get this in for 1.18.

@dpgeorge
Copy link
Member

Fixed IDF 4.0.2 build, tested on TinyPICO with IDF 4.0.2 and 4.2.2, and merged in 599b61c

@dpgeorge dpgeorge closed this Dec 22, 2021
@wimaha
Copy link

wimaha commented Jan 1, 2022

Testet on ESP32 and it works!
Thank you very much! @jimmo

@odi6331
Copy link

odi6331 commented Jan 1, 2022

I also tested the new firmware and it works! One question, i was using a library called urequests in one of my network modules. After flashing your new firmware it was not able to find this modul anymore. Do you have a idea to fix that? The rest was working with no problems.

Thank's so far @jimmo

@dpgeorge
Copy link
Member

dpgeorge commented Jan 6, 2022

One question, i was using a library called urequests in one of my network modules. After flashing your new firmware it was not able to find this modul anymore. Do you have a idea to fix that?

It could be because the stable releases of esp32 firmware bundle some additional Python modules. You can separately install these by copying (eg with https://pypi.org/project/mpremote/) the files, eg from https://github.com/micropython/micropython-lib/blob/master/python-ecosys/urequests/urequests.py

@scoates
Copy link
Contributor

scoates commented Jan 10, 2022

I was experimenting with this (firmware above) again this weekend, and I noticed that if I turn WiFi on, I get noise again. Happy to explore this in another issue, or maybe wait for the official release… just commenting because we'd had this conversation here already.

@wimaha
Copy link

wimaha commented Jan 10, 2022

Thanks @scoates! I also was experimenting with this. I also got noise, when WiFi is turned on.

@dpgeorge
Copy link
Member

Can you please open a new issue about this noise with WiFi enabled? And add some detail about how to reproduce it. I'm trying with an 8-pixel strip doing while True: neopixel.write(), and at the same time ping'ing the esp32 from a PC at 100Hz. There are no glitches on the LEDs.

@dpgeorge
Copy link
Member

See #8158

@odi6331
Copy link

odi6331 commented Jan 11, 2022

I am also working on a Neopixel project and I was bothered about sporadic flickering. All the Tips I found on internet did not bring me to a satisfying solution. Then I found a webpage discussing, that the Neopixel WS2812b exists in two versions. The regular one and a new one. According to the datasheet from the new Version the timing of the T0H/T0L and T1H/T1L is slightly different and need some adjustments. Usually the Neopixel Library available for micropython works with a timing pattern of (timing=(400, 850, 800, 450)) according to the new datasheet the value 400 and 450 is to close to maximum allowed. I changed them on my setup to a timing=(350,800,800,350) and all the flickering was gone since then. Try to adjust this timing if you are using the new version of WS2812B Neopixel maybe it helps for you too. Here the link to the Webpage of this discussion: https://blog.adafruit.com/2017/05/03/psa-the-ws2812b-rgb-led-has-been-revised-will-require-code-tweak/

@scoates
Copy link
Contributor

scoates commented Jan 11, 2022

#8161

tannewt pushed a commit to tannewt/circuitpython that referenced this pull request Jun 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants