This picture shows the wiring, it is much easier than any other method of running the addressable LED strings. Since I only have four strings of 150 LED's they are split in half to make 8 strings of 75 LED's each.
Here is my first test program running. I changed the default array of patterns into some text.
I have improved the code to support longer strings:
It now has the ability to do 8 colors and use a character generator!
The sign now breaks down into sections that are each 40 inches long. That is done with eight 3 pin plugs that are identical to what comes on the LED strips.
Here is the code so far:
// BOB Davis Enhanced Version for sending data to 8 Parallel WS2812 strings
// PORTD is Digital Pins 0-7 on the Uno change for other boards.
#define PIXEL_PORT PORTD // Port of the pin the pixels are connected to
#define PIXEL_DDR DDRD // Port of the pin the pixels are connected to
// These are the timing constraints taken mostly from the WS2812 datasheets
#define T0H 400 // Width of a 0 bit in ns
#define RES 6000 // Width of the low gap between bits to cause a frame to latch
// Here are some convience defines to generate actual CPU delays
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED
#define CYCLES_PER_SEC (F_CPU)
#define NS_PER_CYCLE ( NS_PER_SEC / CYCLES_PER_SEC )
#define NS_TO_CYCLES(n) ( (n) / NS_PER_CYCLE )
// Actually send the next set of 8 WS2812B encoded bits to the 8 pins.
// We must to drop to assembler to ensure proper timing
static inline __attribute__ ((always_inline)) void sendBitX8( uint8_t bits ) {
const uint8_t onBits = 0xff; // to send all bits on
const uint8_t offBits = 0x00; // to send all bits off
asm volatile (
"out %[port], %[onBits] \n\t" // 1st step - send T0H high
".rept %[T0HCycles] \n\t" // Execute NOPs to delay
"nop \n\t"
".endr \n\t"
"out %[port], %[bits] \n\t" // Set the output bits to their values
".rept %[T0HCycles] \n\t" // Execute NOPs to delay
"nop \n\t"
".endr \n\t"
"out %[port], %[offBits]\n\t" // last step set all bits low
::
[port] "I" (_SFR_IO_ADDR(PIXEL_PORT)),
[bits] "d" (bits),
[onBits] "d" (onBits),
[offBits] "d" (offBits),
[T0HCycles] "I" (NS_TO_CYCLES(T0H) - 2) // 1-bit width less overhead
);
}
// Set default color for letters 1=red, 2=blue, 0=green
int color=0;
static inline void __attribute__ ((always_inline)) sendPixelRow( uint8_t row ) {
// Send the bit 8 times down every row, each pixel is 8 bits each for R,G,B
for (int c=0; c<3; c++) {
for (int bit=0; bit<8; bit++){
if (color==c)sendBitX8( row );
else sendBitX8( 0x00 );
}
}
}
byte cha[]={ // Can be hex or binary-easier to read
0x80, 0x80, 0xff, 0x80, 0x80, 0x00, //T
B11111111, B10010001, B10010001, B10010001, B10010001, B00000000, //E
B01100001, B10010001, B10010001, B10010001, B10001110, B00000000, //S
B10000000, B10000000, B11111111, B10000000, B10000000, B00000000, //T
B00000000, B10000001, B11111111, B10000001, B00000000, B00000000, //I
B11111111, B01100000, B00011000, B00000110, B11111111, B00000000, //N
B01111110, B10000001, B10000001, B10000101, B01100110, B00000000, //G
B00000000, B01000001, B11111111, B00000001, B00000000, B00000000, //1
B01000001, B10000001, B10000111, B10011001, B01100001, B00000000, //2
B10000001, B10010001, B10010001, B10010001, B01101110, B00000000, //3
B00011000, B00101000, B01001000, B10001000, B11111111, B00000000, //4
B11110001, B10010001, B10010001, B10010001, B10001110, B00000000, //5
};
void setup() {
PIXEL_DDR = 0xff; // Set all row pins to output
}
void loop() {
cli(); // No time for interruptions!
for (int l=0; l<72; l++){ // 66 is number of bytes to send
sendPixelRow(cha[l]);
}
sei();
delay(10); // Wait more than RESET timeout to latch into the LEDs
return;
}