Китай надає за невелику ціну величезну кількість не лише електронних пристроїв, а й їх компонентів. Невелика матриця, складена з світловипромінюючих діодів може показувати потрібну вам інформацію, імовірно це числа, оскільки роздільна здатність не дуже велика, 8 на 8 світлодіодівкожен діаметром 3 мм. Ця матриця світить червоним, адже він найбільш помітний і привертає увагу більше, ніж інші кольори.
Якщо у вас є кілька таких матриць на світлодіодах, ви можете з'єднувати їх, створюючи великі за площею інформаційні табло.
Матричний дисплей - пристрій, що складається з LED матриці 8x8 і плати управління на базі мікросхеми MAX7219 з мінімальною необхідною обв'язкою. На фото ви вже бачите готовий пристрій, але мені воно прийшло поштою ось у такому вигляді, так що довелося взяти в руки паяльник і спаяти все у потрібному вигляді.
Базове підключення до плати Arduino Nano показано на важливій схемі.
Як видно зі схеми - все просто, потрібно лише з'єднати проводами контакти обох плат у такому порядку:
Arduino Nano | Matrix 8x8 |
PIN 12 | PIN DIN |
PIN 11 | PIN CLK |
PIN 10 | PIN CS |
PIN 5V | PIN 5V |
PIN GND | PIN GND |
Отже, настав час попрацювати з кодом, і для того щоб запустити LED матрицю, потрібно завантажити та встановити бібліотеку LedControl. Бібліотека підтримує роботу з мікросхемами MAXIM 7221 і 7219. LED матриця як драйвер використовує MAX7219, це те, що нам потрібно. Я думаю, що потрібно почати з невеликого скетчу, що демонструє базові функції цієї бібліотеки. У скетчі, для включення/вимкнення світлодіодів використана функція setRow(). Синтаксис виклику функції setRow():
matrix.setRow(0, row, col, set);
Де matrix- об'єкт класу LedControl
0 - адреса пристрою на шині SPI, в даному випадку пристрій один, і нумерація починається з нульової адреси
row- ряд(Можливі значення від 0 до 7)
col- колонка (можливі значення від 0 до 7)
set- значення установки ( true- увімкнути, false- Вимкнути)
matrix.setRow(0, 1, 4, true)
Включити на матриці світлодіод, що знаходиться в 1-му ряду та в 4-му стовпці.
Ще приклад:
int x = 1;
int y = 4;
matrix.setRow(0, x, y, true);
matrix.setRow(0, x, y, false);
Те саме тільки з використанням змінних, і наступним вимкненням запаленого світлодіода за заданими координатами. Отже, у скетчі програється кілька анімацій з використанням функції setRow().
#include "LedControl.h" //Синтаксис створення класу LedControl(dataPin,clockPin,csPin,numDevices) //Де LedControl - об'єкт класу //dataPin - пін на платі Arduino до якого буде підключений пін DIN //clockPin - пін на платі Arduino до якого буде підключено пін CLK //csPin - пін на платі Arduino до якого буде підключено пін CS //numDevices - кількість пристроїв на шині //Створити об'єкт класу matrix у нашому випадку з одним підключеним пристроєм LedControl matrix = LedControl(12, 11 , 10; 1); //Час затримки включення/вимикання світлодіода на матриці const int delayValue = 100; //Прототипи функцій //Послідовне включення/вимкнення void PointSerialSet(); //Змійка праворуч - ліворуч void PointRigthToLeft(); //Змійка знизу - догори void PointDownToUp(); //Змійка зліва - праворуч void PointLeftToRigth(); //Змійка зверху - донизу void PointUpToDown(); // Ефект - загасаючий імпульс void PointFading (); / / Ефект - імпульс void PointPulse (); //Ефект - наростаючий імпульс void PointClimbing (); //Ефект закручування спіралі всередину void PointToSpiralIn(); //Ефект розкручування спіралі назовні void PointToSpiralOut(); void setup() ( //Пристрої з адресою 0 вийти зі сплячого режиму за умовчанням matrix.shutdown(0, false); //Встановити яскравість Led матриці на 8 //Можливі значення від 0 до 15 matrix.setIntensity(0, 8) //Очистити дисплей matrix.clearDisplay(0); ) void loop() ( //Викликаємо функції по черзі PointSerialSet(); PointRigthToLeft(); PointDownToUp(); PointClimbing(); PointToSpiralIn(); PointToSpiralOut(); ) //Тіла функцій void PointSerialSet() ( //Використовуємо функцію setLed(address, row, col, set) //Послідовне включення по рядах for(int i = 0; i< 8; i ++) { for(int j = 0; j < 8; j ++) { //Включить светодиод matrix.setLed(0, i, j, true); delay(delayValue); //Выключить светодиод matrix.setLed(0, i, j, false); } } } void PointRigthToLeft() { //Используем функцию setLed(address, row, col, set) //Змейка справа - налево for(int i = 7; i >= 0; i --) ( for(int j = 7, n = 0; j >= 0, n< 8; j --, n ++) { if((i % 2) >0) ( matrix.setLed(0, j, i, true); delay(delayValue); matrix.setLed(0, j, i, false); ) else ( matrix.setLed(0, n, i, true); delay(delayValue); matrix.setLed(0, n, i, false); ) ) ) ) void PointDownToUp() ( //Використовуємо функцію setLed(address, row, col, set) //Змійка знизу - вгору for(int i = 7; i >= 0; i --) ( for(int j = 7, n = 0; j >= 0, n< 8; j --, n ++) { if((i % 2) >0) ( matrix.setLed(0, i, n, true); delay(delayValue); matrix.setLed(0, i, n, false); ) else ( matrix.setLed(0, i, j, true); delay(delayValue);matrix.setLed(0, i, j, false); i = 0;< 8; i ++) { for(int j = 7, n = 0; j >= 0, n< 8; j --, n ++) { if((i % 2) >0) ( matrix.setLed(0, j, i, true); delay(delayValue); matrix.setLed(0, j, i, false); ) else ( matrix.setLed(0, n, i, true); delay(delayValue); matrix.setLed(0, n, i, false); ) ) ) ) void PointUpToDown() ( //Використовуємо функцію setLed(address, row, col, set) //Змійка зверху - вниз for(int i = 0;< 8; i ++) { for(int j = 7, n = 0; j >= 0, n< 8; j --, n ++) { if((i % 2) >0) ( matrix.setLed(0, i, n, true); delay(delayValue); matrix.setLed(0, i, n, false); ) else ( matrix.setLed(0, i, j, true); matrix.setLed(0, i, j, false); ) ) ) ) void PointFading() ( //Використовуємо функцію setLed(address, row, col, set) //Ефект загасання int upValue = 0; int downValue = 7; for(int i = 0; i< 8; i ++) { if(i % 2) { for(int n = downValue; n >= upValue; n --) ( matrix.setLed(0, n, i, true); delay(delayValue); matrix.setLed(0, n, i, false); ) downValue --; ) else ( for (int j = upValue; j< downValue + 1; j ++) { matrix.setLed(0, j, i, true); delay(delayValue); matrix.setLed(0, j, i, false); } upValue ++; } } } void PointClimbing() { //Используем функцию setLed(address, row, col, set) //Эффект затухания int upValue = 4; int downValue = 4; for(int i = 0; i < 8; i ++) { if(i % 2) { for(int n = downValue; n >= upValue; n --) ( matrix.setLed(0, n, i, true); delay(delayValue); matrix.setLed(0, n, i, false); ) downValue ++; ) else ( for (int j = upValue; j< downValue + 1; j ++) { matrix.setLed(0, j, i, true); delay(delayValue); matrix.setLed(0, j, i, false); } upValue --; } } } void PointPulse() { //Используем функцию setLed(address, row, col, set) //Эффект пульса for(int i = 0; i < 8; i ++) { if(i == 4) { for(int climb = i; climb >= 0; climb --) ( matrix.setLed(0, climb, i, true); delay(delayValue / 4); matrix.setLed(0, climb, i, false); ) for(int fade = 1; fade< 8; fade ++) { matrix.setLed(0, fade, i, true); delay(delayValue / 4); matrix.setLed(0, fade, i, false); } } else { matrix.setLed(0, 4, i, true); delay(delayValue); matrix.setLed(0, 4, i, false); } } } void PointToSpiralIn() { //Используем функцию setLed(address, row, col, set) //Эффект спирали внутрь int lengthX = 8; // Ширина матрицы int lengthY = 8; // Высота матрицы int pointX = 0; int pointY = 0; int dir = 0; // Направление (0 - вправо, 1 - вниз, 2 - влево, 3 - вверх) int offset = 0; // Смещение // Перебираем всю матрицу for (int i = 0; i < lengthX * lengthY; i++) { matrix.setLed(0, pointY, pointX, true); delay(delayValue); matrix.setLed(0, pointY, pointX, false); if(dir == 0) { pointX ++; if(pointX >= lengthX - 1 - offset) (dir = 1;) continue; ) if(dir == 1) ( pointY ++; if(pointY ><= offset) { dir = 3; } continue; } if(dir == 3) { pointY --; if(pointY <= offset + 1) { dir = 0; offset ++; pointY = offset; } continue; } } } void PointToSpiralOut() { //Используем функцию setLed(address, row, col, set) //Эффект спирали внаружу int lengthX = 8; // Ширина матрицы int lengthY = 8; // Высота матрицы int pointX = 3; //начать с этих координат int pointY = 3; //начать с этих координат int dir = 0; // Направление (0 - вправо, 1 - вниз, 2 - влево, 3 - вверх) int offset = 3; // Смещение // Перебираем всю матрицу for (int i = 0; i < lengthX * lengthY; i++) { matrix.setLed(0, pointY, pointX, true); delay(delayValue); matrix.setLed(0, pointY, pointX, false); if(dir == 0) { pointX ++; if(pointX >= lengthX - 1 - offset) (dir = 1;) continue; ) if(dir == 1) ( pointY ++; if(pointY >= lengthY - 1 - offset) ( dir = 2; ) continue; ) if(dir == 2) ( pointX --; if(pointX<= offset - 1) { dir = 3; } continue; } if(dir == 3) { pointY --; if(pointY <= offset - 1) { dir = 0; offset --; pointY = offset; } continue; } } }
Відео роботи скетчу:
Ця стаття створена для тих, хто купив голу матрицю 8х8 та зсувні регістри 74hc595 і не знає як це все підключити.
Я довго шукав в інтернеті інструкції про те, як підключити перераховані вище компоненти, але знаходив або не для моїх регістрів або з неробочими скетчами, тому вирішив, що все-таки доведеться попрацювати руками і головою, щоб порадувати себе картинками 8*8.
Знайшовши в інтернеті датішити до матриці та зсувних регістрів, намалював таку схему:
12-а нога в обох мікросхем (latch pin), задля економії портів загальна, т.к немає сенсу замикати регістри у час. Частина пінів матриці (аноди) підключені через струмообмежуючі резистори номіналом 220ом. Все інше за схемою дуже просто. Про всяк випадок картинки з розпинуванням матриці.
Зображення доведеться виводити рядкове (інакше з подібними матрицями ніяк), з маленькою затримкою (людське око практично не розрізняє затримки в 1мс).
У скетчі намагався все пояснювати. При завантаженні в плату на дисплеї відображатимуться цифри, які ми надішлемо до монітора порту ардуіно.(див. відео)
Фото готового пристрою (на екрані зигзаг, у скетчі його зображення зберігається у масиві pic)
Надалі спробую зробити на цьому дисплеї щось цікаве.
Нарешті доїхали з піднебесної матричні модулі. Кожен модуль складається з мікросхеми MAX7219(), світлодіодної матриці, в обв'язці стоять один конденсатор та один резистор.
Керується MAX7219 за інтерфейсом SPI.
Мікросхеми у кластері з'єднані послідовно. Читав в інтернеті, що максимально можливе послідовне підключення припускає всього 8 штук MAX7219. Чи не вірте. 16 модулів з'єднав, і все чудово працює.
Модулі, представлені на Алі, бувають у кількох варіантах виконання. Найбільшою популярністю користуються 2 види: з мікросхемою в DIP та у SOIC корпусах. Модуль з DIP-мікросхемою більшого розміру і не такий зручний при з'єднанні в кластер. З'єднувати доведеться купою дротів.
Модулі з мікросхемою в SOIC-корпусі мають розмір світлодіодної матриці та з'єднуються пайкою або джамперами. Виходить красиво та акуратно.
Найбільш відомими бібліотеками для роботи з матрицями та кластерами є MAX72xx Panel від Марка Райсаі Parola від MajicDesigns :перша бібліотека простіше у використанні, друга складніша з більшими можливостями. Розпишу докладніше.
При використанні MAX72xx Panel обов'язкове встановлення бібліотеки Adafruit GFX.
Для русифікації тексту потрібно буде завантажити ЦЕЙ ФАЙЛта замінити стандартний файл glcdfont.c у каталозі Arduino/Libraries/Adafruit-GFX-Library-master. Також у цьому файлі описані, крім потрібних букв та цифр, купа будь-яких символів. Не всі вони можуть стати в нагоді. Зображення нижче пояснює як формуються символи.
При необхідності Ви можете створити свої символи та замінити ними будь-які файли, які не використовуються. Практично всі точкові шрифти, що використовуються в різних бібліотеках, сформовані таким чином.
Отже, бібліотеки MAX72xx Panel та Adafruit GFX встановлені, файл glcdfont.c замінено. Запускаємо Arduino IDE, відкриваємо ФАЙЛ. У скетчі є функція utf8rus. Вона забезпечує перекодування таблиці символів для російської. Вона потрібна лише для нормального виведення із програми, тобто у програмі потрібний текст пишеться російською. Якщо текст вводиться через СОМ-порт, корекція кодів символу відбувається у функції Serial_Read. У IDE та консолі розробники використовували різні кодування.
На початку файлу є рядки необхідні для роботи бібліотеки.
int numberOfHorizontalDisplays = 1;
int numberOfVerticalDisplays = 16;
У мене модулі із мікросхемою в SOIC-корпусі. Вони мають невелику особливість. Матриця у модулів встановлена на 90 градусів. Це плата за зручність з'єднання. Якщо запустити скетчі, що йдуть у комплекті з бібліотеками, вони виводитимуть текст знизу нагору в кожному модулі. Текст виводиться зигзагами. Для лікування цієї недуги бібліотеці треба сказати, що вертикальних дисплеїв 16 (фізично вони розташовані горизонтально). І потім у void Setup вказати бібліотеці рядок
matrix.setRotation(matrix.getRotation() + 1);
Вона програмно переверне кожну матрицю. І відображатиметься все буде нормально.
У модулів із DIP-корпусом мікросхем такого немає. Там все красиво, окрім купи дротів.
Бібліотека MAX72xx Panel є досить скромною. Візуальних ефектів виводу немає. Кластер сприймається як одне ціле. Набагато кращі справи з MD Parola.
Власники модулів із мікросхемою в SOIC-корпусі також зіштовхнуться із проблемою орієнтації модулів у кластері. Тільки виглядає це трохи інакше, ніж у MAX72xx. Тут модулі виявляться ніби не у своїй черзі.
Скетч HelloWorld із зразків у комплекті з бібліотекою.
Програмно в скетчі мені не вдалося вилікувати цю недугу. Я вилікував його по-іншому. У файлі Adruino/libraries/MD_MAX72xx_lib.h в кінці потрібно знайти рядки як на картинці.
І виправити у виділеному рядку виділену 1 на 0. Зберегти файл. Arduino IDE не можна перезавантажувати. Заливаємо, дивимось.
Тепер можна використовувати 24 ефекти анімації. Анімація запускається командою P.displayText(«Текст для виведення», «вирівнювання тексту», швидкість, затримка показу, ефект появи, ефект зникнення). Як бачите, налаштувань досить багато.
І самий смак - поділ кластера на віртуальні зони. Із зонами працювати не дуже складно. Скетч не викладаю, він є у зразках, що йдуть із бібліотекою. Тепер виводити годинник на початку кластера і рядок з новинами на модулях, що залишилися, можна без проблем, майже.
Як ви вже здогадуєтесь, проблема з кириличними літерами. Вона теж можна вирішити. Поруч із попереднім файлом у тій же директорії лежить файлик MD_MAX72xx_font.cpp. Це файл шрифту. Символи в ньому сформовані аналогічно до файлу шрифту GFX бібліотеки. Є невелика відмінність. Тут розмір символу може бути меншим за 5 точок. У бібліотеці Adafruit GFX знак оклику, наприклад, займає також 5 точок шириною, як і будь-який інший символ, тільки використовується один ряд точок. Інші не світяться, але використовуються під символ. У Parola той же знак оклику займає також один ряд точок, тільки поруч не порожні точки, а можуть стояти сусідні символи. Зрозуміліше розібратися по картинці.
Доповнити файл кириличними символами аналогічно файлу з першої розглянутої бібліотеки поки немає часу. Якщо хтось це зробить і надішле мені файл, я додам його до цієї статті, і Вам будуть вдячні і я, і гості мого сайту.
Підсумок. Бібліотека MAX72xx Panel від Марка Райса проста у використанні та розумінні, але з бідним функціоналом.
Бібліотека Parola від MajicDesigns складніша і її можливостей вистачить практично для будь-якого застосування.
На попередніх уроках ми навчилися за допомогою зсувного регістру. Це виявилося трохи складніше, ніж із висновків загального призначення. Проблема, яку ми тоді мали вирішити, полягала в обмеженій кількості керованих висновків у контролера Ардуїно. Апогеєм же наших досліджень стало використання динамічної індикації для . Тепер настав час ще трохи ускладнити завдання: вчимося працювати зі світлодіодною матрицею.