Instead of sending digital data, how to read said data from a fastled 5v wire?

EugenM

Member
Greetings, ive been trying to get an answear for this question in arduino forums, and the only indication that i could get there was that arduino is too slow for such operations, my needs are pretty simple really, please imagine this scenario.
You install fastled library in a teensy board, you use it then to send data to a connected ws2801 ledstrip, when you do that, youre sending data through a 5v wire.
In essence what i need to do instead is not to send the data but to sit between a ledstrip and another board and capture the sent data from said board, even if its in its raw bit data (a series of 1s and 0s).
How would i achieve such feat?

To avoid as much confusion as possible, ive drawn my need in red in the following picture
teensy example.jpg

Thank you very much in advance!
 
As far as I know, there is no easy way. So with that in mind, here are some ideas about not easy ways....

You'll probably want to use Teensy 4.0 or 4.1, since this needs high speed. Your diagram shows another Teensy transmitting, which will output a 3.3V signal. But your question asks "sending data through a 5v wire". If the signal is from a board like Arduino Mega which transmits 5 volt signals, you'll need to reduce to 3.3V level. Driving a Teensy 4 pin with a 5V signal could cause damage.

I would try using a serial port running at 8000000 baud. The idea is to try receiving each WS2812 bit as a byte. Serial 8n1 format means 10 bits, so you would want 8 Mbit/sec baud rate (10X the WS2812 800 kHz bitrate), or maybe slightly faster so the serial hardware has always finished receiving the last part of the WS2812 bit time as the serial stop bit.

The first challenge is Teensy 4 defaults to running the serial ports from the 24 MHz crystal, so the maximum baud rate is 6 Mbit/sec. But there is a way to reconfigure to run from 80 MHz clock, which gives you access to higher baud rates.

The other challenge is serial expects an active low signal, but WS2812 is active high. In theory, SERIAL_8N1_RXINV should work, though I'm not sure if we're supporting that on Teensy 4. Maybe Kurt will see this and comment. Might be simpler to just add hardware to invert the signal.

You'll probably also need to use addMemoryForRead() to increase the serial receive buffer. Each bit will be received as a byte, and each LED is 24 bits, or 32 bits if RGBW (though my understanding of FastLED is RGB format only). But maybe your code will be able to read the bytes as fast as they arrive? I imagine you'll create a lookup table which translates all 256 possible bytes into either a 0 or 1. Serial receives LSB first, and the bits are inverted. So a WS2812 short pulse for a 0 bit should be received with zeros in the low 1-3 bits and the rest as ones. So if you receive 0xFE, that's definitely a WS2812 bit 0 (remember the serial port swallows the start bit, so you won't receive anything for the first 1/10th of the pulse). If you receive 0xC0, that's definitely a 1 bit. Lots of bit patterns should never occur.

If you're going to retransmit the data, use a non-blocking library like WS2812Serial or OctoWS2811. WS2812Serial is probably better since it doesn't use any interrupts at all, and you'll be getting a *lot* of interrupts when data is incoming. But if you've reconfigured the serial hardware for 80 MHz clock, you'll probably need to modify WS2812Serial to transmit at the correct speed, because it's designed for the serial ports running from default 24 MHz.

Hopefully Teensy 4.0 at 600 MHz can do this. But as far as I know, we've never tested how much CPU overhead the serial code (with addMemoryForRead in use) takes for sustained reception at such a high baud rate. I guess in theory you could also dive into the serial port code and write something custom with less overhead than the circular buffer approach. Then again, it may be plenty fast enough.

Yet another way you might try this would repurpose the I2S digital audio. You could just feed the WS2811 signal into pin 8 (I2S1 port) or pin 5 (ISS2 port) and let the audio library capture the data. But the I2S default is a 64 bit frame where we capture two 16 bit chunks and ignore the other bits. You might look at the PDM input, which captures all the bits and feeds them into a huge software low-pass filter. Maybe if you delete the filter and replace it with code to look for groups of 0 and 1, you could parse the WS2812 data that way? But I'd try serial first, because once you invert the signal you can leverage the serial port's detection of start bits to automatically align each WS2812 bit to a received byte, which should make the software sign much simpler.
 
Perhaps receiving with SPI slave mode with a hardware or software one-shot to recover the clock.
 
As far as I know, there is no easy way. So with that in mind, here are some ideas about not easy ways....

You'll probably want to use Teensy 4.0 or 4.1, since this needs high speed. Your diagram shows another Teensy transmitting, which will output a 3.3V signal. But your question asks "sending data through a 5v wire". If the signal is from a board like Arduino Mega which transmits 5 volt signals, you'll need to reduce to 3.3V level. Driving a Teensy 4 pin with a 5V signal could cause damage.

I would try using a serial port running at 8000000 baud. The idea is to try receiving each WS2812 bit as a byte. Serial 8n1 format means 10 bits, so you would want 8 Mbit/sec baud rate (10X the WS2812 800 kHz bitrate), or maybe slightly faster so the serial hardware has always finished receiving the last part of the WS2812 bit time as the serial stop bit.

The first challenge is Teensy 4 defaults to running the serial ports from the 24 MHz crystal, so the maximum baud rate is 6 Mbit/sec. But there is a way to reconfigure to run from 80 MHz clock, which gives you access to higher baud rates.

The other challenge is serial expects an active low signal, but WS2812 is active high. In theory, SERIAL_8N1_RXINV should work, though I'm not sure if we're supporting that on Teensy 4. Maybe Kurt will see this and comment. Might be simpler to just add hardware to invert the signal.

You'll probably also need to use addMemoryForRead() to increase the serial receive buffer. Each bit will be received as a byte, and each LED is 24 bits, or 32 bits if RGBW (though my understanding of FastLED is RGB format only). But maybe your code will be able to read the bytes as fast as they arrive? I imagine you'll create a lookup table which translates all 256 possible bytes into either a 0 or 1. Serial receives LSB first, and the bits are inverted. So a WS2812 short pulse for a 0 bit should be received with zeros in the low 1-3 bits and the rest as ones. So if you receive 0xFE, that's definitely a WS2812 bit 0 (remember the serial port swallows the start bit, so you won't receive anything for the first 1/10th of the pulse). If you receive 0xC0, that's definitely a 1 bit. Lots of bit patterns should never occur.

If you're going to retransmit the data, use a non-blocking library like WS2812Serial or OctoWS2811. WS2812Serial is probably better since it doesn't use any interrupts at all, and you'll be getting a *lot* of interrupts when data is incoming. But if you've reconfigured the serial hardware for 80 MHz clock, you'll probably need to modify WS2812Serial to transmit at the correct speed, because it's designed for the serial ports running from default 24 MHz.

Hopefully Teensy 4.0 at 600 MHz can do this. But as far as I know, we've never tested how much CPU overhead the serial code (with addMemoryForRead in use) takes for sustained reception at such a high baud rate. I guess in theory you could also dive into the serial port code and write something custom with less overhead than the circular buffer approach. Then again, it may be plenty fast enough.

Yet another way you might try this would repurpose the I2S digital audio. You could just feed the WS2811 signal into pin 8 (I2S1 port) or pin 5 (ISS2 port) and let the audio library capture the data. But the I2S default is a 64 bit frame where we capture two 16 bit chunks and ignore the other bits. You might look at the PDM input, which captures all the bits and feeds them into a huge software low-pass filter. Maybe if you delete the filter and replace it with code to look for groups of 0 and 1, you could parse the WS2812 data that way? But I'd try serial first, because once you invert the signal you can leverage the serial port's detection of start bits to automatically align each WS2812 bit to a received byte, which should make the software sign much simpler.

Thank you very much for your wonderful explanation of all the possibilities i currently have to read such data, im really new at Teensy and your post is very enlightening, you have no idea how hard was to find a post as useful as yours! Have a wonderful weekend and once again thank you very much for your help!
 
Back
Top