cookbook/advanced/matrix.md
Difficulty Level: ⭐⭐⭐ Advanced Time to Complete: 45-60 minutes Prerequisites:
You'll Learn:
When working with LED matrices or grids, you need to map 2D coordinates to a 1D array. This guide covers the essential techniques for creating patterns on LED matrices.
The most important function for matrix work is the XY mapper, which converts 2D coordinates to array indices.
#define MATRIX_WIDTH 16
#define MATRIX_HEIGHT 16
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
CRGB leds[NUM_LEDS];
// Convert X,Y to array index
uint16_t XY(uint8_t x, uint8_t y) {
// Handle out of bounds
if (x >= MATRIX_WIDTH || y >= MATRIX_HEIGHT) {
return 0;
}
// Serpentine (zigzag) layout
if (y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (MATRIX_WIDTH - 1) - x;
return (y * MATRIX_WIDTH) + reverseX;
} else {
// Even rows run forwards
return (y * MATRIX_WIDTH) + x;
}
}
Most LED matrices are wired in a serpentine (zigzag) pattern:
This layout minimizes wiring complexity but requires special handling in code.
Create organic, flowing patterns using 2D noise:
void plasma() {
for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
// Create 2D sine wave pattern
uint8_t brightness = qsub8(
inoise8(x * 30, y * 30, millis() / 10),
inoise8(x * 50, y * 50, millis() / 20)
);
uint16_t index = XY(x, y);
leds[index] = CHSV(brightness, 255, 255);
}
}
}
Animate objects across the matrix:
void bouncingBall() {
static float ballX = MATRIX_WIDTH / 2.0;
static float ballY = MATRIX_HEIGHT / 2.0;
static float velocityX = 0.3;
static float velocityY = 0.2;
// Clear matrix
fadeToBlackBy(leds, NUM_LEDS, 50);
// Update position
ballX += velocityX;
ballY += velocityY;
// Bounce off walls
if (ballX <= 0 || ballX >= MATRIX_WIDTH - 1) velocityX = -velocityX;
if (ballY <= 0 || ballY >= MATRIX_HEIGHT - 1) velocityY = -velocityY;
// Draw ball
leds[XY((uint8_t)ballX, (uint8_t)ballY)] = CRGB::White;
}
Serpentine (Zigzag):
Progressive (Rows all same direction):
return (y * MATRIX_WIDTH) + xRemember that LED matrices can have different origin points:
Adjust your XY function accordingly.
void checkerboard() {
for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
CRGB color = ((x + y) % 2) ? CRGB::White : CRGB::Black;
leds[XY(x, y)] = color;
}
}
}
For text display on matrices, consider using the LED-Matrix library in combination with FastLED.
void heatMap() {
for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
// Distance from center
int dx = x - MATRIX_WIDTH / 2;
int dy = y - MATRIX_HEIGHT / 2;
uint8_t distance = sqrt(dx * dx + dy * dy) * 10;
leds[XY(x, y)] = ColorFromPalette(HeatColors_p, distance);
}
}
}
Wrong pixel positions:
Performance issues:
Memory limitations:
Next Steps: