Rainbow effect on 8x8 RGB common anode LED matrix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SPI.h> | |
// port register maniuplation macros | |
#define sbi(port, bit) (port) |= (1 << (bit)) | |
#define cbi(port, bit) (port) &= ~(1 << (bit)) | |
// pins | |
// note if you change the latchpin, you will need to change the code in the loop as this is hard | |
// coded to make use of faster port register manipulation | |
int latchPin = 8; // Pin connected to ST_CP of 74HC595 | |
int clockPin = 13; // Pin connected to SH_CP of 74HC595 | |
int dataPin = 11; // Pin connected to DS of 74HC595 | |
// these arrays hold the pixel configuration for each colour channel | |
// 0 = off | |
// 4 = on 50% of the time | |
// 8 = on all the time | |
// based on measurements the rows are being refreshed at 1.56kHz with a duty cycle of ~12-13% | |
// so 100% for the lamps is really 13% | |
int blevels[8][8] = { | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8}, | |
{8,0,0,0,0,8,8,8} | |
}; | |
int rlevels[8][8] = { | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8}, | |
{0,0,8,8,8,8,1,8} | |
}; | |
int glevels[8][8] = { | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8}, | |
{0,8,8,2,0,0,0,8} | |
}; | |
// counter to hold the 'frame number' used to drive PWM | |
int pwmc = 1; | |
// counter for column moves | |
long colm = 1; | |
// mapping from columns to array entries | |
int col1 = 7; | |
int col2 = 6; | |
int col3 = 5; | |
int col4 = 4; | |
int col5 = 3; | |
int col6 = 2; | |
int col7 = 1; | |
int col8 = 0; | |
void setup() { | |
// setup the pins | |
pinMode(latchPin, OUTPUT); | |
pinMode(clockPin, OUTPUT); | |
pinMode(dataPin, OUTPUT); | |
// setup SPI | |
SPI.setClockDivider(SPI_CLOCK_DIV2); | |
SPI.setBitOrder(MSBFIRST); | |
SPI.setDataMode(SPI_MODE0); | |
SPI.begin(); | |
// set pwmc | |
pwmc = 1; | |
} | |
void loop() { | |
// reset pwm counter if too high | |
if (pwmc > 8) { | |
pwmc = 1; | |
} | |
// manage col maps | |
if (colm == 500) { | |
col1 = col1 == 7 ? 0 : col1 + 1; | |
col2 = col2 == 7 ? 0 : col2 + 1; | |
col3 = col3 == 7 ? 0 : col3 + 1; | |
col4 = col4 == 7 ? 0 : col4 + 1; | |
col5 = col5 == 7 ? 0 : col5 + 1; | |
col6 = col6 == 7 ? 0 : col6 + 1; | |
col7 = col7 == 7 ? 0 : col7 + 1; | |
col8 = col8 == 7 ? 0 : col8 + 1; | |
colm = 1; | |
} | |
// refresh each row | |
int row = 1; | |
for (int numberToDisplay = 0; numberToDisplay < 8; numberToDisplay++) { | |
// take the latchPin low so the LEDs don't change while you're sending in bits: | |
// using port register as it is quicker, bit 0 is pin 8 | |
cbi(PORTB, 0); | |
// construct blue values | |
int blue = (blevels[numberToDisplay][col1] >= pwmc ? B10000000 : B00000000) | | |
(blevels[numberToDisplay][col2] >= pwmc ? B01000000 : B00000000) | | |
(blevels[numberToDisplay][col3] >= pwmc ? B00100000 : B00000000) | | |
(blevels[numberToDisplay][col4] >= pwmc ? B00010000 : B00000000) | | |
(blevels[numberToDisplay][col5] >= pwmc ? B00001000 : B00000000) | | |
(blevels[numberToDisplay][col6] >= pwmc ? B00000100 : B00000000) | | |
(blevels[numberToDisplay][col7] >= pwmc ? B00000010 : B00000000) | | |
(blevels[numberToDisplay][col8] >= pwmc ? B00000001 : B00000000); | |
// construct red values | |
int red = (rlevels[numberToDisplay][col1] >= pwmc ? B10000000 : B00000000) | | |
(rlevels[numberToDisplay][col2] >= pwmc ? B01000000 : B00000000) | | |
(rlevels[numberToDisplay][col3] >= pwmc ? B00100000 : B00000000) | | |
(rlevels[numberToDisplay][col4] >= pwmc ? B00010000 : B00000000) | | |
(rlevels[numberToDisplay][col5] >= pwmc ? B00001000 : B00000000) | | |
(rlevels[numberToDisplay][col6] >= pwmc ? B00000100 : B00000000) | | |
(rlevels[numberToDisplay][col7] >= pwmc ? B00000010 : B00000000) | | |
(rlevels[numberToDisplay][col8] >= pwmc ? B00000001 : B00000000); | |
// construct red values | |
int green = (glevels[numberToDisplay][col1] >= pwmc ? B10000000 : B00000000) | | |
(glevels[numberToDisplay][col2] >= pwmc ? B01000000 : B00000000) | | |
(glevels[numberToDisplay][col3] >= pwmc ? B00100000 : B00000000) | | |
(glevels[numberToDisplay][col4] >= pwmc ? B00010000 : B00000000) | | |
(glevels[numberToDisplay][col5] >= pwmc ? B00001000 : B00000000) | | |
(glevels[numberToDisplay][col6] >= pwmc ? B00000100 : B00000000) | | |
(glevels[numberToDisplay][col7] >= pwmc ? B00000010 : B00000000) | | |
(glevels[numberToDisplay][col8] >= pwmc ? B00000001 : B00000000); | |
// send the row green byte, red byte, blue byte and then the row access byte | |
// because colours are cathodes, the 595s must sink current, hence bitwise not on byte being sent | |
SPI.transfer(~green); | |
SPI.transfer(~red); | |
SPI.transfer(~blue); | |
SPI.transfer(row); | |
// rows are accessed by taking the pins on the first shift register high (source current) | |
row = row * 2; | |
// take the latch pin high so the LEDs will light up | |
sbi(PORTB, 0); | |
// slight delay to have the lamps stay lit for a bit longer | |
delayMicroseconds(40); | |
} | |
// increment pwm counter | |
pwmc++; | |
// increment col counter | |
colm++; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment