Built-in project · Arduino Uno R3

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.

The circuit runs here once the page has loaded.

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.

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 pinConnects to
74HC595 shift register (1) pin SHCPArduino Uno R3 pin 13
74HC595 shift register (2) pin SHCPArduino Uno R3 pin 13
74HC595 shift register (1) pin STCPArduino Uno R3 pin 12
74HC595 shift register (2) pin STCPArduino Uno R3 pin 12
74HC595 shift register (1) pin DSArduino Uno R3 pin 11
LED matrix, bicolor 8x8 pin R8Arduino Uno R3 pin 9
LED matrix, bicolor 8x8 pin R7Arduino Uno R3 pin 8
LED matrix, bicolor 8x8 pin R6Arduino Uno R3 pin 7
LED matrix, bicolor 8x8 pin R5Arduino Uno R3 pin 6
LED matrix, bicolor 8x8 pin R4Arduino Uno R3 pin 5
LED matrix, bicolor 8x8 pin R3Arduino Uno R3 pin 4
LED matrix, bicolor 8x8 pin R2Arduino Uno R3 pin 3
LED matrix, bicolor 8x8 pin R1Arduino Uno R3 pin 2
74HC595 shift register (1) pin MRArduino Uno R3 pin 5V
74HC595 shift register (1) pin VCCArduino Uno R3 pin 5V
74HC595 shift register (2) pin MRArduino Uno R3 pin 5V
74HC595 shift register (2) pin VCCArduino Uno R3 pin 5V
74HC595 shift register (1) pin GNDArduino Uno R3 pin GND
74HC595 shift register (1) pin OEArduino Uno R3 pin GND
74HC595 shift register (2) pin GNDArduino Uno R3 pin GND
74HC595 shift register (2) pin OEArduino Uno R3 pin GND
Resistor, 1k Ω (1) pin 2LED matrix, bicolor 8x8 pin RC1
Resistor, 1k Ω (3) pin 2LED matrix, bicolor 8x8 pin RC2
Resistor, 1k Ω (5) pin 2LED matrix, bicolor 8x8 pin RC3
Resistor, 1k Ω (7) pin 2LED matrix, bicolor 8x8 pin RC4
Resistor, 1k Ω (9) pin 2LED matrix, bicolor 8x8 pin RC5
Resistor, 1k Ω (11) pin 2LED matrix, bicolor 8x8 pin RC6
Resistor, 1k Ω (13) pin 2LED matrix, bicolor 8x8 pin RC7
Resistor, 1k Ω (15) pin 2LED matrix, bicolor 8x8 pin RC8
Resistor, 1k Ω (2) pin 2LED matrix, bicolor 8x8 pin GC1
Resistor, 1k Ω (4) pin 2LED matrix, bicolor 8x8 pin GC2
Resistor, 1k Ω (6) pin 2LED matrix, bicolor 8x8 pin GC3
Resistor, 1k Ω (8) pin 2LED matrix, bicolor 8x8 pin GC4
Resistor, 1k Ω (10) pin 2LED matrix, bicolor 8x8 pin GC5
Resistor, 1k Ω (12) pin 2LED matrix, bicolor 8x8 pin GC6
Resistor, 1k Ω (14) pin 2LED matrix, bicolor 8x8 pin GC7
Resistor, 1k Ω (16) pin 2LED matrix, bicolor 8x8 pin GC8
Resistor, 1k Ω (3) pin 174HC595 shift register (1) pin Q1
Resistor, 1k Ω (5) pin 174HC595 shift register (1) pin Q2
Resistor, 1k Ω (7) pin 174HC595 shift register (1) pin Q3
Resistor, 1k Ω (9) pin 174HC595 shift register (1) pin Q4
Resistor, 1k Ω (11) pin 174HC595 shift register (1) pin Q5
Resistor, 1k Ω (13) pin 174HC595 shift register (1) pin Q6
Resistor, 1k Ω (15) pin 174HC595 shift register (1) pin Q7
74HC595 shift register (2) pin DS74HC595 shift register (1) pin Q7S
Resistor, 1k Ω (1) pin 174HC595 shift register (1) pin Q0
Resistor, 1k Ω (4) pin 174HC595 shift register (2) pin Q1
Resistor, 1k Ω (6) pin 174HC595 shift register (2) pin Q2
Resistor, 1k Ω (8) pin 174HC595 shift register (2) pin Q3
Resistor, 1k Ω (10) pin 174HC595 shift register (2) pin Q4
Resistor, 1k Ω (12) pin 174HC595 shift register (2) pin Q5
Resistor, 1k Ω (14) pin 174HC595 shift register (2) pin Q6
Resistor, 1k Ω (16) pin 174HC595 shift register (2) pin Q7
Resistor, 1k Ω (2) pin 174HC595 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.

sketch.ino · Arduino Uno R3
// 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 in drawFor and 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.