Red, green and orange on a bicolor matrix, on an Arduino Uno
A red and green 8x8 matrix: the Uno drives its eight rows and two chained 74HC595s sink the sixteen columns, so a smiley turns green, orange and red. The whole build, an Arduino Uno and 19 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Advanced About 60 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $36. On Mokxi they're free.
What you'll learn
- Chaining two shift registers to get 16 outputs
- Multiplexing: lighting one row at a time
- Why column data is sent inverted
- Mixing red and green LEDs to make orange
- Bit patterns that describe a picture
- Difficulty: Advanced
- Time: About 60 minutes
- Board: Arduino Uno R3
- Parts: 21
How it works
The matrix has 8 rows and 16 column wires: 8 red and 8 green. The Uno drives the rows directly on pins 2 to 9. Two chained 74HC595 shift registers drive the 16 columns, each through a 1k resistor.
An LED lights when its row is HIGH and its column is LOW. The sketch turns on one row at a time, very fast, so your eye sees the whole smiley face.
Red alone looks red, green alone looks green, and both together make orange. The sketch shows green, orange, then red, 600 ms each, then goes dark for 300 ms and repeats.
Parts list
21 parts, plus the jumper wires. They retail for about $36; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × LED matrix, bicolor 8x8
- 2 × 74HC595 shift registerIn LED Cube Kit.
- 16 × Resistor, 1k ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| 74HC595 shift register (1) pin SHCP | Arduino Uno R3 pin 13 |
| 74HC595 shift register (2) pin SHCP | Arduino Uno R3 pin 13 |
| 74HC595 shift register (1) pin STCP | Arduino Uno R3 pin 12 |
| 74HC595 shift register (2) pin STCP | Arduino Uno R3 pin 12 |
| 74HC595 shift register (1) pin DS | Arduino Uno R3 pin 11 |
| LED matrix, bicolor 8x8 pin R8 | Arduino Uno R3 pin 9 |
| LED matrix, bicolor 8x8 pin R7 | Arduino Uno R3 pin 8 |
| LED matrix, bicolor 8x8 pin R6 | Arduino Uno R3 pin 7 |
| LED matrix, bicolor 8x8 pin R5 | Arduino Uno R3 pin 6 |
| LED matrix, bicolor 8x8 pin R4 | Arduino Uno R3 pin 5 |
| LED matrix, bicolor 8x8 pin R3 | Arduino Uno R3 pin 4 |
| LED matrix, bicolor 8x8 pin R2 | Arduino Uno R3 pin 3 |
| LED matrix, bicolor 8x8 pin R1 | Arduino Uno R3 pin 2 |
| 74HC595 shift register (1) pin MR | Arduino Uno R3 pin 5V |
| 74HC595 shift register (1) pin VCC | Arduino Uno R3 pin 5V |
| 74HC595 shift register (2) pin MR | Arduino Uno R3 pin 5V |
| 74HC595 shift register (2) pin VCC | Arduino Uno R3 pin 5V |
| 74HC595 shift register (1) pin GND | Arduino Uno R3 pin GND |
| 74HC595 shift register (1) pin OE | Arduino Uno R3 pin GND |
| 74HC595 shift register (2) pin GND | Arduino Uno R3 pin GND |
| 74HC595 shift register (2) pin OE | Arduino Uno R3 pin GND |
| Resistor, 1k Ω (1) pin 2 | LED matrix, bicolor 8x8 pin RC1 |
| Resistor, 1k Ω (3) pin 2 | LED matrix, bicolor 8x8 pin RC2 |
| Resistor, 1k Ω (5) pin 2 | LED matrix, bicolor 8x8 pin RC3 |
| Resistor, 1k Ω (7) pin 2 | LED matrix, bicolor 8x8 pin RC4 |
| Resistor, 1k Ω (9) pin 2 | LED matrix, bicolor 8x8 pin RC5 |
| Resistor, 1k Ω (11) pin 2 | LED matrix, bicolor 8x8 pin RC6 |
| Resistor, 1k Ω (13) pin 2 | LED matrix, bicolor 8x8 pin RC7 |
| Resistor, 1k Ω (15) pin 2 | LED matrix, bicolor 8x8 pin RC8 |
| Resistor, 1k Ω (2) pin 2 | LED matrix, bicolor 8x8 pin GC1 |
| Resistor, 1k Ω (4) pin 2 | LED matrix, bicolor 8x8 pin GC2 |
| Resistor, 1k Ω (6) pin 2 | LED matrix, bicolor 8x8 pin GC3 |
| Resistor, 1k Ω (8) pin 2 | LED matrix, bicolor 8x8 pin GC4 |
| Resistor, 1k Ω (10) pin 2 | LED matrix, bicolor 8x8 pin GC5 |
| Resistor, 1k Ω (12) pin 2 | LED matrix, bicolor 8x8 pin GC6 |
| Resistor, 1k Ω (14) pin 2 | LED matrix, bicolor 8x8 pin GC7 |
| Resistor, 1k Ω (16) pin 2 | LED matrix, bicolor 8x8 pin GC8 |
| Resistor, 1k Ω (3) pin 1 | 74HC595 shift register (1) pin Q1 |
| Resistor, 1k Ω (5) pin 1 | 74HC595 shift register (1) pin Q2 |
| Resistor, 1k Ω (7) pin 1 | 74HC595 shift register (1) pin Q3 |
| Resistor, 1k Ω (9) pin 1 | 74HC595 shift register (1) pin Q4 |
| Resistor, 1k Ω (11) pin 1 | 74HC595 shift register (1) pin Q5 |
| Resistor, 1k Ω (13) pin 1 | 74HC595 shift register (1) pin Q6 |
| Resistor, 1k Ω (15) pin 1 | 74HC595 shift register (1) pin Q7 |
| 74HC595 shift register (2) pin DS | 74HC595 shift register (1) pin Q7S |
| Resistor, 1k Ω (1) pin 1 | 74HC595 shift register (1) pin Q0 |
| Resistor, 1k Ω (4) pin 1 | 74HC595 shift register (2) pin Q1 |
| Resistor, 1k Ω (6) pin 1 | 74HC595 shift register (2) pin Q2 |
| Resistor, 1k Ω (8) pin 1 | 74HC595 shift register (2) pin Q3 |
| Resistor, 1k Ω (10) pin 1 | 74HC595 shift register (2) pin Q4 |
| Resistor, 1k Ω (12) pin 1 | 74HC595 shift register (2) pin Q5 |
| Resistor, 1k Ω (14) pin 1 | 74HC595 shift register (2) pin Q6 |
| Resistor, 1k Ω (16) pin 1 | 74HC595 shift register (2) pin Q7 |
| Resistor, 1k Ω (2) pin 1 | 74HC595 shift register (2) pin Q0 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// A red and green 8x8 matrix: eight rows from the Uno, sixteen columns from
// two chained 74HC595s.
//
// rows R1..R8 (the anodes) -> pins 2 to 9
// 74HC595 DS 11, SH_CP 13, ST_CP 12; the first chip's Q7S into the second's DS
// first 595 Q0..Q7 -> red columns RC1..RC8, each through 1k
// second 595 Q0..Q7 -> green columns GC1..GC8, each through 1k
//
// A column's LED lights when its row is HIGH and its column output LOW, so the
// column bytes are sent inverted. One row is on at a time; red and green
// together make orange.
const uint8_t ROW_PINS[8] = {2, 3, 4, 5, 6, 7, 8, 9};
const uint8_t DATA = 11, LATCH = 12, CLOCK = 13;
const uint8_t FACE[8] = {0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C};
void columns(uint8_t red, uint8_t green) {
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, (uint8_t)~green); // ends up in the second chip
shiftOut(DATA, CLOCK, MSBFIRST, (uint8_t)~red);
digitalWrite(LATCH, HIGH);
}
void drawFor(bool red, bool green, unsigned long ms) {
unsigned long start = millis();
while (millis() - start < ms) {
for (uint8_t r = 0; r < 8; r++) {
// Q0 is column 1, so the leftmost dot is bit 0: reverse the row's bits.
uint8_t row = 0;
for (uint8_t b = 0; b < 8; b++) row |= ((FACE[r] >> b) & 1) << (7 - b);
columns(red ? row : 0, green ? row : 0);
digitalWrite(ROW_PINS[r], HIGH);
delay(2);
digitalWrite(ROW_PINS[r], LOW);
}
}
}
void setup() {
for (uint8_t i = 0; i < 8; i++) pinMode(ROW_PINS[i], OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
}
void loop() {
drawFor(false, true, 600); // green
drawFor(true, true, 600); // orange
drawFor(true, false, 600); // red
delay(300); // dark, then green again
}
Code walkthrough
The key functions of the sketch, and what each one does.
columns sketch.ino
Sends two bytes to the chained registers and latches them. The green byte goes first, so it ends up in the second chip. Both are flipped with ~ because a column must be LOW to light.
void columns(uint8_t red, uint8_t green) {
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, (uint8_t)~green); // ends up in the second chip
shiftOut(DATA, CLOCK, MSBFIRST, (uint8_t)~red);
digitalWrite(LATCH, HIGH);
}drawFor sketch.ino
Repeats the picture for a given number of milliseconds. For each row it sets the column bytes, turns that row HIGH for 2 ms, then turns it off. It also reverses the bits of each FACE row, because Q0 is the leftmost column.
void drawFor(bool red, bool green, unsigned long ms) {
unsigned long start = millis();
while (millis() - start < ms) {
for (uint8_t r = 0; r < 8; r++) {
// Q0 is column 1, so the leftmost dot is bit 0: reverse the row's bits.
uint8_t row = 0;
for (uint8_t b = 0; b < 8; b++) row |= ((FACE[r] >> b) & 1) << (7 - b);
columns(red ? row : 0, green ? row : 0);
digitalWrite(ROW_PINS[r], HIGH);
delay(2);
digitalWrite(ROW_PINS[r], LOW);
}
}
}loop sketch.ino
Calls drawFor three times with different color flags: green, both for orange, then red. Each lasts 600 ms. A 300 ms delay leaves the matrix dark before it starts over.
void loop() {
drawFor(false, true, 600); // green
drawFor(true, true, 600); // orange
drawFor(true, false, 600); // red
delay(300); // dark, then green again
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The face is mirrored left to right. This project
Q0 is column 1, so the leftmost dot is bit 0. Check the row bit reversal indrawForand that Q0 to Q7 go to columns 1 to 8 in order. - Red and green are swapped, or only one color shows. This project
The first chip drives the red columns RC1 to RC8 and the second drives green GC1 to GC8. Chain Q7S of the first chip into DS of the second. - The matrix is dark. This project
Tie OE to GND and MR to 5V on both registers. OE is active low and MR clears the chip when low. - Some dots are dim, or the wrong colors light. LED matrix
Find the pinout first, since rows and columns for red and green are separate. Wire a resistor to each line, around 220 to 330 ohms. - The display flickers or pins are overloaded. LED matrix
Multiplex it fast, over 100 Hz per frame, or use a driver like the MAX7219 or shift registers. Do not drive many LEDs directly from one pin. - Outputs show garbage, or the register never clears. 74HC595 shift register
Tie OE low and SRCLR (pin 10) high. Left floating, these pins make the chip behave randomly. Then pulse the latch pin after shifting the byte. - The bits come out in the wrong order, or LEDs are dim. 74HC595 shift register
Choose MSBFIRST or LSBFIRST in shiftOut to flip the order. Give each LED its own resistor, since each output can source only about 6 mA safely. - The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.