Black Lives Matter - Action and Equality. ... Adafruit is open and shipping.
0

FT232H CircuitPython WS2812B Timing Wrong
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

FT232H CircuitPython WS2812B Timing Wrong

by jajo426 on Fri Jul 24, 2020 11:15 pm

I am using an Adafruit FT232H breakout to drive a strip of WS2812B LEDs. I have followed this tutorial (https://learn.adafruit.com/circuitpytho ... i/overview) and can get the example code to work and produce output on D1 of the FT232H. However, connecting D1 to the input of the first LED of a 4 LED test strip produces nothing. Upon further inspection I observe the timing of the outputs is out of specification for the WS2812B. I have verified the test segment works fine by using an FPGA which generates an exact timing sequence per WS2812B specifications, so I suspect the timing of the FT232H is the problem. I also tried interfacing the WS2812B strip to the FT232H using a high speed logic translator (SN74LV4T125) to shift to 5V logic, no change, LED strip still does not light up.

Scope outputs of pin D1 using Adafruit FT232H running provided neo_ring.py example are attached. Each bit has duration 1500 ns. The sample low bit has high time 350 ns, low time 1170 ns. The sample high bit has high time 650ns, low time 840ns. This is out of spec and highly unusual, assuming the Adafruit library still sets the SPI clock to 6MHz and uses 8 FT232H bits per WS2812B bit, each bit should have duration 1330 ns and could have high time 500 ns and low time 830 ns or high time 830 ns and low time 500 ns, within specifications for the WS2812B.

scope_0.png
scope_0.png (19.81 KiB) Viewed 14 times

Total bit duration, low bit
scope_1.png
scope_1.png (19.79 KiB) Viewed 14 times

High time, low bit
scope_2.png
scope_2.png (19.79 KiB) Viewed 14 times

Low time, low bit

I'm only allowed to attach 3 files, so I can't include measurements for high bit shown next to the low bit. Recorded duration is included above scope output in this post.

Seems I have either a computer problem, USB cable problem, or a faulty FT232H breakout. Please advise suggested next steps to root out the problem.

jajo426
 
Posts: 5
Joined: Fri Jul 24, 2020 10:36 pm

Re: FT232H CircuitPython WS2812B Timing Wrong

by jajo426 on Tue Jul 28, 2020 12:05 pm

I did a little more probing, over the weekend I did not think to check the SPI clock. Observing D0 on the FT232H, I see a ~6 MHz clock as one would expect, 8 clock ticks per byte sent to the neopixel for each of R, G, and B. I also see a 168 ns dead time after the last negedge of the clock and the next pixel bit being sent. More scope outputs follow.

scope_6.png
scope_6.png (19.83 KiB) Viewed 9 times

In this scope screenshot, D0 and D1 probes correspond directly with FT232H breakout D0 and D1. I observe this low bit is transmitted as 2 clock cycles high, 6 clock cycles low - for 333 ns high, within neopixel spec, and 1000 ns low - technically within 850 ns +- 150 ns specification, but risky.

scope_5.png
scope_5.png (19.67 KiB) Viewed 9 times


Now consider the dead time in this scope output, adding 168 ns to the low time - for total low time 1168 ns. Completely out of spec, *I think*. Except for this: https://wp.josh.com/2014/05/13/ws2812-n ... know-them/ which suggests this dead time should not be a problem, and also suggests the low side of the pulse could be as long as 5000 ns! So the 330 ns high duration is within the spec for communicating a 0 bit to the neopixel.

scope_8.png
scope_8.png (19.87 KiB) Viewed 9 times

Now I consider a high bit. Here is one on the scope. I observe this high bit is transmitted as 4 clock cycles high, 4 clock cycles low - for 667 ns high, and 667 ns low. Total low time 667 ns + dead time, but let's assume the dead time doesn't matter. The neopixel spec is 800 ns high time +- 150ns for a 1 bit, and 667 ns is within that specification. A little risky, but within spec.

I checked again and tried to drive the test strip with this output using 3v3 logic, no dice. I tested again using my level shifter, no scope outputs included, scope shows the 5V output directly reproduces the 3v3 logic signal with no relevant delay. Still no luck. Any suggestions from Adafruit support are appreciated. More debug notes will be included in follow up posts as I am limited to 3 images per post, in case it helps shed some light on what is going on.

jajo426
 
Posts: 5
Joined: Fri Jul 24, 2020 10:36 pm

Re: FT232H CircuitPython WS2812B Timing Wrong

by adafruit_support_carter on Tue Jul 28, 2020 12:41 pm

You can try tweaking the high/low bit patterns here:
https://github.com/adafruit/Adafruit_Ci ... #L161-L163

The current values were tweaked and verified with the NeoPixels that Adafruit sells. But there can be some variation among WS2812B variants. Both in timing and probably in behavior for out of spec timings.

Here's where the SPI bus clock frequency is set:
https://github.com/adafruit/Adafruit_Ci ... spi.py#L96
as well as the reset timing (TRST) on the next line.

Also see the _transmit function for details about what actually gets sent out.

adafruit_support_carter
 
Posts: 16268
Joined: Tue Nov 29, 2016 2:45 pm

Re: FT232H CircuitPython WS2812B Timing Wrong

by jajo426 on Tue Jul 28, 2020 12:57 pm

For the next step in my debugging process I turn to an old github repository of code for driving neopixels with the Adafruit FT232H breakout board written by Tony DiCola here. Tony's approach uses MPSSE and drives the neopixel strip with low bits 3 clock cycles high, 5 clock cycles low, and high bits 5 clock cycles high, 3 clock cycles low (in SPI land). That is, for a low bit, a high time 500 ns and low time 833 ns (1000 ns including dead time between SPI bytes). For a high bit, this is a high time of 833 ns and a low time of 500 ns (670 ns including dead time between SPI bytes). This library also fails to drive the neopixel strip using raw 3v3 logic output and using a high speed SNxx125 logic translator upshifting to 5V logic.

scope_7.png
scope_7.png (19.45 KiB) Viewed 6 times

Here is a sample low bit, showing measurement of high time as 500 ns. The low time which follows is 1000 ns.

scope_10.png
scope_10.png (19.91 KiB) Viewed 6 times

Here is a sample high bit, showing measurement of high time as 832 ns. The low time which follows is 664 ns.

For a little background I suppose I should also mention my original approach was to use an FPGA until I found the FT232H breakout sold by Adafruit and the convenient Python library by Tony DiCola (Adafruit_NeoPixel_FTDI) on GitHub to communicate with it. The FPGA worked but interfacing to a PC would require a lot more overhead than the approach offered by Adafruit and the MPSSE interface in this library.

Earlier this year I tried this and the Adafruit Blinka library and had no success. Thinking the 3v3 logic level was the problem, I used two of 6 inverting Schmitt triggers from a CD40106 hex Schmitt trigger inverter in series to upshift to 5V logic. Built on a breadboard with the FT232H. It worked! However I was unhappy with using a breadboard and an antique CD series chip as a level shifter so I designed a breakout *for the breakout* (getting a little meta up in here) which includes an SNxx125 logic translator and some terminal blocks so I can mount this nice little PCB inside the enclosure I made for the LED strip power supply and have an elegant interface. That's when I found the issue was not the logic level but the timing produced by the Adafruit library. I compared the timing of the output from the SNxx125 logic translator with the output of the CD40106 using analog probes. The SNxx125 logic translator preserves the timing of the FT232H output exactly while the CD40106 has a large rise and fall time.

WA000005.png
WA000005.png (7 KiB) Viewed 6 times

Here is a scope screenshot showing structure of CD40106 output (blue) compared to FT232H input (yellow) using analog probes.

Turns out the reason this system was working is this. Despite the antique CD40106 having a rise and fall time of 100-200 ns as specified by the datasheet, I just happened to be using a CD40106 with 250 ns rise and fall time, out of spec for the IC, which happens to be the right delay to fix the timing error in a way the neopixels would accept. Now that I've seen this, I cannot in good faith continue to rely on the particular badness of one CD40106 from one particular batch to control my LED lighting so I turned to this forum in hope of support. It is interesting to note the SNxx125 has a max transition time of 100 ns running on 5V supply, but in practice I observe sub-10 ns transition times 0-5 V and 5-0 V. So the reason this isn't working is definitely the timing output of the FT232H.

jajo426
 
Posts: 5
Joined: Fri Jul 24, 2020 10:36 pm

Re: FT232H CircuitPython WS2812B Timing Wrong

by jajo426 on Tue Jul 28, 2020 1:19 pm

Final bit of information, in case it helps, here is some inspection of output timing from my FPGA. I use a 20 MHz clock to synthesize the serial data stream to the neopixels so I have a resolution of 50 ns and can satisfy the timing requirements exactly. The nominal timing output is 400 ns high, 850 ns low for a low bit and 800 ns high, 450 ns low for a high bit, bit period 1.25 us, a direct reproduction of the timing requirement specified by the manufacturer of the WS2812B LEDs used on the neopixel strips.

scope_3.png
scope_3.png (19.78 KiB) Viewed 5 times

Total bit period for high bit produced by FPGA.

scope_4.png
scope_4.png (19.74 KiB) Viewed 5 times

High time for high bit produced by FPGA.

scope_5.png
scope_5.png (19.53 KiB) Viewed 5 times

Low time for high bit produced by FPGA.

Upon close inspection it looks like I have an extra clock tick of dwell time for setup between each transmitted bit (which could be eliminated with an update to my HDL design) but it is within the tolerance +-150 ns for the LEDs. This is irrelevant at this point as my goal is to transition to the Adafruit FT232H breakout. Regarding the issue I have with the FT232H breakout unable to drive the neopixel strip, I'm totally stumped.

jajo426
 
Posts: 5
Joined: Fri Jul 24, 2020 10:36 pm

Re: FT232H CircuitPython WS2812B Timing Wrong

by jajo426 on Tue Jul 28, 2020 1:23 pm

adafruit_support_carter wrote:You can try tweaking the high/low bit patterns here:
https://github.com/adafruit/Adafruit_Ci ... #L161-L163

The current values were tweaked and verified with the NeoPixels that Adafruit sells. But there can be some variation among WS2812B variants. Both in timing and probably in behavior for out of spec timings.

Here's where the SPI bus clock frequency is set:
https://github.com/adafruit/Adafruit_Ci ... spi.py#L96
as well as the reset timing (TRST) on the next line.

Also see the _transmit function for details about what actually gets sent out.



THANK YOU, I'll give that a try. Excuse the extra information, I got so excited to post more scope screenshots I didn't notice your response. I will play with this and report back what I find. I'm hopeful as it looks like this is exactly what I need.

jajo426
 
Posts: 5
Joined: Fri Jul 24, 2020 10:36 pm

Please be positive and constructive with your questions and comments.