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
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.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × LED matrix, 8x8
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 pin | Connects to |
|---|---|
| LED matrix, 8x8 pin GND | Arduino Uno R3 pin GND |
| LED matrix, 8x8 pin CLK | Arduino Uno R3 pin 13 |
| LED matrix, 8x8 pin DIN | Arduino Uno R3 pin 11 |
| LED matrix, 8x8 pin CS | Arduino Uno R3 pin 10 |
| LED matrix, 8x8 pin VCC | Arduino 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.
// 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 editorTroubleshooting
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 untilbeginruns. - The ball goes off the edge This project
KeepLIMITat 8 minus the ball size, so the 2x2 ball stops at 6. - The animation is too fast or slow This project
ChangeFRAME_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.