Not long ago, I purchased some LED spots from Thomann. Of course I wanted to control them somehow. Thus, I bought an USB-to-DMX-interface and a fitting adapter cable, too. And I started to learn, how to use QLC+.
While playing with QLC+ I discovered a video shared by it's main developer. This video shows an LED matrix controlled using QLC+.
And I thought: I want that too!the LED display
I started looking for affordable LED stripes with individually controllable pixels. I found some on eBay; Basically, there are four different kinds of stripes around differing in the chips they deploy:
The WS8201 communicates using SPI. For that kind of stripe there is a tutorial how to drive it using a Raspberry Pi. That's likely to be the means of control the QLC+ developer Massimo Callegari used.
I decided to buy three stripes with WS8211 with a total length of 15 m because they are cheaper. Those 15 meters hold 900 LEDs. I planned to build a matrix with 75×12 pixels. The stripes arrived the day after, so I searched for an appropriate wooden board and sticked the stripes onto it.Power supply
Although a single LED does not consume much energy, a total of 900 LEDs will: 900 × 60 mA will eat up a whole 18 amps, or 216 watts at 12 V. Therefore it is important to supply each of the 12 stripes individually and use a power supply with enough power. Fortunately, I had a spare server power unit and started to solder cables to the stripes: Because neighbouring stripes are pointing in opposite directions, I have same electrical poles next to each other such that I was able to connect them to a common cable:
As the server power unit is an ATX supply, one needs to connect the green (power) cable on the large multi-line plug with one of the black ones (ground) to turn it on.
Connecting the data lines was easy. One just has to connect the middle poles on the ends thereby following the arrows along the stripes.
In the images you can see, that on some stripes I also interconnected the power lines. I started to do this before I thought of the power connections and these connections at the ends of the stripes are not required.Feeding the matrix with data
For a first proof of concept, I wanted to use an already present Raspberry Pi. A short search in the webs led me to a short python program, fitting my needs:
Following the instructions, I connected the ground (Pin 6) of my Raspberry to the minus pole of the LED stripes and Pin 12 (GPIO 18) to the data input connector of the very first stripe segment.
Then I launched the following commands on the Raspberry:
sudo apt-get update
sudo apt-get install gcc make build-essential python-dev git scons swig
sudo echo "blacklist snd_bcm2835" > /etc/modprobe.d/snd-blacklist.conf
sudo nano /boot/config.txt
to alter the line
After a reboot:
git clone https://github.com/jgarff/rpi_ws281x
sudo python setup.py build
sudo python setup.py install
Test script to let python control the leds
As described in the instructions, I started an editor with
sudo nano examples/strandtest.py and adjusted the line
LED_COUNT = 16 # Number of LED pixels. – I have some 900 pixels.
Re-checked that the right pin is configured for the data line:
LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!).
And we are set to test the whole thing:
sudo PYTHONPATH=".:build/lib.linux-armv7l-2.7" python examples/strandtest.py
And there was light! But something was odd:
I noticed that I had missed something in the description of the led stripes. On the stripes I purchased, each chip controls three RGB LEDs, meaning my effective resolution was only 300 pixels! Damn!
After a short moment of sadness I accepted that fact and re-adjusted the corresponding line in the script:
LED_COUNT = 300 # Number of LED pixels.
Control via QLC+
The original goal was to control the led matrix using QLC+. I already knew that this software was able to run on the Raspberry and to drive WS201 LEDs utilizing SPI protocol. Now I needed to find a solution to drive WS8211 stripes.
I had different ideas in mind:
- convert the SPI signals electronically. I found two circuits that seemed appropriate:
- SPI nach WS2811-Umsetzer mittels Standard-Logik
- WS2811 SPI Driver Using One Transistor And Passives
I did not try to implement any of them, since I found another solution (below).
- convert the SPI signal with a micro controller
I tried to use an Arduino in SPI slave mode to receive the SPI data and then drive the LEDs using bit banging. Unfortunately, I did not succeed: for a reason unknown to me, the Arduino always missed the first bit of each incoming packet. Moreover, the frequency of the SPI transmission is way to high for the Arduino controller.
- converting SPI by software
I thought maybe it could be possible to provide a virtual SPI port to QLC+, grab the data passed to it and actually send them by bit banging. I have to admit, I have no clue how one could do this.
As mentioned, I did not master any of these ideas, but I found another solution:
Without any problems, a python program on the raspberry can receive ArtNet packets and control the matrix with a modified version of the Strandtest.Py program!
The resulting Python script can be run easily:
sudo PYTHONPATH="rpi_ws281x/python/build/lib.linux-armv7l-2.7/" python artnet.py --brightness=255 -c
rpi_ws281x/python/build/lib.linux-armv7l-2.7/ is to be replaced by the corresponding directory (see → Software installation).
The script is tailored for my hardware setup:
The LED matrix is divided into two universes, each with 150 LEDs, in QLC+.
Those are adressed as ArtNet universes 0 and 1 in the local network.
Thus, the script only recieves data from these universes and applies data from universe 0 to the LEDs with index 1 to 150 and universe 1 to LEDs 151 to 300, respectively.
You will probably need to adjust the program for other setups!Performance
For my first tests, I utilized a Raspberry Pi Model 1. With its single core, this device is rather slow. Too slow to process the commands from QLC+ in real time. I transferred the whole software to a Raspberry Pi 3 afterwards. And, well, it works!
1) WS2811, WS2812 and WS2812B are compatible. They are different makeups of the same Controller type.