For this example, I have chosen to drive a 1-meter strip of NeoPixels with a LED density of 30 NeoPixels per meter. Reading the data sheet shows that the Neo Pixel array is designed to work with a 5V supply. However, reading the datasheet more carefully reveals that the highest voltage required is for powering the Blue LED, which needs a voltage between 3.2 and 3.4 volts. That’s right in the range of the 3.3V supply voltage available on the MicroZed I/O Carrier Card, which is what we’ll use.
The MicroZed I/O Carrier card has two on-board voltage regulators that you can use to supply I/O banks 34 and 35 on the Zynq SoC (and bank 13 if you are using the Zynq Z7020). The output voltages of these regulators are selectable between 1.8V, 2.5V, and 3.3V. Of the two regulators, the one associated with bank 35 has a higher current rating (2.8A) compared to the 2.3A rating for the regulator associated with bank 34. As we will be driving a large number of LEDs, I will be using the regulator for bank 35 to power the 1m NeoPixel array.
Each of the individual LEDs in a NeoPixel requires a maximum current of 20mA. There are three LED’s in each NeoPixel, hence each RGB pixel requires 60mA. With 30 NeoPixels per meter, we need a maximum current of 1.8A from the 3.3V supply. That is well within the rated current capacity of both of the I/O Carrier Card’s power supplies but we achieve maximum regulator de-rating by using the higher-rated regulator of the pair.
This means that the Pmod wire-terminal adapter plug attached to the NeoPixel array will be plugged into one of the I/O Carrier Card’s JE, JF, JG, or JH PMOD connectors because these four Pmod connectors are connected to the bank 35 regulator. The figure below shows the pinout for a Pmod interface:
Pmod Connector Pinout
The Digilent PmodCON1 wire-terminal adapter I am using breaks out only the power, ground, and four I/O signals. These pins are sufficient for driving the NeoPixel array, which only requires, power, return and Din.
The Din pin is how we program a pixel’s color. Each NeoPixel requires a 24-bit control word consisting of eight 8-bit green, red, and blue values in the order shown below:
NeoPixels have no clock line. They use a unique self-clocking, non-return-to-zero (NRZ) waveform to specify the bit values, as shown below:
NeoPixel bit timing
The waveform’s bit period and duty cycle both change depending on whether the bit value represented is a 1 or 0. The timings are: T0H = 0.35μsec, T0L = 0.8μsec, T1H = 0.7μsec, and T1L = 0.6μsec. All timing values have a tolerance of ± 150nsec. These times give slightly different durations for a Low bit (1.15μsec) compared to a High bit (1.3μsec). We will analyze this serial communications scheme in much more detail when we write the software driver in a future blog.
If a NeoPixel does not start receiving another word within 50μsec after receiving all 24 data bits in a data word, it loads the received 24-bit word into an internal register and lights its three LEDs using that 24-bit value. However, if the NeoPixel does receive another 24-bit word within the 50μsec timeout period, it retransmits the previously received word on its Dout port instead of using it internally. This mechanism allows you to use one serial signal line to control a large number of pixels in a very simple manner.
In the next blog, I will introduce the architecture within the Zynq PS and PL needed to drive the NeoPixels through the MicroZed I/O carrier card. Meanwhile, to whet your appetite, here are examples of the waveform output from the finished solution when it is outputting a High (1) and Low (0) bit.
Neo Pixel High bit output
Neo Pixel Low bit output
Please see the previous entries in this MicroZed series by Adam Taylor: