An Arduino MAX7219 LED matrix, with a ball bouncing on it
- 192parts on the bench
- 25boards running now
- 1.00xreal time, on every board
Sixty-four LEDs would need sixty-four pins if you wired them one by one, and an Arduino Uno has twenty. The MAX7219 is the chip that solves that: it sits on the back of the cheap red 8x8 matrix modules, takes three wires from the board, and does the scanning of all sixty-four LEDs itself. The circuit above is an Uno bouncing a two by two dot around one of those matrices, running in your browser on the same sketch you can read below.
Each time the ball hits a wall, that whole edge lights for one frame and the brightness jumps, so a bounce is something you can see rather than something you take on trust. Open it in the editor and you can change the speed, the size of the ball or what it draws.
What you need
- An Arduino Uno
- An 8x8 LED matrix module with a MAX7219 on the back (the common red kind)
- Five jumper wires, female to male if the module has header pins
- A breadboard for the power rails (optional)
Wiring
How the MAX7219 draws a picture
The chip holds eight registers of eight bits each, one register per row of the matrix. A 1 bit is a lit LED and a 0 bit is a dark one, with bit 7 as the leftmost column. So the whole picture is eight bytes, and changing a row of the display is writing one byte to one register. The chip then lights the rows one at a time, fast enough that your eye sees all eight at once.
Talking to it is a packet of sixteen bits: pull CS low, clock out a register address and a data byte on DIN and CLK, and raise CS. The rising edge of CS is what makes the chip act on the packet. Registers 1 to 8 are the rows; the others set the brightness (sixteen levels), how many rows to scan, whether to decode digits, and whether the chip is shut down.
That last one catches everyone once. At power-on every register is zero, which means shut down, one row scanned and minimum brightness. A matrix that stays dark is almost always a sketch that never wrote the Shutdown, Scan Limit and Intensity registers. The begin() call in the sketch does exactly that.
The sketch, frame by frame
The driver keeps the eight row bytes in the Uno’s RAM. The loop moves the ball one pixel, bounces it off any wall it reached, clears the buffer, draws the ball with fillRect, draws a line along any wall that was hit, and calls show(), which sends all eight rows to the chip. Then it waits 90 milliseconds, so the ball moves about eleven times a second.
Keeping the picture in RAM and sending it all at once is the pattern every matrix library uses. It means drawing is just setting bits in an array, and the slow part, the serial transfer, happens once per frame instead of once per pixel.
matrix.clear();
if (flash & 0x01) matrix.fillRect(0, 0, 8, 1, true); // top wall
if (flash & 0x02) matrix.fillRect(7, 0, 1, 8, true); // right wall
if (flash & 0x04) matrix.fillRect(0, 7, 8, 1, true); // bottom wall
if (flash & 0x08) matrix.fillRect(0, 0, 1, 8, true); // left wall
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);The helper, and the library you would use on a real Uno
The example includes mokxi_max7219.h, a small driver that ships with Mokxi: Max7219 matrix(DIN, CS, CLK, blocks), then begin(), setPixel(), fillRect(), text() and show(). On a real board the usual choice is the LedControl library from the Arduino Library Manager, which Mokxi also ships as LedControl.h, or MD_MAX72XX for scrolling text across several modules.
With LedControl the same setup is LedControl lc(11, 13, 10, 1), then lc.shutdown(0, false), lc.setIntensity(0, 8) and lc.clearDisplay(0) in setup(), and lc.setLed(0, row, column, true) or lc.setRow(0, row, value) to draw. Note the pin order: LedControl takes data, clock, then CS, while the Mokxi driver takes data, CS, then clock. Getting that order wrong is the most common reason a first matrix sketch shows nothing.
Pins 11 and 13 are also the Uno’s hardware SPI pins (MOSI and SCK), which is why most wiring diagrams use them. A library that uses hardware SPI needs DIN on 11 and CLK on 13; CS can be any pin.
Try it in the editor
Change FRAME_MS from 90 to 30 and the ball speeds up. Change BALL to 1 and it becomes a single pixel that can reach every square.
Replace the ball with text: matrix.text(0, 0, "A") draws a letter from the built-in 5x7 font. Then try a smiley face as eight bytes, one per row, written with setPixel in two loops.
Set the module’s count property to 4 and the constructor’s last argument to 4, and the same code has a 32 by 8 sign to work with, which is what the four-in-one modules sold for scrolling text are.
Where to buy the parts in the US
The ready-made red matrix module with the MAX7219 already on the back is sold under many generic brands, usually in packs, by the big online marketplaces. If you would rather build it, Adafruit sells the MAX7219CNG chip on its own and a miniature 8x8 red matrix that pairs with it. SparkFun and DigiKey both carry LED matrices and driver chips; search their catalogs for MAX7219. Links to the Adafruit pages are in the sources below.
Common mistakes
A dark matrix after upload. The chip powers up shut down at minimum brightness. Make sure your setup writes Shutdown off, a scan limit of 7 and an intensity.
The picture is mirrored or rotated. Modules are built in different orientations. Flip the x or y coordinate in your code rather than rewiring.
CS and CLK swapped. The pin order in the constructor differs between libraries, as above.
Powering several modules from the Uno’s 5 V pin. One module at moderate brightness is fine; a chain of four with many LEDs lit can draw more than the board’s regulator or a USB port should supply. Give a long chain its own 5 V supply with a shared ground.
Questions
How many pins does a MAX7219 matrix need on an Arduino?
Three signal pins (DIN, CS and CLK) plus 5 V and ground. More modules chain off the same three pins, DOUT of one to DIN of the next.
Which library should I use for a MAX7219 on a real Arduino?
LedControl is the simplest for single pixels and rows. MD_MAX72XX, with MD_Parola on top, is the usual choice for scrolling text across several modules. Mokxi uses its own small header, mokxi_max7219.h, and ships LedControl.h too.
Does Mokxi show the MAX7219 multiplexing?
No. A real chip lights one row at a time at about 800 Hz; the model shows every enabled row at once, and intensity is a brightness rather than a current. The registers, the power-on state and the chaining are the chip’s.
Keep going
Where the facts on this page come from
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.