Skip to content

Instantly share code, notes, and snippets.

@richardjkendall
Created May 29, 2020 05:38
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save richardjkendall/55132cec195bd49331d244948102d0a1 to your computer and use it in GitHub Desktop.
Rainbow effect on 8x8 RGB common anode LED matrix
#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