-
-
Notifications
You must be signed in to change notification settings - Fork 264
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
ESP32 I2S Parallel driving external shift register #648
Comments
NOTE: Shift registers require three pins: data, clock, and latch. If more than one external shift register is used, then they can reuse the clock and latch between them; but they will each require their own data line. As noted in the linked article; it will use the parallel feature of the i2s (newly added to NeoPixelBus) to provide the latch and 7 data io lines (8bit parallel) or 15 data lines (16bit parallel). I believe the ESP32 I2S has the ability to have a separate dedicated clock line but a little investigation can prove this and worst case another channel can be used for the clock. |
From the FastLED virtual driver line 707:
It seems like the clock is coming from a dedicated channel for each I2S bus if I'm reading this correctly. |
Actually, I think the clock is separate as I2S supports not only the data lines, but also a clock and word select pins. https://en.wikipedia.org/wiki/I%C2%B2S from gpi_sig_map.h |
The shift register pin naming is a little messy. So I thought I would include a map of the ones we care about ;-) |
So the I2S does provide both a CLK and WS pin output. But as suspected, the WS isn't useful. In non PDM mode the WS matches the frequency. BUT, the clock signal is useful as captured here with two channels of x8 parallel NeoPixel pulses. But to output N channels to the shift register on a single data pin, the frequency will need to be increased by xN. |
Ramped up the speed by 8 (needed for a 8bit shift register) and while a little messy, it does seem to provide the correct data that a shift register could use. |
@Makuna You intend on implementing my method to drive virtual pins into your library ? I could rewrite it to be able to only push through 7 pins instead of 15 this way you’ll save 384bytes of memory Having it to work with the 8 virtual pins was a bit a challenge because the esp32 clock above 20mhz tends to skip bits from time to time. Which is no big deal for its intended usage sound. But for the leds it is. |
@hpwit So, it was 7 pins + WS that worked ok? My experiments showed the max was 8 also.
Design notes: |
@Makuna I have just look at the ws signal for latch. it does not work the ws signal is not after 8 or 16 serial bits. The code to transform serial to parrallel you cannot quite go around it You need to use the parallel mode to send to each 7 shifts registers at the same time. even if you could use the WS signal as latch. Note, the DMA send buffer and its twin non-dma memory edit buffer must be full size; while individual BUS edit buffers are only allocated if a bus is instanced.
|
Using a single shift register on the WS output today (which cycles on a single bit or half the speed of the clock) you could divide it by 8 and thus create a Latch output at the correct timing to use on the other shift registers. Shift registers can be used as dividers. The only issue I could see was triggering it at the correct time, as the I2s seems to continuously send the WS when we would need it to start at the same time as the first data bit. Could the data pin be used as the latch/clear/enable for WS divider Shift Register? Those comments at the end (dirty flag and dma memory size) were not targeted at you. They were just capturing details of the i2s parallel Shift Register version will have. |
you need then to use D flip/flop to divide the frequency. as I will not work with an hc595 that needs a latch to ‘show’ the input to the output pins. In theory you could then use the clock signal to do so. It needs to be studied. Because you need to take the propagation speed of the signal through the gates. Indeed we are talking in around 50ns between signal. The normal ic could create a shift in signal. It would have to be tested. Why do you need to not have the latch with the data stream ? Of course you can drive one less shift register but as you said 7x8 is 56 strips which is already a lot. And 15x8 =120 which is more |
Its more about having a low memory and low pin count solution. If you could get the RW/Clock latch to work, then the non-parallel i2s could support a series of shift registers, getting x8 and even x16 support using only three pins. And the x8 would only need memory for x8, not the x64 it does with this solution. x8 SR would use the same frequency we already know is supportable. |
You want to use the series i2s to drive 1 shift register. Because using serial i2s you will not drive more than one shift register because of i2s speed limitations. Then maybe using the ws will work. In parrallel mode of you want to drive 8 SR you need the 16bit per bits not 64. |
@Makuna I have tried to go with the SPI, which can go faster than 20Mhz on my oscillo i can see good signal up to 80Mhz . |
SPI will require the DMA core to not have pauses. I have yet to confirm the new DMA SPI method for DotStars doesn't also have pauses (SPI spec doesn't state that it can't stretch and pause, making it more resilient on longer wire lengths). Note that when i2s is used in the non-parallel mode, the WS timing is correct i2s timing (a word of data). But it seems when in single channel 16 bit mode, they still send a normal balanced pulse even though there should be only one channel (WS is a sort of channel select, right and left is + and - on). Here is a capture (note, WS is inverted). The primary thing I wanted to prove with this capture was that WS could be used to "sync" the data with the latch. While it still can't be used directly as the latch (without a 4x multiplier, is this a thing?), when inverted as the capture above, on its rising edge it could be used to sync a divider of the real clock that is tied to the latch. The latch would need a div 4 from the clock that is synchronized starting at the edge of the WS. |
Thoughts on the 74VHC164? Seems to run considerably faster than the 74hc595. Not sure if there's any other electrical/signal properties I should be comparing too. |
NOTE: If you are seeking help or have questions, this is NOT the place to do it. For questions and support, jump on Gitter and ask away.
Is your feature request related to a problem? Please describe.
Looking for a way to expand the number of strips available when constrained on free GPIO pins.
Describe the solution you'd like
Creating an ESP32 I2S driver to enable multiple outputs over a single pin through a shift register as described in this article:
https://hackaday.com/2019/05/07/lots-of-blinky-esp32-drives-20000-ws2812-leds/
Describe alternatives you've considered
I am unaware of any other options to achieve multiple strips running off of a single data pin.
Additional context
I'm unfamiliar with this codebase and I2S driver implementation in general, but I'm currently trying to understand both and would be willing to help in some capacity.
The text was updated successfully, but these errors were encountered: