Built-in project · Arduino Uno R3

Matrix ball on an Arduino Uno

An Arduino Uno bounces a dot around an 8x8 LED matrix on a MAX7219, three wires and eight registers. The whole build, an Arduino Uno and 1 more part, 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.

Intermediate About 15 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $35. On Mokxi they're free.

Step by step, with the wiring and the common mistakes: Arduino MAX7219 8x8 LED Matrix: Wiring and Code

The circuit runs here once the page has loaded.

What you'll learn

  • Driving an LED matrix with a MAX7219
  • Three wire serial data: data, clock and chip select
  • Animating with position and direction variables
  • Bit flags to remember which wall was hit
  • Difficulty: Intermediate
  • Time: About 15 minutes
  • Board: Arduino Uno R3
  • Parts: 3

How it works

A MAX7219 chip drives the 8x8 LED matrix. It holds eight registers, one for each row, and scans them out by itself. The Uno sends it data on three wires: DIN on 11, CLK on 13 and CS on 10.

A 2x2 ball moves one pixel each frame, every 90 ms. When it hits a wall it reverses direction and that wall lights for a frame. Each frame the sketch clears the picture, draws the wall and the ball and sends it all with show. A bounce also bumps the brightness.

Parts list

3 parts, plus the jumper wires. They retail for about $35; on Mokxi they're free.

Kits that can build it

This starter kit has every part in the circuit. Each kit's page lists what else it can build.

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
LED matrix, 8x8 pin GNDArduino Uno R3 pin GND
LED matrix, 8x8 pin CLKArduino Uno R3 pin 13
LED matrix, 8x8 pin DINArduino Uno R3 pin 11
LED matrix, 8x8 pin CSArduino Uno R3 pin 10
LED matrix, 8x8 pin VCCArduino Uno R3 pin 5V

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
// Matrix ball: a dot bouncing round an 8x8 LED matrix on a MAX7219.
//
// Wiring, module to board:
//   DIN -> pin 11
//   CS  -> pin 10   (marked LOAD on some boards)
//   CLK -> pin 13
//   VCC -> 5 V, GND -> GND
//
// The MAX7219 holds eight digit registers and scans them out itself. On a
// matrix board those eight registers are the eight rows and the eight segment
// outputs are the columns, so writing a row register *is* drawing a row. The
// driver in mokxi_max7219.h keeps the eight bytes in RAM, lets the sketch poke
// pixels into them, and pushes all eight out on show().
//
// Every register comes up zero at power-on (shut down, one row scanned,
// minimum brightness), which is why nothing happens on a real board until
// begin() writes Shutdown, Scan Limit and Intensity.
//
// The ball is 2x2 and moves one pixel a frame. When it hits a wall it bounces
// and that wall lights for a frame, so the collision is something you can see
// rather than something you have to believe.

#include "mokxi_max7219.h"

const uint8_t DIN_PIN = 11;
const uint8_t CS_PIN = 10;
const uint8_t CLK_PIN = 13;

Max7219 matrix(DIN_PIN, CS_PIN, CLK_PIN, 1);

// Top left of the 2x2 ball, so it runs 0..6 on both axes.
const int8_t BALL = 2;
const int8_t LIMIT = 8 - BALL;

int8_t x = 0;
int8_t y = 0;
int8_t dx = 1;
int8_t dy = 1;

// Which wall was hit last frame: one bit each, top right bottom left.
uint8_t flash = 0;

const int FRAME_MS = 90;

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Uno: a ball round an 8x8 matrix");
  matrix.begin(8);
}

void loop() {
  x = (int8_t)(x + dx);
  y = (int8_t)(y + dy);
  flash = 0;

  if (x <= 0) {
    x = 0;
    dx = 1;
    flash |= 0x08;  // left
  } else if (x >= LIMIT) {
    x = LIMIT;
    dx = -1;
    flash |= 0x02;  // right
  }
  if (y <= 0) {
    y = 0;
    dy = 1;
    flash |= 0x01;  // top
  } else if (y >= LIMIT) {
    y = LIMIT;
    dy = -1;
    flash |= 0x04;  // bottom
  }

  matrix.clear();
  if (flash & 0x01) matrix.fillRect(0, 0, 8, 1, true);
  if (flash & 0x02) matrix.fillRect(7, 0, 1, 8, true);
  if (flash & 0x04) matrix.fillRect(0, 7, 8, 1, true);
  if (flash & 0x08) matrix.fillRect(0, 0, 1, 8, true);
  matrix.fillRect(x, y, BALL, BALL, true);
  matrix.show();

  // A bounce is also a flicker of brightness, which costs one packet.
  matrix.setIntensity(flash ? 15 : 8);

  delay(FRAME_MS);
}

Code walkthrough

The key functions of the sketch, and what each one does.

setup sketch.ino

Opens serial and calls matrix.begin with brightness 8. This matters on real hardware, because the MAX7219 powers up shut down and does nothing until it is told to wake and how many rows to scan.

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Uno: a ball round an 8x8 matrix");
  matrix.begin(8);
}

loop sketch.ino

Moves the ball by dx and dy. At an edge it clamps the position, flips the direction and sets a bit in flash for that wall. It clears the matrix, draws the lit wall and the ball, calls matrix.show, then sets brightness 15 on a bounce and 8 otherwise.

void loop() {
  x = (int8_t)(x + dx);
  y = (int8_t)(y + dy);
  flash = 0;

  if (x <= 0) {
    x = 0;
    dx = 1;
    flash |= 0x08;  // left
  } else if (x >= LIMIT) {
    x = LIMIT;
    dx = -1;
    flash |= 0x02;  // right
  }
  if (y <= 0) {
    y = 0;
    dy = 1;
    flash |= 0x01;  // top
  } else if (y >= LIMIT) {
    y = LIMIT;
    dy = -1;
    flash |= 0x04;  // bottom
  }

  matrix.clear();
  if (flash & 0x01) matrix.fillRect(0, 0, 8, 1, true);
  if (flash & 0x02) matrix.fillRect(7, 0, 1, 8, true);
  if (flash & 0x04) matrix.fillRect(0, 7, 8, 1, true);
  // ... 9 more lines in the editor

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The matrix stays dark This project
    Check DIN on 11, CS on 10, CLK on 13, and power and ground. The chip stays shut down until begin runs.
  • The ball goes off the edge This project
    Keep LIMIT at 8 minus the ball size, so the 2x2 ball stops at 6.
  • The animation is too fast or slow This project
    Change FRAME_MS, the delay between frames.
  • The matrix is blank after upload. LED matrix
    On power up the MAX7219 is in shutdown mode with intensity 0. Wake it, set intensity, set scan limit to all 8 digits, and clear the display.
  • Dim, flickering, or wrong rows. LED matrix
    Set the ISET resistor right for your LEDs (about 10 kohm for 40 mA). Power from 5 V with a 0.1 uF capacitor, and chain DOUT to the next DIN.
  • Upload fails or nothing runs after wiring pins 0 and 1 to a module. Arduino Uno R3
    Pins 0 and 1 are the USB serial port. Move the module to other pins, or unplug it while uploading. Also check the right board is selected.
  • Pins misbehave or the board resets when you power motors or servos from it. Arduino Uno R3
    Each I/O pin gives about 20 mA, 40 mA max. Power motors and servos from their own supply and join its ground to the Uno's GND.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.