Как подключить LED-панель 95x8 к Arduino
Для проекта нам понадобятся:
- светодиодная модульная панель;
- Arduino UNO или иная совместимая плата;
- соединительные провода (например, вот такой набор);
- персональный компьютер со средой разработки Arduino IDE.
1Описание и подключение светодиодной панели
Светодиодные панели подобного типа часто используются в рекламе, в магазинах, в транспорте и других местах, где не требуется выводить большие объёмы текстовой или графической информации. Часто с помощью подобных панелей текст выводится по принципу бегущей строки. Данные панели состоят из светодиодных модулей различной размерности. Это могут быть модули 8 на 8 «точек», 8 на 5 и другие. Модули соединяются между собой, образуя большие панели («матрицы»). В рассматриваемом случае один модуль имеет 8 светодиодов по высоте и 5 по ширине, и эти модули в количестве 19 штук располагаются на единой печатной плате друг за другом. Иногда модули могут располагаться в форме, близкой к квадрату.
Вся электронная «обвязка» LED матрицы расположена с обратной стороны платы. На печатной плате имеется маркировка "DISP95.PCB BY ZHOU 2004/02/28".
Для управления панелью применяется последовательный интерфейс, схожий с SPI. Сигналы управления поступают через разъём JP2, который представляет собой двухрядную «гребёнку» коннекторов типа PLD-40. Рядом с разъёмом JP2 находятся клеммы подключения питания. К ним припаяны два провода: жёлтый – GND, синий – VCC (+5 В).
Прежде чем подавать питание на LED панель, необходимо убедиться, что у источника питания хватит мощности, т.к. матрица потребляет довольно много. Один модуль может потреблять до 300 мА; умножаем на число модулей и получаем весьма приличный ток и, соответственно, потребляемую мощность.
Для того чтобы управлять таким большим числом светодиодов (19*5*8=760), разумеется, нужно иметь сдвиговый регистр. Что мы и наблюдаем: данная LED панель использует 12 сдвиговых регистров SM74HC595D, расположенных на её обратной стороне.
Сдвиговый регистр SM74HC595В – это китайский аналог американской микросхемы SN74HC595, который часто используется как драйвер для управления разнообразными дисплеями (LED, LCD и др.). В конце статьи можно скачать техническое описание на сдвиговый регистр SM74HC595, а также на оригинальную микросхему SN74HC595.
Ниже представлена таблица подключений светодиодной панели к Arduino. Здесь в скобках для LED панели показаны названия, соответствующие управляющим выводам сдвигового регистра, потому что именно он, по сути, и является управляющим элементом. В скобках для Arduino показаны названия выводов, которые относятся к режиму SPI.
Вывод разъёма JP2 на LED панели | Вывод Arduino |
---|---|
A (ADDR0) | D7 |
B (ADDR1) | D6 |
C (ADDR2) | D5 |
D (ENA) | D4 |
STB (RCLK) | D10 (SS) |
CLK (SRCLK) | D13 (SCK) |
DATA (SER) | D11 (MOSI) |
GND | GND |
Я не говорю, что это единственно возможный способ подключения светодиодной панели. Но если изучить техническое описание микросхемы HC595, то станет понятно, что для работы с выводами STB, CLK и DATA удобно использовать аппаратные ножки Arduino режима SPI (SS, SCK, MOSI). А для работы с выводами адресации (ADDR0..ADDR2) и разрешения записи (ENA) световой панели, в принципе, можно использовать любые цифровые пины Arduino.
2Управление LED панелью с помощью Arduino
Первый скетч будет базовым и довольно простым. Мы будем поочерёдно зажигать горизонтальные строки нашей LED панели.
Скетч для вывода линий на LED-панель
#include <SPI.h> // задаём назначение выводов Arduino: const byte A = 7; const byte B = 6; const byte C = 5; const byte D = 4; const byte STB = 10; const byte CLK = 13; const byte DATA = 11; void setup() { // назначаем режимы работы выводов: pinMode(A, OUTPUT); pinMode(B, OUTPUT); pinMode(C, OUTPUT); pinMode(D, OUTPUT); pinMode(STB, OUTPUT); pinMode(CLK, OUTPUT); pinMode(DATA, OUTPUT); // выставляем начальные значения: digitalWrite(A, LOW); digitalWrite(B, LOW); digitalWrite(C, LOW); digitalWrite(D, LOW); // разрешаем вывод на LED панель digitalWrite(STB, HIGH); // инициализируем режим SPI: SPI.begin(); // гасим все светодиоды: byte arrBlank[] = {255,255,255,255,255,255,255,255,255,255,255,255}; for (int row=0; row<8; row++) { writeLine(arrBlank); } delay(100); } byte arr[] = {0,0,0,0,0,0,0,0,0,0,0,0}; // 12 байтов = 12*8 бит = 96 бит - это одна строка LED панели (+1 лишний бит) void loop() { for (int row=0; row<8; row++) { setLine(row); // задаём номер строки LED матрицы writeLine(arr); // записываем в строку массив из 96 бит delay(100); // делаем задержку и повторяем } } // записывает 96 битов строки void writeLine(byte *ar) { digitalWrite(STB, LOW); // разрешаем передачу по SPI delay(1); for (int i=0; i<12; i++){ SPI.transfer(ar[i]); // передаём i-ый байт массива } digitalWrite(STB, HIGH); // завершаем передачу по SPI delay(1); } // задаёт номер строки, от 0 до 7 void setLine(byte lineNumber) { switch (lineNumber) { case 0: setAddr(0, 0, 0); break; case 1: setAddr(1, 0, 0); break; case 2: setAddr(0, 1, 0); break; case 3: setAddr(1, 1, 0); break; case 4: setAddr(0, 0, 1); break; case 5: setAddr(1, 0, 1); break; case 6: setAddr(0, 1, 1); break; case 7: setAddr(1, 1, 1); break; } } // выставляет адрес на пинах адреса: void setAddr(bool levA, bool levB, bool levC) { digitalWrite(A, levA); digitalWrite(B, levB); digitalWrite(C, levC); }
После загрузки и выполнения скетча получится что-то типа этого:
В динамике работа скетча со светодиодной панелью выглядит так:
Ключевые моменты в скетче следующие:
- запись данных происходит построчно;
- чтобы записать одну строку из 95-ти точек нужно передать в сдвиговый регистр 95-битовое число или, как сделано в скетче, массив;
- чтобы выбрать номер строки, с помощью пинов ADDR0..ADDR2 следует выставить её адрес (пины ADDRx образуют 3 бита: 000 – 1-ая строка, 001 – 2-ая, 010 – 3-я, 011 – 4-ая и т.п.);
- бит "1" гасит ячейку в строке, бит "0" – зажигает (например, передавая число 0x0F мы погасим 4 бита этого байта, а 4 бита зажгём).
Если убрать задержку 100 мс в основном цикле loop, то панель будет светиться вся, т.к. наше инерционное зрение не способно различать такие быстрые переключения строк. На этом основывается и работа мониторов и других дисплеев, в которых используется построчная развёртка кадров. При такой развёртке в каждый момент времени на экране отрисовывается только одна строка, а глаз хранит образ предыдущих строк, и в мозгу достраивается вся картинка.
3Вывод статического текста и изображенияна LED панель с помощью Arduino
Принцип работы с LED панелью заключается в том, что нужно зажигать c определённой частотой определённые светодиоды, чтобы вывести на матрицу изображение или текст. Ведь по сути, матрица – это дисплей с разрешением 8 на 95 точек. В следующем скетче выведем на матрицу неподвижный текст. Например, такой:
То, что на рисунке показано синими линиями пусть будут горящие светодиоды. Каждый светодиод будем описывать битом, равным "1", а каждый потухший – битом "0". Таким образом, каждая из 8-ми строк будет представлена массивом из 12-ти байтов. Например, первую строку будет описывать такой массив:
byte line0[] = {B01110111, B00000010, B01000000, B00000001, B11000000, B01000100, B00000000, B00000000, B00000000, B00000100, B00000000, B00000000};
В языке программирования для Arduino двоичные числа можно записывать таким образом: B11110000, что соответствует шестнадцатеричному 0xF0 или десятичному 240. Записывая число в двоичной нотации, становятся видны отдельные биты. Через это можно представить, как будет выглядеть рисунок в данной строке LED матрицы.
Красными вертикальными линиями для наглядности отделены друг от друга зоны, которые будут представлены отдельными байтами.
Алгоритм вывода текста (или изображения) предельно прост:
- перейти к нужной строке LED матрицы (выставить адрес строки);
- записать массив из 12-ти байтов (96 бит) в сдвиговый регистр.
Также немного переделаем функцию writeLine(). Пусть она принимает в качестве аргументов номер строки и описывающий её массив. Перенести номер строки в эту функцию – логичнее и просто выглядит красивее. Кроме того, будем записывать в сдвиговый регистр значение, объединённое по XOR (^) с числом 0xFF, то есть, инвертированное число. Это необходимо для того, чтобы описывать в массиве горящие точки битами "1", а не "0". Если бы мы передавали не инвертированное число, то на панели появилось бы инвертированное изображение.
Соединяя описанное, получим такой скетч:
Скетч для вывода статического текста на LED-панель
#include <SPI.h> const byte A = 7; const byte B = 6; const byte C = 5; const byte ENA = 4; // => D const byte STB = 10; const byte CLK = 13; const byte DATA = 11; void setup() { pinMode(A, OUTPUT); pinMode(B, OUTPUT); pinMode(C, OUTPUT); pinMode(ENA, OUTPUT); pinMode(STB, OUTPUT); pinMode(CLK, OUTPUT); pinMode(DATA, OUTPUT); digitalWrite(A, LOW); digitalWrite(B, LOW); digitalWrite(C, LOW); digitalWrite(ENA, HIGH); SPI.begin(); delay(100); } // задаём массивы, которые описывают изображение на LED панели: byte line0[] = {B01110111, B00000010, B01000000, B00000001, B11000000, B01000100, B00000000, B00000000, B00000000, B00000100, B00000000, B00000000}; byte line1[] = {B00100010, B00000010, B01000000, B00000010, B00100000, B01000100, B00000000, B00000000, B00000000, B00000100, B00001000, B00000000}; byte line2[] = {B00100010, B00000010, B01000000, B00000010, B00000000, B01001111, B00000000, B00000000, B00000000, B00000100, B00000100, B00000000}; byte line3[] = {B00111110, B00110010, B01000110, B00000001, B11000110, B01000100, B00110010, B01000000, B01100100, B10000100, B01100010, B00000000}; byte line4[] = {B00100010, B01001010, B01001001, B00000000, B00101001, B01000100, B00001010, B01000000, B10010100, B10000100, B00000010, B00000000}; byte line5[] = {B00100010, B01111010, B01001001, B00000010, B00101001, B01000100, B00111010, B01000000, B10000100, B10000000, B01100010, B00000000}; byte line6[] = {B00100010, B01000010, B01001001, B00110010, B00101001, B01000100, B01001010, B01001100, B10000100, B10000100, B00000100, B00000000}; byte line7[] = {B01110111, B00110011, B01100110, B00100001, B11000110, B01100011, B00111001, B11001100, B10000011, B10001110, B00001000, B00000000}; void loop() { writeLine(0, line0); writeLine(1, line1); writeLine(2, line2); writeLine(3, line3); writeLine(4, line4); writeLine(5, line5); writeLine(6, line6); writeLine(7, line7); } // записывает 96 битов строки void writeLine(byte line, byte *ar) { setLine(line); digitalWrite(STB, LOW); for (int i=0; i<12; i++){ SPI.transfer(ar[i]^0xff); } digitalWrite(STB, HIGH); } // задаёт номер строки, от 0 до 7 void setLine(byte lineNumber) { digitalWrite(ENA, LOW); delay(1); switch (lineNumber){ case 0: setAddr(0, 0, 0); break; case 1: setAddr(1, 0, 0); break; case 2: setAddr(0, 1, 0); break; case 3: setAddr(1, 1, 0); break; case 4: setAddr(0, 0, 1); break; case 5: setAddr(1, 0, 1); break; case 6: setAddr(0, 1, 1); break; case 7: setAddr(1, 1, 1); break; } digitalWrite(ENA, HIGH); } // выставляет на входах адреса число: void setAddr(bool levA, bool levB, bool levC) { digitalWrite(A, levA); digitalWrite(B, levB); digitalWrite(C, levC); }
В результате выполнения этого скетча получится вот такое изображение:
Конечно, всё это довольно занятно, но чаще всего такого рода панели используют для вывода текста в виде бегущей строки. Кроме того, довольно утомительно для каждого нового рисунка или надписи прописывать все 760 точек (95*8) матрицы вручную. Хотелось бы иметь какой-то механизм, который обеспечивал бы вывод текста в произвольном месте матрицы и автоматическое его перемещение. Этим и займёмся далее.
3Вывод динамического текста на LED панель с помощью Arduino
Продолжение следует…
Скачать вложения:
- Скачать datasheet на SM74HC595 (1010 Скачиваний)
- Скачать datasheet на SN74HC595 (656 Скачиваний)
Поблагодарить автора:
Поделиться
Похожие материалы (по тегу)
3 комментарии
-
aave1 30.01.2020 17:59 Комментировать
Решение подойдёт для любой LED-панели с подобным типом подключения. Конкретно это довольно старая модель, на печатной плате маркировка DISP95.PCB by ZHOU 2004/02/28, вряд ли её можно купить сегодня. Но такого типа панели используются там, где применяются дисплеи типа "бегущая строка".