Personal tools
The Open Lighting Project has moved!

We've launched our new site at www.openlighting.org. This wiki will remain and be updated with more technical information.

Difference between revisions of "OLA LED Pixels"

From wiki.openlighting.org

Jump to: navigation, search
 
(46 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
{{PageMigrated|url=https://www.openlighting.org/ola/tutorials/ola-led-pixels/}}
 
[[Image:Lpd8806.jpeg|300px|right]]
 
[[Image:Lpd8806.jpeg|300px|right]]
  
Since March 2013, [[OLA]] contains an SPI plugin, which allows you to drive strings of LEDs pixels provided your hardware has an SPI device. Using embedded Linux platforms like the [[OLA_Raspberry_Pi | Raspberry Pi]], this allows one to build  Pixel strings controlable via any of the [[OLA#Supported_Protocols|supported protocols]] ([[ArtNet]],  [[E1.31]],  [[OSC]] & more)   for < $100.
+
Since March 2013, [[OLA]] contains an [http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus SPI] plugin, which allows you to drive strings of LEDs pixels provided your platform has an SPI interface. Using embedded Linux platforms like the [[OLA_Raspberry_Pi | Raspberry Pi]], this allows one to build  Pixel strings controllable via any of the [[OLA#Supported_Protocols|supported protocols]] ([[ArtNet]],  [[E1.31]],  [[OSC]] & more) for less than $100.
  
Alternatively if you don't want network control, you can send [[DMX512]] to the LEDs using the Python, C++ or Java client library.
+
Alternatively if you don't want network control, you can send [[DMX512]] to the LEDs using the Python, C++ or Java client library running on the host itself.
  
== Supported Hardware ==
+
This page is focused on the Raspberry Pi, but may be applicable to other hardware such as the BeagleBone.  If you're using a Raspberry Pi you can save yourself a lot of time by using the pre-built images, see [[OLA_Raspberry_Pi| OLA on the Raspberry Pi]] for details.
  
On the host side, any SPI hardware supported by the kernel should work correctly. By default OLA looks for devices in the form /dev/spi* .
+
== Host Hardware  ==
  
On the LED pixel side the following is supported:
+
The Raspberry Pi contains three SPI interfaces, but only one of these is wired to the 26-pin connector. The interface comes with 3 chip-enable (CE) lines but again only two are connected (pins 24 & 26). With the default mode, pin 24 is pulled low when the /dev/spi0.0 device is used and pin 26 is pulled low when /dev/spi0.1 is used.
* LPD8806, e.g. https://www.adafruit.com/products/306
 
* WS2801, e.g. https://www.adafruit.com/products/738
 
  
Only the WS2801 is supported in the 0.8.27 release. Code to support LPD8806 is in the git repo and will be in 0.7.28.
+
The Pi uses 3.3V logic. You can usually get away with connecting the pins directly to the pixel hardware which uses 5V for testing, but for reliable operation it's best to use a driver circuit to convert the voltage levels from 3.3v to 5v especially if you have a cable run between the Pi and the Pixel string. There is a [https://github.com/hackerspaceshop/RaspberryPI_WS2801_Bridge schematic] available or you can buy a [http://www.hackerspaceshop.com/raspberrypi-ws2801.html kit].
  
 +
Here are some timings stats collected from the Pi:
 +
 +
{| border=1 cellspacing="0"
 +
! SPI Speed !! Number of bytes || time taken for write()  !! Time on the wire
 +
|-
 +
|| 1MHz || 75 ||  13.5ms || 11.1ms
 +
|-
 +
|| 2MHz || 75 ||  8.1ms || 5.6ms
 +
|-
 +
|| 4MHz || 75 ||  4.7 ms || 3.0 ms
 +
|-
 +
|| 8MHz || 75 ||  3.7ms || 1.4ms
 +
|-
 +
|| 12MHz || 75 ||  3.2ms || 0.75 ms
 +
|-
 +
|| 1MHz || 516 ||  78.5 ms || 76.15  ms
 +
|-
 +
|| 2MHz || 516 ||  40.2 ms || 38.2ms
 +
|-
 +
|| 4MHz || 516 ||  21.5 ms || 19.1 ms
 +
|-
 +
|| 8MHz || 516 ||  12.2ms || 9.6ms
 +
|-
 +
|| 12MHz || 516 ||  7.4ms || 4.83 ms
 +
|-
 +
|}
 +
 +
It also takes somewhere between 3.6 and 4.6 ms to toggle a GPIO pin using the /sys/class/gpio interface. The importance of these numbers will be clear in a minute.
 +
 +
 +
Beyond the Pi, any SPI hardware supported by the Linux kernel should work modulo the timing restrictions. By default OLA looks for devices that match the /dev/spi* .
 +
 +
== Pixel Hardware ==
 +
 +
On the pixel side the following is supported:
 +
* LPD8806, e.g. https://www.adafruit.com/products/306.  since 0.8.27
 +
* WS2801, e.g. https://www.adafruit.com/products/738, since 0.8.28
 +
 +
Each of these uses 3 DMX slots per pixel, so you can drive up to 170 pixels from a universe of DMX data.
  
 
== Hardware Setup ==
 
== Hardware Setup ==
  
TODO(someone): document this.
+
The simplest setup is to connect SCLK (pin 23) to the pixel string's clock line and MOSI (pin 19) to the pixel string's DATA line. You'll need a separate power supply for the pixel string, check the pixel specifications but 1A per m is a good rule of thumb. Don't forget to connect the ground on the power supply to a ground pin (e.g. 25) on the Pi.Do not connect the 5V rail of the pixel power supply to the Pi.
 +
 
 +
=== Multiplexer ===
 +
 
 +
If you want to drive more than one string in parallel you'll need to use a de-multiplexer. For a two-line multiplexer one can use the CE0 and CE1 lines to select the output string. To run more than 2 strings you'll need to use some of the GPIO pins as chip-enables. However these pins are slow (~4ms) which limits the update rate.
 +
 
 +
There is a 8 way demultiplexer schematic [https://drive.google.com/file/d/0B7Z8oqKsoX5HWE1qV2hCeDNNOU0/view?usp=sharing&resourcekey=0-8yDZLnlQ-8FlPaSRPqrIgQ here].
 +
 
 +
== OLA SPI Plugin ==
 +
 
 +
The [[OLA]] SPI plugin is pretty flexible, the primary limitation is how long it takes to write the data out the SPI interface, and this limits the overall refresh rate. Each SPI interface (/dev/spi*) is represented as an OLA Device. Devices can have multiple 'ports' since each port can consume at most one universe of DMX512 data (170 RGB pixels). Each port can be configured (via RDM) with a start address and personality (pixel type). This allows a combination of various strings lengths & pixel hardware types.
 +
 
 +
Each SPI device uses a backend to write the SPI data. Right now there are two types backends available: a software backend which merges the SPI data from one or more ports, and a hardware backend which uses the GPIO pins to control a hardware demultiplexer.
 +
 
 +
=== Timing ===
 +
 
 +
It all comes down to timing. Consider the following example:
 +
 
 +
* 170 LPD8806  pixels per string (results in 516 bytes written)
 +
* Two strings using the built in CE lines to drive a hardware demultipliexer.
 +
* SPI speed of 2Mhz
 +
 
 +
Using timing table above, we can see this will take 40.2 ms x 2 = 80ms to update all pixels. That means you'll only be able to do 12 updates per second. Most DMX systems run at 40 updates per second so we'll end up dropping updates.
 +
 
 +
If we tried to use GPIO pins rather than the CE ones it gets worse. Consider a second example:
 +
 
 +
* 32 WS2801 pixels per string (results in 75 bytes written)
 +
* Four strings using two GPIO lines to drive a hardware demultipliexer.
 +
* SPI speed of 2Mhz
 +
 
 +
Now each write requires setting GPIO pins. Worse case both pins will need to change which adds 8ms. The write itself takes 8.1 ms, so that's 16.1 ms per string or 64.4 ms to update all strings. That gives you an update rate of 15 updates per second. Still not close to DMX's 40 updates per second.
  
 
== Software Setup ==
 
== Software Setup ==
 +
You'll need a suitable [[OLA_Device_Specific_Configuration#SPI|udev config]], so that OLA has permission to talk to your SPI port. There is also some Raspberry Pi specific config (enabling a kernel module) on the same page.
  
Once you have OLA running it's a matter of patching an SPI Output port to a universe and then patching the desired input port.  
+
If you're using the GPIO pins to drive an hardware demultiplexer, you'll need to run the following as root prior to starting olad.
 +
 
 +
<pre>
 +
for pin in 17 21; do
 +
  echo $pin > /sys/class/gpio/export;
 +
  chmod a+w /sys/class/gpio/gpio${pin}/value;
 +
  chmod a+w /sys/class/gpio/gpio${pin}/direction;
 +
done
 +
</pre>
 +
 
 +
Once you have OLA running it's a matter of patching an SPI Output port to a universe and then patching the desired input port. This can be done from the OLA web UI or by using ola_patch
 +
.
 +
[[Image:Ola-spi-artnet.png| thumb|center |200px|Example of an ArtNet controlled LED String]]
  
 
== Configuration ==
 
== Configuration ==
  
 
The type of LED drivers, operating mode and DMX Start Address are configurable via [[RDM]]. Click on the RDM tab and you'll see the options.
 
The type of LED drivers, operating mode and DMX Start Address are configurable via [[RDM]]. Click on the RDM tab and you'll see the options.
 +
 +
[[Image:Ola-spi-rdm.png| thumb|center |200px|Using RDM to set the hardware type and DMX start address]]
 +
  
 
The number of LEDs and SPI speed is set using the ola-spi.conf file.
 
The number of LEDs and SPI speed is set using the ola-spi.conf file.
 +
 +
<pre>
 +
base_uid = 7a70:00000100
 +
device_prefix = spidev
 +
enabled = true
 +
spidev0.0-dmx-address = 1
 +
spidev0.0-personality = 1
 +
spidev0.0-pixel-count = 25
 +
spidev0.0-spi-speed = 100000
 +
spidev0.1-dmx-address = 1
 +
spidev0.1-personality = 2
 +
spidev0.1-pixel-count = 25
 +
spidev0.1-spi-speed = 1000000
 +
</pre>
 +
 +
== Example Configs ==
 +
 +
=== Single Pixel String ===
 +
 +
For a simple single-string output we can use the software backend and ignore the CE lines. This config is for 25 WS2801 pixels running at 1Mhz on /dev/spi0.0.  From the timing information above this should support about 75 updates / second.
 +
 +
<pre>
 +
base_uid = 7a70:00000100                                                                                                                                   
 +
device_prefix = spidev
 +
enabled = true
 +
spidev0.0-0-dmx-address = 1
 +
spidev0.0-0-pixel-count = 25
 +
spidev0.0-0-personality = 1
 +
spidev0.0-backend = software
 +
spidev0.0-ports = 1
 +
spidev0.0-spi-speed = 1000000
 +
</pre>
 +
 +
=== Two Pixel Strings, using the CE lines ===
 +
 +
This example is for 25 WS2801 pixels and 32 LPD8806 pixels. Both strings run at 2Mhz and are connected to the spi bus, and we're using the CE chips to de-multiplex.  We want to CE lines to be active-high.
 +
 +
<pre>
 +
base_uid = 7a70:00000100
 +
device_prefix = spidev
 +
enabled = true
 +
spidev0.0-0-dmx-address = 1
 +
spidev0.0-0-personality = 1
 +
spidev0.0-0-pixel-count = 25
 +
spidev0.0-backend = software
 +
spidev0.0-ports = 1
 +
spidev0.0-spi-ce-high = true
 +
spidev0.0-spi-speed = 200000
 +
spidev0.1-0-dmx-address = 1
 +
spidev0.1-0-personality = 1
 +
spidev0.1-0-pixel-count = 25
 +
spidev0.1-backend = software
 +
spidev0.1-ports = 1
 +
spidev0.1-spi-ce-high = true
 +
spidev0.1-spi-speed = 2000000 
 +
</pre>
 +
 +
=== Two Pixel Strings, using a single output ===
 +
 +
This example is a string of 300 WS2801 pixels. Since this is more than one universe of data, we need to use multiple ports.
 +
 +
<pre>
 +
base_uid = 7a70:00000100
 +
device_prefix = spidev
 +
enabled = true
 +
spidev0.0-0-dmx-address = 1
 +
spidev0.0-0-personality = 1
 +
spidev0.0-0-pixel-count = 150
 +
spidev0.0-1-dmx-address = 1
 +
spidev0.0-1-personality = 1
 +
spidev0.0-1-pixel-count = 150
 +
spidev0.0-backend = software
 +
spidev0.0-ports = 2
 +
spidev0.0-spi-speed = 1000000
 +
spidev0.0-sync-port = -2
 +
</pre>
 +
 +
SPI data is written when data arrives on the second port (sync-port = -2). See the plugin description for more info.
 +
 +
== Exported Variables ==
 +
 +
The SPI plugin exports a number of useful variables. These can be found at http://<ip>:9090/debug. Each is indexed by the device name e.g. /dev/spi0.0 .
 +
 +
;spi-writes
 +
: Number of writes to each SPI device
 +
; spi-write-errors
 +
: Number of writes that resulted in an error
 +
; spi-drops
 +
: Number of DMX updates that were skipped. The happens if DMX data is arriving faster than it can be written to the SPI bus.
 +
 +
== Related Links ==
 +
 +
http://www.solderlab.de/index.php/software/glediator (Pixel Control Software that outputs ArtNet)

Latest revision as of 13:04, 25 December 2021

This page has migrated

This page has migrated to our new site, please see https://www.openlighting.org/ola/tutorials/ola-led-pixels/.

This content will not be updated and is just left here for reference and will be removed at some point in the future, see the link above for the most up-to-date version.


Lpd8806.jpeg

Since March 2013, OLA contains an SPI plugin, which allows you to drive strings of LEDs pixels provided your platform has an SPI interface. Using embedded Linux platforms like the Raspberry Pi, this allows one to build Pixel strings controllable via any of the supported protocols (ArtNet, E1.31, OSC & more) for less than $100.

Alternatively if you don't want network control, you can send DMX512 to the LEDs using the Python, C++ or Java client library running on the host itself.

This page is focused on the Raspberry Pi, but may be applicable to other hardware such as the BeagleBone. If you're using a Raspberry Pi you can save yourself a lot of time by using the pre-built images, see OLA on the Raspberry Pi for details.

Host Hardware

The Raspberry Pi contains three SPI interfaces, but only one of these is wired to the 26-pin connector. The interface comes with 3 chip-enable (CE) lines but again only two are connected (pins 24 & 26). With the default mode, pin 24 is pulled low when the /dev/spi0.0 device is used and pin 26 is pulled low when /dev/spi0.1 is used.

The Pi uses 3.3V logic. You can usually get away with connecting the pins directly to the pixel hardware which uses 5V for testing, but for reliable operation it's best to use a driver circuit to convert the voltage levels from 3.3v to 5v especially if you have a cable run between the Pi and the Pixel string. There is a schematic available or you can buy a kit.

Here are some timings stats collected from the Pi:

SPI Speed Number of bytes time taken for write() Time on the wire
1MHz 75 13.5ms 11.1ms
2MHz 75 8.1ms 5.6ms
4MHz 75 4.7 ms 3.0 ms
8MHz 75 3.7ms 1.4ms
12MHz 75 3.2ms 0.75 ms
1MHz 516 78.5 ms 76.15 ms
2MHz 516 40.2 ms 38.2ms
4MHz 516 21.5 ms 19.1 ms
8MHz 516 12.2ms 9.6ms
12MHz 516 7.4ms 4.83 ms

It also takes somewhere between 3.6 and 4.6 ms to toggle a GPIO pin using the /sys/class/gpio interface. The importance of these numbers will be clear in a minute.


Beyond the Pi, any SPI hardware supported by the Linux kernel should work modulo the timing restrictions. By default OLA looks for devices that match the /dev/spi* .

Pixel Hardware

On the pixel side the following is supported:

Each of these uses 3 DMX slots per pixel, so you can drive up to 170 pixels from a universe of DMX data.

Hardware Setup

The simplest setup is to connect SCLK (pin 23) to the pixel string's clock line and MOSI (pin 19) to the pixel string's DATA line. You'll need a separate power supply for the pixel string, check the pixel specifications but 1A per m is a good rule of thumb. Don't forget to connect the ground on the power supply to a ground pin (e.g. 25) on the Pi.Do not connect the 5V rail of the pixel power supply to the Pi.

Multiplexer

If you want to drive more than one string in parallel you'll need to use a de-multiplexer. For a two-line multiplexer one can use the CE0 and CE1 lines to select the output string. To run more than 2 strings you'll need to use some of the GPIO pins as chip-enables. However these pins are slow (~4ms) which limits the update rate.

There is a 8 way demultiplexer schematic here.

OLA SPI Plugin

The OLA SPI plugin is pretty flexible, the primary limitation is how long it takes to write the data out the SPI interface, and this limits the overall refresh rate. Each SPI interface (/dev/spi*) is represented as an OLA Device. Devices can have multiple 'ports' since each port can consume at most one universe of DMX512 data (170 RGB pixels). Each port can be configured (via RDM) with a start address and personality (pixel type). This allows a combination of various strings lengths & pixel hardware types.

Each SPI device uses a backend to write the SPI data. Right now there are two types backends available: a software backend which merges the SPI data from one or more ports, and a hardware backend which uses the GPIO pins to control a hardware demultiplexer.

Timing

It all comes down to timing. Consider the following example:

  • 170 LPD8806 pixels per string (results in 516 bytes written)
  • Two strings using the built in CE lines to drive a hardware demultipliexer.
  • SPI speed of 2Mhz

Using timing table above, we can see this will take 40.2 ms x 2 = 80ms to update all pixels. That means you'll only be able to do 12 updates per second. Most DMX systems run at 40 updates per second so we'll end up dropping updates.

If we tried to use GPIO pins rather than the CE ones it gets worse. Consider a second example:

  • 32 WS2801 pixels per string (results in 75 bytes written)
  • Four strings using two GPIO lines to drive a hardware demultipliexer.
  • SPI speed of 2Mhz

Now each write requires setting GPIO pins. Worse case both pins will need to change which adds 8ms. The write itself takes 8.1 ms, so that's 16.1 ms per string or 64.4 ms to update all strings. That gives you an update rate of 15 updates per second. Still not close to DMX's 40 updates per second.

Software Setup

You'll need a suitable udev config, so that OLA has permission to talk to your SPI port. There is also some Raspberry Pi specific config (enabling a kernel module) on the same page.

If you're using the GPIO pins to drive an hardware demultiplexer, you'll need to run the following as root prior to starting olad.

for pin in 17 21; do
  echo $pin > /sys/class/gpio/export;
  chmod a+w /sys/class/gpio/gpio${pin}/value;
  chmod a+w /sys/class/gpio/gpio${pin}/direction;
done

Once you have OLA running it's a matter of patching an SPI Output port to a universe and then patching the desired input port. This can be done from the OLA web UI or by using ola_patch .

Example of an ArtNet controlled LED String

Configuration

The type of LED drivers, operating mode and DMX Start Address are configurable via RDM. Click on the RDM tab and you'll see the options.

Using RDM to set the hardware type and DMX start address


The number of LEDs and SPI speed is set using the ola-spi.conf file.

base_uid = 7a70:00000100
device_prefix = spidev
enabled = true
spidev0.0-dmx-address = 1
spidev0.0-personality = 1
spidev0.0-pixel-count = 25
spidev0.0-spi-speed = 100000
spidev0.1-dmx-address = 1
spidev0.1-personality = 2
spidev0.1-pixel-count = 25
spidev0.1-spi-speed = 1000000

Example Configs

Single Pixel String

For a simple single-string output we can use the software backend and ignore the CE lines. This config is for 25 WS2801 pixels running at 1Mhz on /dev/spi0.0. From the timing information above this should support about 75 updates / second.

base_uid = 7a70:00000100                                                                                                                                    
device_prefix = spidev
enabled = true
spidev0.0-0-dmx-address = 1
spidev0.0-0-pixel-count = 25
spidev0.0-0-personality = 1
spidev0.0-backend = software
spidev0.0-ports = 1
spidev0.0-spi-speed = 1000000

Two Pixel Strings, using the CE lines

This example is for 25 WS2801 pixels and 32 LPD8806 pixels. Both strings run at 2Mhz and are connected to the spi bus, and we're using the CE chips to de-multiplex. We want to CE lines to be active-high.

base_uid = 7a70:00000100
device_prefix = spidev
enabled = true
spidev0.0-0-dmx-address = 1
spidev0.0-0-personality = 1
spidev0.0-0-pixel-count = 25
spidev0.0-backend = software
spidev0.0-ports = 1
spidev0.0-spi-ce-high = true
spidev0.0-spi-speed = 200000
spidev0.1-0-dmx-address = 1
spidev0.1-0-personality = 1
spidev0.1-0-pixel-count = 25
spidev0.1-backend = software
spidev0.1-ports = 1
spidev0.1-spi-ce-high = true
spidev0.1-spi-speed = 2000000  

Two Pixel Strings, using a single output

This example is a string of 300 WS2801 pixels. Since this is more than one universe of data, we need to use multiple ports.

base_uid = 7a70:00000100
device_prefix = spidev
enabled = true
spidev0.0-0-dmx-address = 1
spidev0.0-0-personality = 1
spidev0.0-0-pixel-count = 150
spidev0.0-1-dmx-address = 1
spidev0.0-1-personality = 1
spidev0.0-1-pixel-count = 150
spidev0.0-backend = software
spidev0.0-ports = 2
spidev0.0-spi-speed = 1000000
spidev0.0-sync-port = -2

SPI data is written when data arrives on the second port (sync-port = -2). See the plugin description for more info.

Exported Variables

The SPI plugin exports a number of useful variables. These can be found at http://<ip>:9090/debug. Each is indexed by the device name e.g. /dev/spi0.0 .

spi-writes
Number of writes to each SPI device
spi-write-errors
Number of writes that resulted in an error
spi-drops
Number of DMX updates that were skipped. The happens if DMX data is arriving faster than it can be written to the SPI bus.

Related Links

http://www.solderlab.de/index.php/software/glediator (Pixel Control Software that outputs ArtNet)