Now that the connections to the Raspberry Pi have been made, and the software loaded, it is time to begin writing the program that will control the LED strip.
The first step is to load the necessary libraries, which in this case is just the WiringPi library. For ease of reading the code, I started by adding definitions for the clock pin and data pin. As you can see, I used the 10 and 11 pins, but any of the IO pins should work just as well.
#include <WiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#define CLOCK_PIN 10
#define DATA_PIN 11
I defined three functions for initialization of the LED strip, called Init(), Reset(), and ClockCycle(). To connect with the LED strip, the two control pins need to be set to output. Furthermore, each time a new set of 32 colours is sent to the LED strip the WS2801 chips require a 0.5ms low signal on both the serial and clock lines, which is the purpose of the Reset() function.
void Init(){
wiringPiSetup();
pinMode(CLOCK_PIN,OUTPUT);
pinMode(DATA_PIN,OUTPUT);
}
void Reset(){
digitalWrite(CLOCK_PIN,LOW);
digitalWrite(DATA_PIN,LOW);
delayMicroseconds(500);
}
void ClockCycle(){
digitalWrite(CLOCK_PIN,HIGH);
delayMicroseconds(1);
digitalWrite(CLOCK_PIN,LOW);
delayMicroseconds(1);
}
Once the pins have been initialized and the reset signal is sent, the actual control of the LED strip is very simple. Take the 24-bit RGB values of the last pixel in the strip (ie the one furthest from the connections to the RasPi board), and start by setting the data line HIGH or LOW depending on whether the most significant bit of the blue value is a 1 or a 0. Then call the ClockCycle() function once to transmit that single bit. Now do the same thing with the second most significant bit of the blue value, and again call the ClockCycle() function. Continue this pattern for the 8 bits of blue, 8 bits of green, and finally 8 bits of red.
In the code examples on the right, I have include three sample functions for turning off a single LED, turning a single LED red, or for giving any RGB colour.
Notice in the SendByte() function that each bit is written explicitly, instead of using a for loop, because this method transmitted the signal slightly faster in speed tests.
Immediately follow the least significant bit of the red value by the most significant bit of the blue value of the next to last LED, and then the next most significant bit and so on. After repeating this process 768 times (ie 24 bits for each of 32 LEDs) stop sendng data, and the LED strip will light up with each LED showing the correct colour.
To transmit data to the LED strip, the data line is set to HIGH or LOW, and followed by a 20ns wide pulse on the clock line. However since the RasPi board cannot operate this quickly, I have used pulses of a few microseconds and they seem to work just fine. (One might wonder why if we need as much speed as possible from the clock cycles, there are two delay functions included. However in testing the code I found that these 1 microsecond delays made the output timing more consistent and caused less errors in the transmission of data)
When you need to send a new block of colours, call the Reset() function to start the process again, and then send another 768 bits along the data line, with a ClockCycle() call after each bit. In principle the colour of the entire strip can be reset about 600 times per second, and so it isn't difficult to achieve the 60 frames per second maximum that human eye can view. In practice this method does produce some errors in the colour bits though, because the clock pin and data pin need to be synchronized, and sometimes the RasPi will send a clock pulse and then do another task before changing the data pin, leading to extra data bits or missing data bits. Personally I haven't worried too much about these errors because they don't affect the lower speed projects I have been using the LED strips for, but with more work on the programming I am sure they can be minimized.
The main() loop in the program then just has to call the Init() function, the Reset() function, and then send strings of 24bits to each of the 32 LEDs. Using variations on this program the LED strip can be made to have chasing lights, or slow colour change lights, or could be used for any number of visual meters.
I encourage the reader to take this sample code (available here as a C file) and modify it to make all sorts of wonderful new projects!
//Turn LED Off
void DrawBlank(){
int i;
for(i=0; i<24; i++){
digitalWrite(DATA_PIN,LOW);
ClockCycle();
}
}
//Make LED Red
void DrawRed(){
int i;
for(i=0; i<24; i++){
if(i>16){
digitalWrite(DATA_PIN,HIGH);
}else{
digitalWrite(DATA_PIN,LOW);
}
ClockCycle();
}
}
//Send one byte on data line
void SendByte(int b){
int i;
digitalWrite(DATA_PIN,b&128);
ClockCycle();
digitalWrite(DATA_PIN,b&64);
ClockCycle();
digitalWrite(DATA_PIN,b&32);
ClockCycle();
digitalWrite(DATA_PIN,b&16);
ClockCycle();
digitalWrite(DATA_PIN,b&8);
ClockCycle();
digitalWrite(DATA_PIN,b&4);
ClockCycle();
digitalWrite(DATA_PIN,b&2);
ClockCycle();
digitalWrite(DATA_PIN,b&1);
ClockCycle();
}
//Make LED the colour given by RGB
void DrawRGB(int r,int g, int b){
SendByte(b);
SendByte(g);
SendByte(r);
}
void main(int argc, char **argv){
Init();
Reset();
int n;
for(;;){
for(n=0; n<32; n++){
DrawRGB(rand()%255,rand()%255,rand()%255);
}
delay(1000);
}
}