Симулятор MAX7219 онлайн: матрица 8x8 и бегущая строка
Матрица MAX7219 — модуль, на котором я впервые увидел бегущую строку вживую. Скетч из интернета собрался, но текст шёл задом наперёд и зеркально: я потратил вечер на поиск причины, пока не понял, что библиотека LedControl ждёт биты в обратном порядке от того, как я их нарисовал в массиве. Сейчас бы я проверил узор сначала в браузере: нарисовал восемь байт в карточке матрицы, нажал «запустить» — и видно, что пунктир едет влево, а не вправо.
Модуль ставится на стенд симулятора из каталога: красный провод с меткой MAT, три пина DIN, CLK, CS на D11, D13, D10 (стандартный SPI). 64 красных пикселя на плашке — нарисуйте узор в карточке, и он сразу отрисуется; зажгите пиксели скетчем через LedControl.setRow — лента на стене повторит. Ниже — стартовый скетч, бегущая строка через массив, разница LedControl и Max72xxPanel, честная граница.
Что эмулируется на стенде
MAX7219 в каталоге — деталь «Светодиодная матрица 8×8 (MAX7219)»: три пина DIN, CLK, CS на D10-D13 (SPI-зона Uno), красный провод с меткой MAT. 64 пикселя — 8 байт по 8 бит, каждый байт это колонка или строка (зависит от библиотеки). На плашке матрицы можно нарисовать узор в карточке вручную — поставили восемь чекбоксов, увидели символ сразу. Скетч через LedControl.setRow(col, byte) зажигает строку байтом — старший бит слева или справа, как договоритесь в коде. Ловушка про «зеркальный текст» — из заголовка: я перевернул биты через bitswap, и неделю не понимал, почему символ поехал влево, а не вправо — а причина была в порядке столбцов.
- SPI на D10-D13: стандартный расклад Uno, CS на D10, CLK на D13, DIN (MOSI) на D11 — ничего паять не нужно.
- 64 пикселя 8x8: 8 байт, по байту на строку или столбец — в зависимости от вызова setRow/setColumn.
- LedControl(DIN, CLK, CS, 1): конструктор с одним модулем; setRow(addr, row, byte) зажигает строку байтом.
- setMaxIntensity(0..15): яркость от 0 до 15 — на плате это ток через сегмент, в браузере просто число.
- clearDisplay(addr): гасит матрицу; setShutdown(false) включает чип после старта.
Стартовый скетч: сердечко на 8x8
#include <LedControl.h> LedControl lc = LedControl(11, 13, 10, 1); // DIN, CLK, CS, 1 модуль byte heart[8] = { 0b00000000, 0b01100110, 0b11111111, 0b11111111, 0b11111111, 0b01111110, 0b00111100, 0b00011000}; void setup() { lc.shutdown(0, false); // вывести из сна lc.setIntensity(0, 8); // средняя яркость lc.clearDisplay(0);} void loop() { for (int r = 0; r < 8; r++) { lc.setRow(0, r, heart[r]); } delay(500);}Запустите скетч — матрица рисует сердце. Поменяйте единицы и нули в массиве heart, и узор изменится сразу. Полный разбор порядка бит и схемы — в уроке про MAX7219 матрицу; если SPI как шина для вас новое, начните с урока про основы SPI.
Бегущая строка: сдвиг массива по столбцам
#include <LedControl.h> LedControl lc = LedControl(11, 13, 10, 1); // Буквы 5x8, по 5 столбцов на букву, 1 столбец пробелаbyte H[] = {0x7E, 0x90, 0x90, 0x90, 0x7E};byte E[] = {0xFE, 0x92, 0x92, 0x92, 0x82};byte L[] = {0xFE, 0x80, 0x80, 0x80, 0x80};byte O[] = {0x7E, 0x81, 0x81, 0x81, 0x7E};byte* slovo[] = {H, E, L, L, O}; void setup() { lc.shutdown(0, false); lc.setIntensity(0, 8); lc.clearDisplay(0);} void loop() { for (int s = 0; s < 5 * 6 - 8; s++) { // сдвиг по длине строки for (int col = 0; col < 8; col++) { int srcCol = s + col; byte colData = 0; if (srcCol >= 0 && srcCol < 30) { int letter = srcCol / 6; int offset = srcCol % 6; if (offset < 5) colData = slovo[letter][offset]; } lc.setColumn(0, col, colData); } delay(150); }}Логика бегущей строки — сдвиг битмапа по столбцам: каждый кадр берёт восемь столбцов из строки, начиная со сдвига s, и пишет их в матрицу через setColumn. Скорость — константой delay; для плавности её меняют на millis-расписание. Ловушка «зеркальный текст» — в порядке бит в столбце: на одних модулях старший бит сверху, на других снизу, и без bitswap строка едет «отражённой». Проверьте направление в браузере, потом переносите на плату.
Граница: модель против живого модуля
| Проверка | Симулятор | Только железо |
|---|---|---|
| SPI: D10-D13, LedControl конструктор | да: пиксели зажигаются | то же, плюс реальные тайминги SPI |
| setRow/setColumn: байт в строку/столбец | да: массив → узор | то же, плюс ток через сегмент |
| setIntensity: яркость 0-15 | да: число, без тока | то же, плюс реальная нагрузка |
| clearDisplay, shutdown, setScanLimit | да: заглушки, не роняют скетч | то же, плюс управление чипом |
| Несколько матриц каскадом (daisy-chain) | одна матрица на стенд | до 8 модулей через cascade out |
| Ток 150 мА на матрицу и резистор RSET | не моделируется | да — на 5V нужен RSET 10 кОм |
Движок держит одну матрицу на стенд, без каскада: на живой плате выход DOUT матрицы идёт на DIN следующей, и в LedControl(…, 4) указывается число модулей. Скетч с четырьмя матрицами компилируется в симе, но зажжётся только первая. Электрические вопросы — ток 150 мА на матрицу, резистор RSET 10 кОм, отдельное питание при длинной цепи — только на плате: на 5V USB матрица светит тускло, и при каскаде из четырёх плата уходит в перезагрузку.
Грабли MAX7219
- Зеркальный текст: старший бит слева или справа — зависит от сборки модуля. В браузере проверьте направление, на плате — то же самое; в коде лечится bitswap.
- Забытый shutdown(0, false): чип стартует в спячке, матрица молчит. Строка shutdown(0, false) в setup обязательна, как и setIntensity.
- Несколько матриц: LedControl(…, 4) обещает 4 модуля, в браузере светит только первый — движок держит одну матрицу на стенд. Каскад проверяйте на плате.
- Ток через RSET: на 5V и RSET 10 кОм сегмент ест 150 мА; на USB Uno предел 500 мА, и четыре матрицы валит плату. На длинной цепи — отдельный 5V блок.
- Библиотеки путаются: LedControl, Max72xxPanel, MD_MAX72XX — у каждой свой порядок бит и API. Скетч из интернета под одну не соберётся на другой без правок.