Светодиодный куб на Arduino: как собрать 3x3x3 и 4x4x4 с кодом
Светодиодный куб на Arduino: шаблон для пайки, сборка 3x3x3 и 4x4x4, транзисторы для слоёв, расчёт резисторов, расширение на 74HC595 и код анимаций на массивах.
Светодиодный куб — один из самых эффектных световых проектов, которые можно собрать на Arduino: светодиоды, расставленные в трёхмерную сетку, зажигаются слой за слоем и рисуют вращающиеся плоскости, падающие капли и кубы, которые растут и сжимаются прямо в воздухе. Начинать светодиодный куб на Arduino лучше всего с размера 3x3x3 (27 светодиодов) или 4x4x4 (64 светодиода): для них хватит пинов Arduino Uno, нескольких транзисторов и терпеливой пайки. Весь секрет в том, чтобы не выделять каждому светодиоду отдельный пин, а использовать метод под названием мультиплексирование по слоям и столбцам: 27 светодиодами управляют 12 пинов, а 64 светодиодами — всего 7 пинов благодаря двум микросхемам 74HC595.
В этом руководстве ты узнаешь, как работает светодиодный куб, как сделать шаблон для пайки, как пошагово соединить слои, почему слоями должны управлять транзисторы и как рассчитываются номиналы резисторов. Дальше — код Arduino, который проигрывает анимации на массивах на кубе 3x3x3, переход к кубу 4x4x4 на 74HC595, версии для ESP32 и Raspberry Pi Pico (MicroPython), вариант на WS2812B для цветного куба и решения самых частых ошибок сборки, например перевёрнутого светодиода или холодной пайки.

Что такое светодиодный куб и как он работает?
Светодиодный куб собирается из горизонтальных слоёв светодиодов, расставленных с одинаковым шагом и уложенных друг на друга. В каждом слое катодные (−) ножки всех светодиодов спаяны вместе, поэтому у каждого слоя одна общая катодная линия. Анодные (+) ножки светодиодов, стоящих друг над другом, спаяны вертикально и образуют столбцы. Куб 3x3x3 состоит из 3 слоёв и 9 столбцов, а куб 4x4x4 — из 4 слоёв и 16 столбцов. Каждый светодиод находится ровно на пересечении одного слоя и одного столбца: чтобы зажечь светодиод, нужно подать плюс на его столбец и соединить его слой с GND.
Каждый светодиод в кубе можно описать тремя координатами: x (слева направо), y (спереди назад) и z (снизу вверх). В коде этой статьи номер столбца вычисляется как c = y × 3 + x (в кубе 4x4x4 c = y × 4 + x), а z — это номер слоя. Как пиксель на экране, отдельная светящаяся точка куба называется вокселем (объёмным пикселем). Создать анимацию, по сути, значит решить, какие воксели и в какой момент будут гореть.
Как работает мультиплексирование по слоям и столбцам?
Если включить сразу несколько слоёв, плюс, поданный на столбец, зажжёт светодиод в каждом активном слое этого столбца, и нужный узор нарисовать не получится. Поэтому куб сканируется слой за слоем: Arduino сначала выключает все слои, выводит на пины узор столбцов для первого слоя, включает только этот слой на несколько миллисекунд, затем выключает его и переходит ко второму слою. Когда этот цикл повторяется больше ста раз в секунду, глаз на мгновение удерживает свет (инерция зрения), и все слои кажутся горящими одновременно.
Частоту сканирования посчитать несложно: частота обновления = 1 / (число слоёв × время слоя). Если в кубе 3x3x3 держать каждый слой включённым 3 мс, один проход займёт 9 мс, и куб будет обновляться примерно 110 раз в секунду. В кубе 4x4x4 при 2 мс на слой проход длится 8 мс, а частота составит 125 Hz. Ниже 50–60 Hz глаз замечает мерцание; выше 100 Hz картинка выглядит для глаза совершенно стабильной, а на камере телефона появляется меньше полос. Платить за это приходится яркостью: каждый слой горит лишь 1/3 времени (в кубе 4x4x4 — 1/4), поэтому средний ток светодиода падает до этой доли от мгновенного тока.
| Куб | Светодиодов | Столбцы + слои | Пинов при прямом управлении | Пинов с 74HC595 | Пинов без мультиплексирования |
|---|---|---|---|---|---|
| 3x3x3 | 27 | 9 + 3 | 12 | 3 + 3 = 6 | 27 |
| 4x4x4 | 64 | 16 + 4 | 20 | 3 + 4 = 7 | 64 |
| 5x5x5 | 125 | 25 + 5 | 30 | 3 + 5 = 8 | 125 |
| 8x8x8 | 512 | 64 + 8 | 72 | 3 + 8 = 11 | 512 |
Список деталей
| Деталь | Куб 3x3x3 | Куб 4x4x4 (с 74HC595) |
|---|---|---|
| Светодиод 5 мм (одного цвета, по возможности матовый) | 27 + 3 запасных | 64 + 6 запасных |
| Резистор столбца | 9 × 220 Ω | 16 × 330 Ω (синие, белые) или 470 Ω (красные, жёлтые) |
| NPN-транзистор (слой) | 3 × 2N2222A или BC337 | 4 × 2N2222A или BC337 |
| Базовый резистор | 3 × 470 Ω | 4 × 470 Ω |
| Сдвиговый регистр | Не нужен | 2 × 74HC595 (74HCT595 для ESP32 и Pico) + 100 nF на каждый |
| Управляющая плата | Arduino Uno или Nano | Arduino Uno, Nano, ESP32 или Pico |
| Сборка | Перфоплата, тонкий одножильный провод | Перфоплата, лужёный медный провод 0,5–0,8 мм |
| Инструменты | Паяльник, припой, бокорезы, плоскогубцы, сверло 5 мм | Те же инструменты + проставки одинаковой высоты |




Как сделать шаблон для пайки
Секрет аккуратного куба — в шаблоне (кондукторе). Если паять светодиоды, держа их в руках, шаг гуляет, слои получаются кривыми, и куб выглядит перекошенным. Шаблон — это деревянная заготовка с отверстиями, расположенными с одинаковым шагом: в них светодиоды вставляются вверх ногами, куполом вниз. Шаг определяется длиной катодной ножки: у большинства светодиодов 5 мм короткая ножка около 25 мм, но свои светодиоды лучше измерить линейкой. Если отогнуть ножку на 90° в 2–3 мм от корпуса, оставшаяся горизонтальная часть должна заходить на ножку соседнего светодиода на 2–3 мм, поэтому шаг 20 мм — хорошая отправная точка.
- Начерти линейкой на фанере, МДФ или толстом картоне сетку 3x3 (или 4x4) с расстоянием 20 мм между точками и отступом не меньше 2 см от краёв.
- Сначала наметь каждую точку гвоздём, затем просверли её строго вертикально сверлом 5 мм. Светодиод должен плотно сидеть в отверстии, но вытаскиваться без усилия; если слишком туго, слегка расширь отверстие.
- Нарисуй на одном краю шаблона стрелку, которая показывает направление катода: короткие ножки всех светодиодов будут смотреть в одну сторону.
- Подготовь четыре проставки одинаковой высоты, подходящие к расстоянию между слоями: на них будет лежать верхний слой, пока слои соединяются. Подойдут обрезки деревянной рейки или сложенный картон.
Пошаговая сборка: слои и столбцы
- Согни ножки: отогни короткую (катодную) ножку каждого светодиода горизонтально на 90° в 2–3 мм от корпуса, в сторону стрелки на шаблоне. Длинная (анодная) ножка остаётся вертикальной.
- Разложи первый слой: вставь светодиоды в отверстия куполом вниз. Каждая катодная ножка в ряду должна касаться катодной ножки следующего светодиода; ножка последнего светодиода в ряду может остаться свободной.
- Пропаяй катоды: паяй каждую точку контакта не дольше 2–3 секунд при температуре жала 320–350 °C. Затем припаяй поперёк концов рядов прямой провод (откушенную ножку резистора или лужёный медный провод), чтобы соединить ряды. Слой становится и единой электрической линией, и прочной рамой; в кубе 4x4x4 провод с обеих сторон делает слой ещё прочнее.
- Проверь слой: не вынимая слой из шаблона, подключи катодную линию к GND и по очереди касайся каждой анодной ножки проводом с 5 V через резистор 220 Ω. Если какой-то светодиод не загорается, замени его сразу.
- Сделай остальные слои: повторяй процесс, пока не наберётся 3 (или 4) слоя. Во всех слоях катодные ножки должны смотреть в одну сторону, чтобы столбцы точно совпали.
- Соедини слои: оставь один слой в шаблоне и выровняй следующий слой точно над ним на проставках. Сделай на конце каждой торчащей вверх анодной ножки нижних светодиодов небольшой изгиб на 2 мм, чтобы ножка проходила рядом с корпусом верхнего светодиода и прилегала к его анодной ножке. Сначала припаяй четыре угла, проверь выравнивание, затем пропаяй остальные столбцы.
- Выведи провода слоёв: припаяй провод к катодной линии каждого слоя и опусти его вниз вдоль одной стороны куба. Эти провода не должны касаться друг друга и столбцов; оставь между ними несколько миллиметров.
- Установи куб на основание: переверни куб: свободные анодные ножки последнего добавленного слоя теперь смотрят вниз, и этот слой становится ближайшим к основанию, то есть нижним (z = 0). Пропусти ножки и провода слоёв через перфоплату, припаяй их и установи резисторы столбцов рядом с каждым столбцом.
Управление слоями через транзисторы

Пин столбца питает один светодиод, но когда слой включён, ток всех светодиодов этого слоя возвращается в GND по одной и той же катодной линии. В кубе 3x3x3 это 9 светодиодов × 12,7 mA ≈ 115 mA, а в кубе 4x4x4 на 74HC595 — 16 светодиодов × 5 mA ≈ 80 mA. Рекомендуемый предел для пина Arduino Uno — 20 mA, абсолютный максимум — 40 mA, поэтому подключать линию слоя напрямую к пину нельзя. Решение — NPN-транзистор под каждым слоем: коллектор подключается к линии слоя, эмиттер — к GND, а база через резистор — к пину Arduino. Когда пин переходит в HIGH, транзистор входит в насыщение и притягивает слой к GND. Чтобы транзистор открылся полностью, ток базы выбирают примерно от 1/10 до 1/20 тока коллектора: для 115 mA нужно 6–12 mA, и (5 V − 0,7 V) / 470 Ω ≈ 9 mA как раз попадает в этот диапазон. Подробности — в статье Что такое транзистор?, а распиновка — в утилите распиновки транзисторов.
| Транзистор | Длительный IC | Порядок выводов (плоской стороной к себе) | Применение в светодиодном кубе |
|---|---|---|---|
| BC547 | 100 mA | C-B-E | Только для кубов с малым током: 115 mA куба 3x3x3 превышают его предел |
| 2N2222A | 600 mA | E-B-C | Идеальный выбор для 3x3x3 и 4x4x4 |
| BC337 | 800 mA | C-B-E | Идеальный выбор для 3x3x3 и 4x4x4 |
| IRLZ44N (MOSFET с логическим уровнем управления) | Десятки ампер | G-D-S | Большие кубы, например 8x8x8; 220 Ω на затвор, 10 kΩ между затвором и GND |
Расчёт резисторов: резисторы столбцов и базы
Резистор столбца — единственная деталь, которая ограничивает ток светодиода, и он стоит по одному в каждом столбце; отдельный резистор на каждый светодиод не нужен, потому что в столбце в любой момент горит только один светодиод. Формула берётся из закона Ома: R = (Vпит − VLED − VCE(sat)) / ILED. При питании 5 V, красном светодиоде с прямым напряжением 2,0 V и транзисторе, на котором в насыщении падает около 0,2 V, для тока 12 mA получается R = (5 − 2,0 − 0,2) / 0,012 ≈ 233 Ω. Ближайший стандартный номинал 220 Ω пропускает через светодиод около 12,7 mA. С синим светодиодом на 3,1 V тот же резистор 220 Ω даёт около 7,7 mA, и при мультиплексировании этого по-прежнему вполне хватает, чтобы светодиод был хорошо виден.
| Цвет светодиода | Прямое напряжение (VF) | 3x3x3, напрямую от Arduino (5 V) | 4x4x4, 74HC595 (5 V) |
|---|---|---|---|
| Красный, жёлтый | 1,8–2,2 V | 220 Ω (≈12–13 mA) | 470 Ω (≈5–6 mA) |
| Чистый зелёный, синий | 2,9–3,3 V | 180–220 Ω (≈8–9 mA) | 330 Ω (≈4–5 mA) |
| Белый | 2,9–3,4 V | 180–220 Ω (≈7–9 mA) | 330 Ω (≈4–5 mA) |
В кубе на 74HC595 мы сознательно берём резисторы побольше: через вывод VCC или GND этой микросхемы может проходить не больше 70 mA в сумме, а при включённом слое могут гореть сразу все восемь выходов. 8 × 5,5 mA ≈ 44 mA оставляют безопасный запас. Средний ток светодиода, от которого зависит воспринимаемая яркость, — это мгновенный ток, делённый на число слоёв: 12,7 / 3 ≈ 4,2 mA в кубе 3x3x3 и 5,5 / 4 ≈ 1,4 mA в кубе 4x4x4. Современные эффективные светодиоды при таких токах хорошо видны в помещении, но в очень светлой комнате куб 4x4x4 может казаться тускловатым. Чтобы посчитать для своих светодиодов, воспользуйся калькулятором резистора для светодиода и утилитой напряжений светодиодов.
Схема подключения светодиодного куба 3x3x3
| Подключение | Arduino Uno / Nano | Примечание |
|---|---|---|
| Столбцы 0–8 (аноды) | D2–D10 | Последовательный резистор 220 Ω на каждом столбце |
| Нижний слой (z = 0) | A0 | К базе транзистора 1 через 470 Ω |
| Средний слой (z = 1) | A1 | К базе транзистора 2 через 470 Ω |
| Верхний слой (z = 2) | A2 | К базе транзистора 3 через 470 Ω |
| Коллекторы транзисторов | — | Каждый — к катодному проводу своего слоя |
| Эмиттеры транзисторов | GND | Все три — к общей земле (GND) |
| Вид сверху | x = 0 | x = 1 | x = 2 |
|---|---|---|---|
| y = 2 (сзади) | Столбец 6 → D8 | Столбец 7 → D9 | Столбец 8 → D10 |
| y = 1 (середина) | Столбец 3 → D5 | Столбец 4 → D6 | Столбец 5 → D7 |
| y = 0 (спереди) | Столбец 0 → D2 | Столбец 1 → D3 | Столбец 2 → D4 |
Код Arduino для светодиодного куба 3x3x3: анимации на массивах
Каждый кадр анимации хранится как одно число на слой. В слое куба 3x3x3 — 9 светодиодов, поэтому хватит 9-битного значения; мы храним его в типе uint16_t, и бит c соответствует столбцу c. Кадры записываются во флеш-память с помощью PROGMEM, поэтому даже анимации из сотен кадров не заполняют 2 КБ ОЗУ платы Uno. Коду ниже не нужны дополнительные библиотеки.
1// 3x3x3 LED küp: katman çoklama ve dizilerle animasyon / 3x3x3 LED cube: layer multiplexing and array animations
2const byte colPins[9] = {2, 3, 4, 5, 6, 7, 8, 9, 10}; // sütun anotları, 220 ohm ile / column anodes via 220 ohm
3const byte layerPins[3] = {A0, A1, A2}; // alt, orta, üst katman transistörü / bottom, middle, top layer transistor
4
5// Her kare 3 katman, her katman 9 bit: bit c = sütun c (c = y*3 + x)
6// Each frame has 3 layers of 9 bits: bit c = column c (c = y*3 + x)
7const uint16_t frames[][3] PROGMEM = {
8 {0b111111111, 0b000000000, 0b000000000}, // 0: alt katman / bottom layer
9 {0b000000000, 0b111111111, 0b000000000}, // 1: orta katman / middle layer
10 {0b000000000, 0b000000000, 0b111111111}, // 2: üst katman / top layer
11 {0b000000000, 0b000010000, 0b000000000}, // 3: yalnız merkez / centre only
12 {0b111101111, 0b101000101, 0b111101111}, // 4: tel kafes, 12 kenar / wireframe, 12 edges
13 {0b010010010, 0b010010010, 0b010010010}, // 5: dönen düzlem, 1. konum / rotating plane, step 1
14 {0b100010001, 0b100010001, 0b100010001}, // 6: dönen düzlem, 2. konum / rotating plane, step 2
15 {0b000111000, 0b000111000, 0b000111000}, // 7: dönen düzlem, 3. konum / rotating plane, step 3
16 {0b001010100, 0b001010100, 0b001010100}, // 8: dönen düzlem, 4. konum / rotating plane, step 4
17 {0b111111111, 0b111111111, 0b111111111} // 9: hepsi açık / all on
18};
19
20void setup() {
21 for (byte c = 0; c < 9; c++) pinMode(colPins[c], OUTPUT);
22 for (byte z = 0; z < 3; z++) pinMode(layerPins[z], OUTPUT); // LOW: katmanlar kapalı / LOW: layers off
23}
24
25// Bir kareyi verilen süre boyunca katman katman tarar / scans one frame layer by layer for the given time
26void showFrame(byte f, unsigned int ms) {
27 unsigned long start = millis();
28 while (millis() - start < ms) {
29 for (byte z = 0; z < 3; z++) {
30 uint16_t bits = pgm_read_word(&frames[f][z]); // katman verisini oku / read the layer data
31 for (byte c = 0; c < 9; c++) digitalWrite(colPins[c], bitRead(bits, c));
32 digitalWrite(layerPins[z], HIGH); // katmanı aç / layer on
33 delay(3); // 3 ms göster / show for 3 ms
34 digitalWrite(layerPins[z], LOW); // sütunlar değişmeden önce kapat / off before the columns change
35 }
36 }
37}
38
39void loop() {
40 for (byte f = 0; f <= 4; f++) showFrame(f, 500); // katmanlar, merkez, kafes / layers, centre, wireframe
41 for (byte turn = 0; turn < 4; turn++) // düzlemi 4 tur döndür / spin the plane 4 times
42 for (byte f = 5; f <= 8; f++) showFrame(f, 120);
43 showFrame(9, 800); // hepsi açık / all on
44}Сердце кода — функция showFrame(). Для каждого слоя она сначала выводит на пины узор столбцов, затем включает транзистор только этого слоя на 3 мс и выключает слой до того, как столбцы изменятся. Порядок важен: если менять столбцы при включённом слое, узор предыдущего слоя на мгновение появляется на новом слое, и возникает паразитная засветка (ghosting). bitRead(bits, c) возвращает бит c числа как 0 или 1, а pgm_read_word() читает 16-битное значение из флеш-памяти. loop() сначала показывает слои по одному, затем центр и 12 рёбер куба, а потом поворачивает вертикальную плоскость через четыре положения, создавая эффект вертушки.
Как придумать свои анимации
Чтобы нарисовать новый кадр, посмотри на куб сверху и представь каждый слой как листок в клетку 3x3. Отметь столбцы, которые должны гореть, и запиши двоичное число после 0b слева направо, от бита 8 до бита 0. Например, четыре угла — это столбцы 0, 2, 6 и 8, что даёт 0b101000101. Если записать это значение во все три слоя, получатся вертикальные столбики в четырёх углах, а если только в средний — четыре точки, висящие в воздухе. Если двоичные числа пока непривычны, статья Системы счисления и битовые операции подробно объясняет эту идею. Несколько приёмов, которые пригодятся при написании кода:
- Сдвиг битов: сдвинь значение слоя влево на 3 бита в кубе 3x3x3 или на 4 бита в кубе 4x4x4, и узор переместится на один ряд назад; если отсекать лишние биты маской через &, получатся эффекты волны и бегущей строки.
- Копирование слоёв: копирование массива слоёв на один шаг вниз или вверх даёт эффекты дождя, поднимающихся пузырьков и лифта.
- Случайность: воксели, выбранные с помощью random() и ненадолго вспыхивающие, создают эффект звёздного неба или искр.
- Инверсия: оператор ~ превращает кадр в негатив, а быстрое переключение между ними даёт мигающий акцент.
Светодиодный куб 4x4x4: расширение с помощью 74HC595
У куба 4x4x4 — 16 столбцов и 4 слоя; для прямого управления нужно 20 пинов, то есть все пины Uno, включая D0 и D1. Если же управлять столбцами через два соединённых цепочкой сдвиговых регистра 74HC595, на 16 столбцов уйдёт всего 3 пина (данные, тактовый сигнал и защёлка); вместе с 4 пинами для слоёв получается 7 пинов. Выход Q7' (вывод 9) первой микросхемы идёт на вход DS второй микросхемы, а линии тактового сигнала и защёлки у обеих микросхем общие. Столбцы 0–7 (два передних ряда) подключаются к выходам Q0–Q7 первой микросхемы, а столбцы 8–15 (два задних ряда) — ко второй. Тот же метод масштабируется до 4 микросхем для куба 5x5x5 и до 8 микросхем для куба 8x8x8.
| Подключение | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| DS (14), первая микросхема | D11 | GPIO 23 | GP19 |
| SH_CP (11), общий для обеих микросхем | D13 | GPIO 18 | GP18 |
| ST_CP (12), общий для обеих микросхем | D10 | GPIO 5 | GP17 |
| OE (13) / MR (10) | GND / 5V | GND / 5V | GND / VBUS |
| VCC (16) / GND (8) | 5V / GND | 5V / GND | VBUS / GND |
| Q7' (9) → DS (14) второй микросхемы | Цепочка | Цепочка | Цепочка |
| Транзисторы слоёв 0–3 (через 470 Ω) | D2, D3, D4, D5 | GPIO 25, 26, 27, 32 | GP10, GP11, GP12, GP13 |
| Тип микросхемы | 74HC595 | 74HCT595 | 74HCT595 |
1// 4x4x4 LED küp: 2 adet 74HC595 (16 sütun) + 4 transistörlü katman / 4x4x4 LED cube: two 74HC595s (16 columns) + 4 transistor layers
2const byte DATA_PIN = 11; // 74HC595 DS (14)
3const byte CLOCK_PIN = 13; // 74HC595 SH_CP (11)
4const byte LATCH_PIN = 10; // 74HC595 ST_CP (12)
5const byte layerPins[4] = {2, 3, 4, 5}; // alttan üste katman transistörleri, 470 ohm ile / layer transistors bottom to top, via 470 ohm
6
7uint16_t cube[4]; // ekrandaki görüntü: katman başına 16 bit / current image: 16 bits per layer
8
9// Hazır kareler: bit c = sütun c (c = y*4 + x) / ready-made frames: bit c = column c (c = y*4 + x)
10const uint16_t frames[][4] PROGMEM = {
11 {0xFFFF, 0x0000, 0x0000, 0x0000}, // alt katman / bottom layer
12 {0x0000, 0xFFFF, 0x0000, 0x0000},
13 {0x0000, 0x0000, 0xFFFF, 0x0000},
14 {0x0000, 0x0000, 0x0000, 0xFFFF}, // üst katman / top layer
15 {0x9009, 0x0000, 0x0000, 0x9009}, // 8 köşe / 8 corners
16 {0xF99F, 0x9009, 0x9009, 0xF99F}, // tel kafes / wireframe
17 {0x0000, 0x0660, 0x0660, 0x0000} // içteki 2x2x2 küp / inner 2x2x2 cube
18};
19const byte FRAME_COUNT = sizeof(frames) / sizeof(frames[0]);
20
21void write16(uint16_t v) { // 16 biti iki entegreye gönder / send 16 bits to both chips
22 digitalWrite(LATCH_PIN, LOW);
23 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, highByte(v)); // önce uzaktaki entegre / far chip first
24 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, lowByte(v));
25 digitalWrite(LATCH_PIN, HIGH); // çıkışlara aktar / copy to the outputs
26}
27
28void refresh() { // her 2 ms'de sıradaki katmana geç / move to the next layer every 2 ms
29 static byte z = 0;
30 static unsigned long last = 0;
31 if (micros() - last < 2000) return;
32 last = micros();
33 digitalWrite(layerPins[z], LOW); // eski katmanı kapat / old layer off
34 z = (z + 1) % 4;
35 write16(cube[z]); // yeni katmanın sütunları / columns of the new layer
36 digitalWrite(layerPins[z], HIGH); // yeni katmanı aç / new layer on
37}
38
39void holdFor(unsigned int ms) { // beklerken küpü yenilemeye devam et / keep refreshing while waiting
40 unsigned long start = millis();
41 while (millis() - start < ms) refresh();
42}
43
44void clearCube() {
45 for (byte z = 0; z < 4; z++) cube[z] = 0;
46}
47
48void setVoxel(byte x, byte y, byte z) { // tek LED yak, x/y/z = 0..3 / light one LED, x/y/z = 0..3
49 bitSet(cube[z], y * 4 + x);
50}
51
52void loadFrame(byte f) { // PROGMEM'deki kareyi yükle / load a frame from PROGMEM
53 for (byte z = 0; z < 4; z++) cube[z] = pgm_read_word(&frames[f][z]);
54}
55
56void sweep() { // dikey düzlemi x ekseninde kaydır / sweep a vertical plane along x
57 for (byte x = 0; x < 4; x++) {
58 clearCube();
59 for (byte y = 0; y < 4; y++)
60 for (byte z = 0; z < 4; z++) setVoxel(x, y, z);
61 holdFor(150);
62 }
63}
64
65void rain(byte steps) { // yağmur: damlalar yukarıdan düşer / rain: drops fall from the top
66 clearCube();
67 for (byte s = 0; s < steps; s++) {
68 for (byte z = 0; z < 3; z++) cube[z] = cube[z + 1]; // her şeyi bir kat indir / move everything down a layer
69 cube[3] = bit(random(16)) | bit(random(16)); // üstte 1-2 yeni damla / 1-2 new drops on top
70 holdFor(120);
71 }
72}
73
74void setup() {
75 pinMode(DATA_PIN, OUTPUT);
76 pinMode(CLOCK_PIN, OUTPUT);
77 pinMode(LATCH_PIN, OUTPUT);
78 for (byte z = 0; z < 4; z++) pinMode(layerPins[z], OUTPUT);
79 randomSeed(analogRead(A0)); // boştaki A0'dan rastgele tohum / random seed from the unconnected A0
80}
81
82void loop() {
83 for (byte f = 0; f < FRAME_COUNT; f++) {
84 loadFrame(f);
85 holdFor(500);
86 }
87 for (byte i = 0; i < 3; i++) sweep();
88 rain(80);
89}В этой версии сканирование выполняет функция refresh(), построенная по неблокирующему принципу: при каждом вызове она проверяет через micros(), прошли ли 2 мс; если да, выключает старый слой, отправляет 16 бит нового слоя в две микросхемы и включает новый слой. Благодаря этому код анимаций только меняет массив cube[] и вообще не занимается обновлением изображения. holdFor() во время ожидания продолжает вызывать refresh(), поэтому нигде в программе не стоит использовать длинный delay(). setVoxel(x, y, z) зажигает отдельный светодиод по координатам; sweep() с её помощью проводит вертикальную плоскость через куб, а rain() копирует слои на один шаг вниз и добавляет сверху случайные капли. Разницу между delay() и millis() можно найти в статье millis() и delay(), а как перенести сканирование в прерывание по таймеру — в статье Прерывания в Arduino.
Светодиодный куб на ESP32
Пины ESP32 выдают 3,3 V. Этого не хватает, чтобы напрямую управлять синими и белыми светодиодами с прямым напряжением около 3 V: после падения на резисторе и транзисторе почти ничего не остаётся. Поэтому самое чистое решение на ESP32 — управлять столбцами через 74HCT595 с питанием 5 V: семейство HCT воспринимает как HIGH даже 2 V, поэтому без проблем читает сигналы 3,3 V, а светодиоды при этом питаются от 5 V. На базы транзисторов слоёв по-прежнему ставь 470 Ω: (3,3 − 0,7) / 470 ≈ 5,5 mA достаточно для тока слоя 80 mA. Код для куба 4x4x4 выше компилируется на ESP32 без изменений; нужно только заменить константы пинов на значения из таблицы (23, 18, 5 и 25, 26, 27, 32). При желании можно использовать Wi-Fi ESP32 и выбирать анимации с веб-страницы на телефоне; для начала загляни в статью Что такое ESP32?.
Светодиодный куб на Raspberry Pi Pico и MicroPython
Pico — тоже плата на 3,3 V, и при настройке по умолчанию её пины выдают всего несколько миллиампер, поэтому используется та же схема с 74HCT595. Питай микросхемы и светодиоды от VBUS (пин 40), на который приходят 5 V от USB. В MicroPython 16 бит отправляются через аппаратный SPI: пины GP18 (SCK) и GP19 (MOSI) интерфейса SPI0 управляют линиями тактового сигнала и данных, а GP17 — защёлкой. Код работает по той же логике: show() сканирует кадр слой за слоем в течение заданного времени, а в эффекте дождя срез списка (cube[1:]) сдвигает все слои на один шаг вниз. Установка и первые шаги описаны в статье Что такое Raspberry Pi Pico?.
1# Pico + 2 adet 74HCT595 ile 4x4x4 LED küp / 4x4x4 LED cube with a Pico + two 74HCT595s
2from machine import Pin, SPI
3import time
4import random
5
6# GP18 = SCK -> SH_CP, GP19 = MOSI -> DS; GP16 (MISO) boş kalır / GP16 (MISO) stays unconnected
7spi = SPI(0, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(19))
8latch = Pin(17, Pin.OUT, value=0) # ST_CP
9layers = [Pin(n, Pin.OUT, value=0) for n in (10, 11, 12, 13)] # alttan üste, 470 ohm ile / bottom to top, via 470 ohm
10
11def write16(v):
12 latch.value(0)
13 spi.write(bytes((v >> 8, v & 0xFF))) # önce uzaktaki entegre / far chip first
14 latch.value(1) # çıkışlara aktar / copy to the outputs
15
16def show(frame, ms):
17 # kareyi ms boyunca katman katman tara / scan the frame layer by layer for ms
18 end = time.ticks_add(time.ticks_ms(), ms)
19 while time.ticks_diff(end, time.ticks_ms()) > 0:
20 for z in range(4):
21 write16(frame[z])
22 layers[z].value(1) # katmanı aç / layer on
23 time.sleep_us(2000)
24 layers[z].value(0) # sütunlar değişmeden kapat / off before the columns change
25
26FRAMES = [
27 [0x9009, 0x0000, 0x0000, 0x9009], # 8 köşe / 8 corners
28 [0xF99F, 0x9009, 0x9009, 0xF99F], # tel kafes / wireframe
29 [0x0000, 0x0660, 0x0660, 0x0000], # içteki küp / inner cube
30]
31
32while True:
33 for f in FRAMES:
34 show(f, 600)
35 cube = [0, 0, 0, 0]
36 for _ in range(60): # yağmur: her şey bir kat iner / rain: everything drops a layer
37 drop = (1 << random.getrandbits(4)) | (1 << random.getrandbits(4))
38 cube = cube[1:] + [drop]
39 show(cube, 120)Кубы побольше: 5x5x5 и 8x8x8
С ростом куба растут и две проблемы. Первая — ток: в кубе 8x8x8 в каждом слое 64 светодиода, и при 10 mA на светодиод ток слоя составляет 640 mA; это уже работа не для маленького транзистора в корпусе TO-92, а для MOSFET с логическим уровнем управления. Вторая — время сканирования: чтобы удержать 100 Hz при 8 слоях, на каждый слой остаётся 1,25 мс, и на каждый слой нужно отправить 64 бита (8 байт); shiftOut() для этого слишком медленный, так что аппаратный SPI обязателен. Кроме того, каждый светодиод горит лишь 1/8 времени, и яркость падает; большим кубам нужны более мощные драйверы столбцов и внешний блок питания на 5 V вместо USB (см. Питание Arduino). Поэтому первый куб лучше делать 3x3x3 или 4x4x4: так техника будет освоена ещё до того, как придётся паять 512 светодиодов.
Альтернатива: цветной светодиодный куб на WS2812B

Если хочется выбирать цвет каждого светодиода отдельно, а не делать одноцветный куб, можно использовать адресные светодиоды, например WS2812B. У каждого такого светодиода есть собственная микросхема драйвера, поэтому не нужны ни мультиплексирование, ни транзисторы, ни резисторы столбцов: 64 светодиода соединяются цепочкой по линиям 5 V, GND и данных и управляются с одного пина. Для куба используют адресные светодиоды 5 мм с 4 выводами (например, PL9823 или APA106) или отрезки ленты WS2812B. Платить приходится током: около 60 mA на светодиод при полном белом, то есть 3,8 A на 64 светодиода. Поэтому используй блок питания 5 V 4 A, добавь конденсатор 1000 µF на питание и резистор 330 Ω на линию данных и ограничь яркость программно. Код использует библиотеку Adafruit NeoPixel.
1// WS2812B ile 4x4x4 RGB LED küp / 4x4x4 RGB LED cube with WS2812B
2#include <Adafruit_NeoPixel.h>
3
4const byte DATA_PIN = 6; // 330 ohm ile ilk LED'in DIN ucuna / to the first LED's DIN via 330 ohm
5const byte N = 4;
6Adafruit_NeoPixel cube(N * N * N, DATA_PIN, NEO_GRB + NEO_KHZ800);
7
8uint16_t idx(byte x, byte y, byte z) { // koordinattan zincirdeki sıraya / coordinate to position in the chain
9 return z * 16 + y * 4 + x; // düz (zikzaksız) kablolama varsayılır / assumes straight, non-zigzag wiring
10}
11
12void setup() {
13 cube.begin();
14 cube.setBrightness(40); // parlaklığı ve akımı sınırla (0-255) / limit brightness and current (0-255)
15}
16
17void loop() {
18 static uint16_t hue = 0;
19 for (byte z = 0; z < N; z++)
20 for (byte y = 0; y < N; y++)
21 for (byte x = 0; x < N; x++) // her katman farklı tonda / each layer gets a different hue
22 cube.setPixelColor(idx(x, y, z), cube.gamma32(cube.ColorHSV(hue + z * 8192U)));
23 cube.show();
24 hue += 256; // gökkuşağını kaydır / shift the rainbow
25 delay(20);
26}Функция idx() в коде переводит координаты x, y, z в номер позиции в цепочке и предполагает, что все ряды соединены в одном направлении. Если проводка идёт зигзагом, в нечётных рядах вместо x нужно использовать 3 − x. Некоторые адресные светодиоды 5 мм ожидают цвета в порядке RGB; если вместо красного виден зелёный, замени NEO_GRB на NEO_RGB. setBrightness(40) снижает яркость примерно до 16%, поэтому даже в худшем случае ток остаётся около 0,6 A.
| Характеристика | Одноцветный светодиодный куб | Светодиодный куб на WS2812B |
|---|---|---|
| Цвет | Один цвет (собственный цвет светодиода) | 16 миллионов цветов, отдельно для каждого светодиода |
| Задействовано пинов (4x4x4) | 7 (с 74HC595) | 1 |
| Дополнительные детали | Транзисторы, резисторы, 74HC595 | Конденсатор, резистор на линии данных, мощный блок питания |
| Объём пайки | 2 ножки на светодиод | 4 ножки на светодиод, больше проводов |
| Управление яркостью | Вкл/выкл (ШИМ для каждого светодиода сделать сложно) | 256 уровней для каждого светодиода |
| Ток (4x4x4) | Около 100 mA, хватает USB | До ≈3,8 A, нужен внешний источник питания |
| Чему учит | Мультиплексирование, транзисторы, битовые операции | Адресация, цветовой тон, управление питанием |
Идеи проектов со светодиодным кубом
- Куб, реагирующий на музыку: увеличивай число горящих слоёв в зависимости от уровня звука, измеренного датчиком звука, и получится трёхмерный эквалайзер.
- 3D-змейка: управляй змейкой по трём осям в кубе 4x4x4 с помощью джойстика и кнопки; больше идей для игр — в статье Игровые проекты на Arduino.
- Игральный кубик: при нажатии кнопки воксели быстро перемешиваются, и куб показывает число от 1 до 6 узором из точек.
- Проект для научной выставки: объясни инерцию зрения, увеличивая время слоя потенциометром и показывая момент, когда появляется мерцание; другие идеи — в статье Идеи проектов для научной выставки.
- Выбор анимаций с телефона: пусть каждая буква, отправленная через Bluetooth-модуль HC-05, запускает свою анимацию.
- Цветной ночник: настрой медленные переходы цветов в кубе на WS2812B; если используешь ESP32, управляй эффектами с телефона через WLED.
Частые ошибки и как их исправить
| Симптом | Вероятная причина | Решение |
|---|---|---|
| Один светодиод вообще не горит | Светодиод перевёрнут или неисправен, либо нарушена пайка ножки | Проверь направление катода, проверь светодиод батарейкой-таблеткой и при необходимости замени |
| Светодиоды, которые должны быть выключены, слабо светятся (ghosting) | Столбцы меняются при включённом слое, или в кубе есть перевёрнутый светодиод | Сначала выключи слой, потом выводи столбцы; если код верный, найди перевёрнутый светодиод |
| Светодиоды мерцают или гаснут, если дотронуться до куба | Холодная пайка: тусклое, зернистое соединение в виде шарика | Прогрей соединение чистым жалом паяльника и добавь немного свежего припоя |
| Не горит целый слой | Перепутаны выводы транзистора (E-B-C вместо C-B-E) или нет контакта у базового резистора | Сверь порядок выводов с даташитом и прозвони цепь базы |
| Не горит целый столбец | Нет пайки столбца к основанию, либо неверный резистор или пин | Прозвони столбец мультиметром от начала до конца и проверь массив пинов в коде |
| Куб мерцает | Слишком долгое время слоя или Serial.print() либо delay() в цикле сканирования | Установи время слоя 2–3 мс и убери код, который блокирует сканирование |
| Куб светит очень тускло | Слишком большие резисторы, синие светодиоды работают от 3,3 V или слишком много слоёв | Пересчитай резистор; на платах с 3,3 V питай 74HCT595 от 5 V |
| Скетч не загружается | К D0 или D1 подключён светодиод | Начинай столбцы с D2 или отключай эти провода на время загрузки |
Светодиодный куб — один из редких проектов, которые учат сразу пайке, транзисторам, расчёту резисторов, мультиплексированию и битовым операциям. Начни с куба 3x3x3, а когда код и логика анимаций станут понятны, переходи к кубу 4x4x4 на 74HC595 или к WS2812B, если нужен цвет. Если хочется сначала попробовать последовательное зажигание светодиодов в одну линию, хорошей разминкой будет статья Огни Knight Rider и бегущий огонь на Arduino. В приложении BlueGrays есть проекты с бегущими огнями, эффектом Knight Rider, анимациями на WS2812B и светодиодной матрицей, с пошаговыми схемами подключения и кодом.
Частые вопросы
Сколько светодиодов и пинов нужно для светодиодного куба?
Для куба 3x3x3 нужно 27 светодиодов, для 4x4x4 — 64; стоит купить несколько запасных. При мультиплексировании по слоям и столбцам кубу 3x3x3 нужны 9 столбцов плюс 3 слоя, то есть 12 пинов. Куб 4x4x4 при прямом управлении занимает 20 пинов, но если управлять столбцами через два 74HC595, всего понадобится 7 пинов.
Какой резистор нужен для светодиодного куба?
На каждый столбец ставится один резистор; для куба 3x3x3, которым Arduino управляет напрямую от 5 V, 220 Ω — распространённый и безопасный номинал. В кубе на 74HC595 бери 330 Ω для синих и белых светодиодов и 470 Ω для красных и жёлтых, чтобы не превысить общий предел микросхемы в 70 mA. Чтобы подобрать свой номинал, используй формулу R = (Vпит − VLED − 0,2 V) / ILED.
Почему слоями светодиодного куба управляют транзисторы?
Когда слой включён, ток всех его светодиодов возвращается в GND по одной линии; в кубе 3x3x3 это больше 100 mA. Рекомендуемый предел пина Arduino — 20 mA, поэтому линию слоя притягивает к GND NPN-транзистор, например 2N2222A или BC337. Базового резистора 470 Ω для этого достаточно.
Почему мерцает светодиодный куб?
Мерцание появляется, когда частота сканирования слишком низкая. Частота обновления равна 1 / (число слоёв × время слоя) и должна быть выше 100 Hz, поэтому держи время слоя в пределах 2–3 мс и не ставь в цикл сканирования длинный delay() или Serial.print(). Если куб мерцает только при прикосновении, скорее всего, дело в холодной пайке.
Почему горят светодиоды, которые должны быть выключены?
Это называется паразитной засветкой (ghosting), и у неё две основные причины. Если менять значения столбцов при включённом слое, предыдущий узор на мгновение переносится на новый слой: сначала выключи слой, потом выводи столбцы. Если код верный, возможно, перевёрнутый светодиод в кубе открывает путь току в другие слои.
Можно ли собрать светодиодный куб 8x8x8 на Arduino Uno?
Да, но одних пинов не хватит: для 64 столбцов нужна цепочка из 74HC595 или похожие драйверы, для 8 слоёв — MOSFET с логическим уровнем управления, а для быстрого сканирования — аппаратный SPI. К тому же пайка 512 светодиодов занимает несколько дней. Лучше сначала освоить технику на кубе 3x3x3 или 4x4x4.
Что собрать после прочтения
Все проекты
Бегущие огни на светодиодах
Огни, которые загораются друг за другом, будто бегут. Arduino зажигает шесть светодиодов по одному; каждый светится короткое мгновение и гаснет, так что свет проходит от начала до конца и начинает сно

Светодиодный эффект Knight Rider
Классический бегущий огонь-сканер: светящаяся точка скользит от одного края шести светодиодов к другому и возвращается обратно. Arduino зажигает каждый светодиод на десятую долю секунды и переходит к

Светодиодный эффект Knight Rider с регулируемой скоростью
Свет бежит от одного края шести светодиодов к другому, разворачивается и бежит обратно. Поверни ручку потенциометра, и скорость этого бега сразу изменится: в одном крайнем положении свет почти летит,

Работа со светодиодной лентой WS2812B
Познакомься с умной светодиодной лентой, где каждому огоньку можно задать свой цвет. Arduino сначала зажигает первые пять светодиодов красным, через секунду остальные пять — синим, затем выключает все

Анимация WS2812B 1
На ленте из 56 светодиодов все цвета радуги выстраиваются рядом и текут без остановки, будто по ленте скользит река света. Каждый светодиод светится чуть другим цветом, чем предыдущий, и пока цвета пл

Анимация WS2812B 2
Устрой в комнате световое шоу, которое само меняет цвета. Arduino гонит цвета по ленте из 30 светодиодов и каждые несколько секунд переключается на новый набор: радуга, фиолетово-зелёные полосы, чёрно

Пиксельная змейка на матрице 8x8
Собери классическую игру «Змейка» своими руками и сыграй в неё. На цветной светодиодной матрице 8x8 ты джойстиком управляешь зелёной змейкой и ешь красные яблоки; с каждым яблоком змейка растёт, немно

4 матрицы 32x8 — набор из 6 анимаций
Четыре светодиодные панели 32x8, сложенные друг на друга, образуют квадратный экран, на котором по очереди идут шесть анимаций: падающий цифровой дождь, растущая спираль, клетки, которые сами рождаютс
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

