ESP32 и матрица 8×8 из 64 светодиодов WS2812B в Arduino IDE

Перевод статьи ESP32: 64 WS2812B RGB LED 8×8 Matrix (Arduino IDE) — Rui Santos & Sara Santos, Random Nerd Tutorials.
В этом руководстве показано, как использовать панель-матрицу 8×8 из 64 RGB-светодиодов WS2812B на ESP32 через Arduino IDE. Мы покажем, как управлять каждым светодиодом, задавать разные цвета и яркость, рисовать фигуры/иконки и создавать радужный RGB-эффект.
Есть и отдельное руководство про адресные RGB-светодиоды WS2812B (Neopixels) на ESP32.
Что понадобится заранее#
Убедитесь, что установлена Arduino IDE с поддержкой плат ESP32:
Знакомимся с панелью-матрицей 8×8 из WS2812B (Neopixels)#
Панель 8×8 на WS2812B содержит 64 RGB-светодиода (они же neopixels), каждым из которых можно управлять независимо — задавать любой цвет и яркость всего одним цифровым пином ESP32.

Панель 8×8 на 64 светодиодах WS2812B.
Питание панели-матрицы WS2812B#
Панель следует питать от источника 5 В. При 5 В каждый светодиод на полной яркости потребляет около 50 мА. То есть при полной яркости белым на каждые 30 светодиодов панель может брать до 1,5 А. Подойдёт адаптер AC/DC на 5 В 2 А.
Если используете внешний источник, не забудьте соединить его землю с пином GND ESP32. В этом руководстве мы управляем 64 светодиодами (квадратная матрица 8×8) от внешнего источника питания.
Что нужно из железа#
- плата ESP32 — любая модель;
- панель-матрица 8×8 на 64 светодиодах WS2812B;
- адаптер питания 5 В 2 А;
- соединительные провода.
Подключение матрицы 8×8 к ESP32#
Подключение простое — нужен всего один цифровой пин (DIN).
| Матрица 8×8 | ESP32 |
|---|---|
| V− | GND |
| DIN | Любой цифровой пин (например, GPIO 2)* |
| Адаптер питания | |
|---|---|
| GND | GND ESP32 |
| GND | V− матрицы |
| 5V | V+ матрицы |
* можно использовать любые другие подходящие GPIO — сверьтесь с распиновкой ESP32.

Пины панели: V−, DIN, V+.
Ниже — схема с внешним адаптером; но можно питать и напрямую от 5 В ESP32, если не используете белый цвет на полной яркости. При питании от адаптера: GND к V−, GPIO 2 к DIN, а 5 В адаптера к V+ и GND к V−.

Схема подключения матрицы 8×8 к ESP32 и адаптеру питания.
Установка библиотеки FastLED#
- откройте менеджер библиотек Arduino IDE;
- найдите FastLED;
- установите библиотеку FastLED от Daniel Garcia.

Установка FastLED.
Пример №1 — управление светодиодами матрицы по отдельности#
Следующий код задаёт свой цвет каждому светодиоду матрицы по координатам (X, Y). Загрузите его на плату — он заработает сразу.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-64-ws2812b-8x8-matrix-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <FastLED.h>
#define DIN_PIN 2
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
#define BRIGHTNESS 80 // Brightness (0-255)
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define ZIGZAG true // Set false if your panel is wired in straight rows instead of zigzag
#define DELAY_MS 500
CRGB leds[NUM_LEDS];
// Convert (x,y) coordinates to the corresponding index in the matrix
uint16_t coordToIndex(uint8_t x, uint8_t y) {
if (ZIGZAG && (y & 0x01)) {
x = (MATRIX_WIDTH - 1) - x;
}
return (y * MATRIX_WIDTH) + x;
}
// Set the color of a pixel at (x,y)
void setPixel(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness = 255) {
if (x >= MATRIX_WIDTH || y >= MATRIX_HEIGHT)
return;
CRGB color = CRGB(r, g, b);
color.nscale8(brightness);
leds[coordToIndex(x, y)] = color;
}
void setup() {
FastLED.addLeds<LED_TYPE, DIN_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
}
void loop() {
setPixel(0, 0, 255, 0, 0); // First LED x=0 and y=0 | Red - Full brightness
FastLED.show();
delay(DELAY_MS);
setPixel(3, 3, 0, 255, 0, 128); // LED x=3 and y=3 | Green - 50% brightness
FastLED.show();
delay(DELAY_MS);
setPixel(7, 7, 0, 0, 255, 200); // Last LED x=7 and y=7 | Blue - ~78% brightness
FastLED.show();
delay(DELAY_MS);
FastLED.clear(); // All LEDs off
FastLED.show();
delay(DELAY_MS);
}
Как работает код#
Подключение библиотеки. Подключаем FastLED.h.
#include <FastLED.h>
Глобальные переменные. Пин данных подключён к GPIO 2. Задаём ширину и высоту матрицы, а их произведение даёт общее число светодиодов.
#define DIN_PIN 2
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
Задаём тип светодиодов WS2812B и порядок цветов GRB.
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
Переменная ZIGZAG используется в функции coordToIndex() для правильной адресации светодиода в зависимости от того, разведены ли ряды матрицы зигзагом или все в одном направлении.
#define ZIGZAG true
coordToIndex(). Переводит координаты (x, y) в соответствующий индекс в матрице:
uint16_t coordToIndex(uint8_t x, uint8_t y) {
if (ZIGZAG && (y & 0x01)) {
x = (MATRIX_WIDTH - 1) - x;
}
return (y * MATRIX_WIDTH) + x;
}
setPixel(). Задаёт цвет и яркость одного пикселя матрицы: проверяет корректность координат, строит цвет CRGB из компонент, масштабирует интенсивность параметром яркости и записывает цвет в глобальный массив leds по индексу от coordToIndex().
void setPixel(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness = 255) {
if (x >= MATRIX_WIDTH || y >= MATRIX_HEIGHT)
return;
CRGB color = CRGB(r, g, b);
color.nscale8(brightness);
leds[coordToIndex(x, y)] = color;
}
Для матрицы с зигзагообразной разводкой координаты каждого светодиода задаются так:

Координаты (x, y) при зигзагообразной разводке.
loop(). Сначала задаём первому светодиоду (x=0, y=0) красный цвет, вызываем show(), ждём, затем задаём цвет и яркость двум другим светодиодам и в конце гасим всё вызовом clear().
Демонстрация#

Пример 1 в работе.
Пример №2 — рисуем фигуру на матрице 8×8#
Следующий код рисует фигуру с эффектом сердцебиения.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-64-ws2812b-8x8-matrix-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <FastLED.h>
#define DIN_PIN 2
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
#define BRIGHTNESS 80 // Brightness (0-255)
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define ZIGZAG true // Set false if your panel is wired in straight rows instead of zigzag
#define FLIP_H false // Set true if the image displays mirrored left to right
#define FLIP_V false // Set true if the image displays upside down
CRGB leds[NUM_LEDS];
// Heart shape (8x8)
const bool heart[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{0,0,0,0,0,0,0,0},
{0,1,1,0,0,1,1,0},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{0,1,1,1,1,1,1,0},
{0,0,1,1,1,1,0,0},
{0,0,0,1,1,0,0,0}
};
// Convert (x,y) coordinates to the corresponding index in the matrix
uint16_t coordToIndex(uint8_t x, uint8_t y) {
if (FLIP_H) x = (MATRIX_WIDTH - 1) - x;
if (FLIP_V) y = (MATRIX_HEIGHT - 1) - y;
if (ZIGZAG && (y & 0x01)) {
x = (MATRIX_WIDTH - 1) - x;
}
return (y * MATRIX_WIDTH) + x;
}
// Set the color of a pixel at (x,y)
void setPixel(uint8_t x, uint8_t y, CRGB color) {
if (x >= MATRIX_WIDTH || y >= MATRIX_HEIGHT)
return;
leds[coordToIndex(x, y)] = color;
}
// Draws the heart shape - scales its color by a brightness factor (0.0 - 1.0)
void drawShape(CRGB color, float scale) {
FastLED.clear();
CRGB c = color;
c.nscale8_video((uint8_t)(scale * 255));
for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
if (heart[y][x]) setPixel(x, y, c);
}
}
}
// Pulses a heartrate LED pattern by changing the brightness over durationMs
// It creates a fade in and fade out effect
void pulse(CRGB color, float from, float to, uint16_t durationMs) {
const uint8_t steps = 24;
for (uint8_t i = 0; i <= steps; i++) {
float t = (float)i / steps;
float eased = (1 - cos(t * PI)) / 2.0;
float scale = from + (to - from) * eased;
drawShape(color, scale);
FastLED.show();
delay(durationMs / steps);
}
}
void setup() {
FastLED.addLeds<LED_TYPE, DIN_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
FastLED.show();
}
void loop() {
// Red color
CRGB color = CRGB(255, 0, 0);
// Heartbeat animation
pulse(color, 0.30, 1.00, 120);
pulse(color, 1.00, 0.55, 140);
pulse(color, 0.55, 0.85, 100);
pulse(color, 0.85, 0.30, 160);
drawShape(color, 0.30);
FastLED.show();
delay(300);
}
Обзор кода#
Инициализация похожа на пример №1, но вместо управления отдельными светодиодами мы рисуем фигуру-сердце 8×8, заданную битовой картой.
const bool heart[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{0,0,0,0,0,0,0,0},
{0,1,1,0,0,1,1,0},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{0,1,1,1,1,1,1,0},
{0,0,1,1,1,1,0,0},
{0,0,0,1,1,0,0,0}
};
Если нужно отразить фигуру по горизонтали или вертикали — задайте эти переменные:
#define FLIP_H false
#define FLIP_V false
Функция drawShape() рисует сердце: очищает дисплей, копирует цвет и масштабирует его яркость коэффициентом scale (0.0–1.0), затем перебирает все пиксели и зажигает те, что заданы в массиве heart[y][x].
void drawShape(CRGB color, float scale) {
FastLED.clear();
CRGB c = color;
c.nscale8_video((uint8_t)(scale * 255));
for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
if (heart[y][x]) setPixel(x, y, c);
}
}
}
Функция pulse() плавно меняет яркость сердца от одного уровня к другому за заданное время — за 24 небольших шага перерисовывает фигуру с новой яркостью, создавая эффект пульса.
void pulse(CRGB color, float from, float to, uint16_t durationMs) {
const uint8_t steps = 24;
for (uint8_t i = 0; i <= steps; i++) {
float t = (float)i / steps;
float eased = (1 - cos(t * PI)) / 2.0;
float scale = from + (to - from) * eased;
drawShape(color, scale);
FastLED.show();
delay(durationMs / steps);
}
}
Главный цикл loop() бесконечно проигрывает красный эффект сердцебиения: задаёт красный цвет и вызывает pulse() четыре раза, чтобы сердце ярко вспыхнуло, чуть погасло, снова мягко вспыхнуло и угасло.
Демонстрация#

Пример 2: красное сердце с эффектом сердцебиения.
Пример №3 — эффект радуги на матрице 8×8#
Следующий код создаёт радужный эффект — цвета плавно движутся по всем светодиодам.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-64-ws2812b-8x8-matrix-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <FastLED.h>
#define DIN_PIN 2
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
#define BRIGHTNESS 80 // Brightness (0-255)
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define ZIGZAG true // Set false if your panel is wired in straight rows instead of zigzag
// Rainbow animation
#define BASE_HUE 160 // Initial blue hue for new LED (0-255)
#define HUE_STEP_PER_TICK 3 // Amount the LED hue shifts per frame
#define DELAY_MS 80 // Animation speed
uint16_t ledsLit = 0; // Number of LEDs currently turned on
uint16_t frame = 0; // Counts animation frames
CRGB leds[NUM_LEDS];
// Convert (x,y) coordinates to the corresponding index in the matrix
uint16_t coordToIndex(uint8_t x, uint8_t y) {
if (ZIGZAG && (y & 0x01)) {
x = (MATRIX_WIDTH - 1) - x;
}
return (y * MATRIX_WIDTH) + x;
}
// Set the color of a pixel at (x,y)
void setPixel(uint8_t x, uint8_t y, CRGB color, uint8_t brightness = 255) {
if (x >= MATRIX_WIDTH || y >= MATRIX_HEIGHT)
return;
color.nscale8(brightness);
leds[coordToIndex(x, y)] = color;
}
void setup() {
FastLED.addLeds<LED_TYPE, DIN_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
FastLED.show();
}
void loop() {
// Turns on 1 LED per frame until fully lit
if (ledsLit < NUM_LEDS) {
ledsLit++;
}
// Update colors of all currently lit LEDs
for (uint16_t i = 0; i < ledsLit; i++) {
uint8_t x = i % MATRIX_WIDTH;
uint8_t y = i / MATRIX_WIDTH;
// Calculate hue based on how long this LED has been lit
// Newer LEDs start at BASE_HUE, older ones shift further along the color wheel
uint16_t age = frame - i;
uint8_t hue = BASE_HUE + (uint8_t)(age * HUE_STEP_PER_TICK);
setPixel(x, y, CHSV(hue, 255, 255));
}
FastLED.show();
delay(DELAY_MS);
frame++;
}
Обзор кода#
Начало похоже на предыдущие примеры, разберём в основном новый код в loop(). Константы задают начальный синий тон и то, насколько цвет сдвигается за кадр:
#define BASE_HUE 160
#define HUE_STEP_PER_TICK 3
Два счётчика хранят значения между кадрами: ledsLit — сколько светодиодов сейчас горит, frame — счётчик кадров анимации.
В loop(), пока матрица не заполнена целиком, каждый кадр зажигается ещё один светодиод. Затем для каждого горящего светодиода вычисляется его позиция (x, y) и тон в зависимости от того, как давно он горит: недавно зажжённые ближе к синему, а «старые» смещаются по цветовому кругу — так и получается радуга.
for (uint16_t i = 0; i < ledsLit; i++) {
uint8_t x = i % MATRIX_WIDTH;
uint8_t y = i / MATRIX_WIDTH;
uint16_t age = frame - i;
uint8_t hue = BASE_HUE + (uint8_t)(age * HUE_STEP_PER_TICK);
setPixel(x, y, CHSV(hue, 255, 255));
}
Демонстрация#

Пример 3: радужный эффект.
Итог#
В этом руководстве вы научились управлять панелью-матрицей 8×8 из WS2812B через библиотеку FastLED: адресовать каждый светодиод отдельно, рисовать фигуры и показывать радужный эффект. Теперь эти приёмы можно применять в своих проектах.
Спасибо за чтение.