/*
Project Title: 5x7 LED Matrix Display with NeoPixel Strips
Author: Dibyaranjan
GitHub: https://github.com/dibyasn/Arduino_Projects/blob/main/7x5_NeoPixel_CustomDisplay/readme.md
Description:
This project utilizes five vertically aligned Adafruit NeoPixel strips (WS2812B-type RGB LEDs)
to create a 5x7 matrix-style display capable of visual effects and displaying alphanumeric characters.
The display consists of:
- 5 vertical LED strips, each with 7 RGB LEDs, representing the 5 columns and 7 rows of the matrix.
- An ESP32 microcontroller that drives each strip via separate GPIO pins.
- Custom fonts and animations rendered by lighting up the appropriate LEDs in each strip.
The project cycles through:
1. Color-based visual effects like wipe, column/row scans, and rainbow cycle.
2. Display of digits 0 to 9 using custom patterns.
3. Display of alphabetic characters A to Z using a 5x7 bitmap font.
Hardware Used:
- ESP32 Development Board
- 5 x NeoPixel Strips (7 pixels each)
- Power Supply (5V regulated, capable of powering all NeoPixels)
- Jumper wires, breadboard, resistors (as needed)
- Optionally: Capacitor across power rails for NeoPixel stability
Libraries:
- Adafruit NeoPixel (required for NeoPixel control)
*/
#include <Adafruit_NeoPixel.h>
// Matrix dimensions
#define NUM_LEDS 7 // Number of rows (LEDs per strip)
#define NUM_STRIPS 5 // Number of vertical strips (columns)
// GPIO pins for each NeoPixel strip
const int dataPins[NUM_STRIPS] = {22, 17, 23, 19, 26};
// Define NeoPixel strips, ordered for left-to-right visual orientation
Adafruit_NeoPixel strips[NUM_STRIPS] = {
Adafruit_NeoPixel(NUM_LEDS, dataPins[4], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_LEDS, dataPins[3], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_LEDS, dataPins[2], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_LEDS, dataPins[1], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_LEDS, dataPins[0], NEO_GRB + NEO_KHZ800)
};
// Font: 5x7 uppercase letters A–Z stored in 5-column bitmaps
const uint8_t font5x7[][5] = {
{0x7C,0x12,0x11,0x12,0x7C}, {0x7F,0x49,0x49,0x49,0x36}, {0x3E,0x41,0x41,0x41,0x22},
{0x7F,0x41,0x41,0x22,0x1C}, {0x7F,0x49,0x49,0x49,0x41}, {0x7F,0x09,0x09,0x09,0x01},
{0x3E,0x41,0x49,0x49,0x7A}, {0x7F,0x08,0x08,0x08,0x7F}, {0x00,0x41,0x7F,0x41,0x00},
{0x20,0x40,0x41,0x3F,0x01}, {0x7F,0x08,0x14,0x22,0x41}, {0x7F,0x40,0x40,0x40,0x40},
{0x7F,0x02,0x0C,0x02,0x7F}, {0x7F,0x04,0x08,0x10,0x7F}, {0x3E,0x41,0x41,0x41,0x3E},
{0x7F,0x09,0x09,0x09,0x06}, {0x3E,0x41,0x51,0x21,0x5E}, {0x7F,0x09,0x19,0x29,0x46},
{0x46,0x49,0x49,0x49,0x31}, {0x01,0x01,0x7F,0x01,0x01}, {0x3F,0x40,0x40,0x40,0x3F},
{0x1F,0x20,0x40,0x20,0x1F}, {0x7F,0x20,0x18,0x20,0x7F}, {0x63,0x14,0x08,0x14,0x63},
{0x07,0x08,0x70,0x08,0x07}, {0x61,0x51,0x49,0x45,0x43}
};
// Digit patterns (0–9) using strings of '#' and '.' characters (5 columns per row)
const char* digits[10][NUM_LEDS] = {
{".###.", "#...#", "#..##", "#.#.#", "##..#", "#...#", ".###."},
{"..#..", ".##..", "#.#..", "..#..", "..#..", "..#..", "#####"},
{".###.", "#...#", "...#.", "..#..", ".#...", "#....", "#####"},
{"####.", "....#", "....#", ".###.", "....#", "....#", "####."},
{"...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#."},
{"#####", "#....", "#....", ".###.", "....#", "....#", "####."},
{".###.", "#....", "#....", "#####", "#...#", "#...#", ".###."},
{"#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..."},
{".###.", "#...#", "#...#", ".###.", "#...#", "#...#", ".###."},
{".###.", "#...#", "#...#", ".####", "....#", "....#", ".###."}
};
void setup() {
// Initialize all NeoPixel strips
for (int i = 0; i < NUM_STRIPS; i++) {
strips[i].begin();
strips[i].show(); // Clear on startup
}
}
void loop() {
// Show animations and characters continuously
colorWipe(255, 0, 0); delay(500); // Red wipe
columnScan(0, 255, 0); delay(500); // Green column scan
rowScan(0, 0, 255); delay(500); // Blue row scan
rainbowCycle(5); delay(500); // Rainbow
// Show all digits 0–9 in cyan
for (int i = 0; i <= 9; i++) {
showDigit(i, 0, 255, 255);
delay(500);
}
// Show all letters A–Z in yellow
for (char c = 'A'; c <= 'Z'; c++) {
showChar(c, 255, 255, 0);
delay(500);
}
}
// Fill all pixels with one color
void colorWipe(uint8_t r, uint8_t g, uint8_t b) {
for (int x = 0; x < NUM_STRIPS; x++) {
for (int y = 0; y < NUM_LEDS; y++) {
strips[x].setPixelColor(y, strips[x].Color(r, g, b));
}
strips[x].show();
}
}
// Light up columns one at a time
void columnScan(uint8_t r, uint8_t g, uint8_t b) {
for (int x = 0; x < NUM_STRIPS; x++) {
clearMatrix();
for (int y = 0; y < NUM_LEDS; y++) {
strips[x].setPixelColor(y, strips[x].Color(r, g, b));
}
strips[x].show();
delay(200);
}
}
// Light up rows one at a time
void rowScan(uint8_t r, uint8_t g, uint8_t b) {
for (int y = 0; y < NUM_LEDS; y++) {
clearMatrix();
for (int x = 0; x < NUM_STRIPS; x++) {
strips[x].setPixelColor(y, strips[x].Color(r, g, b));
}
updateMatrix();
delay(200);
}
}
// Dynamic rainbow effect
void rainbowCycle(uint8_t wait) {
for (int j = 0; j < 256; j++) {
for (int x = 0; x < NUM_STRIPS; x++) {
for (int y = 0; y < NUM_LEDS; y++) {
strips[x].setPixelColor(y, Wheel((x * 10 + y * 10 + j) & 255));
}
strips[x].show();
}
delay(wait);
}
}
// Generate rainbow color from position
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) return strips[0].Color(255 - WheelPos * 3, 0, WheelPos * 3);
if (WheelPos < 170) {
WheelPos -= 85;
return strips[0].Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strips[0].Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
// Turn off all pixels
void clearMatrix() {
for (int x = 0; x < NUM_STRIPS; x++) {
for (int y = 0; y < NUM_LEDS; y++) {
strips[x].setPixelColor(y, 0);
}
}
}
// Apply pixel updates to hardware
void updateMatrix() {
for (int i = 0; i < NUM_STRIPS; i++) {
strips[i].show();
}
}
// Render a single letter (A–Z) in 5x7 font
void showChar(char c, uint8_t r, uint8_t g, uint8_t b) {
clearMatrix();
if (c >= 'A' && c <= 'Z') {
uint8_t* bitmap = (uint8_t*)font5x7[c - 'A'];
for (int col = 0; col < 5; col++) {
for (int row = 0; row < NUM_LEDS; row++) {
if (bitmap[col] & (1 << row)) {
strips[col].setPixelColor(row, strips[col].Color(r, g, b));
}
}
}
updateMatrix();
}
}
// Render a digit (0–9) using string patterns
void showDigit(int digit, uint8_t r, uint8_t g, uint8_t b) {
clearMatrix();
if (digit >= 0 && digit <= 9) {
for (int y = 0; y < NUM_LEDS; y++) {
const char* row = digits[digit][y];
for (int x = 0; x < NUM_STRIPS && row[x]; x++) {
if (row[x] == '#') {
strips[x].setPixelColor(y, strips[x].Color(r, g, b));
}
}
}
updateMatrix();
}
}