Рейтинг@Mail.ru

Как подключить LED-панель 95x8 к Arduino

автор:
3 comments Arduino
Print Friendly, PDF & Email
Подключаем к Arduino LED панель, составленную из нескольких модулей 5x8 светодиодов.

Для проекта нам понадобятся:

  • светодиодная модульная панель;
  • 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 мА; умножаем на число модулей и получаем весьма приличный ток и, соответственно, потребляемую мощность.

Разъём управления LED-панелью
Разъём управления LED-панелью

Для того чтобы управлять таким большим числом светодиодов (19*5*8=760), разумеется, нужно иметь сдвиговый регистр. Что мы и наблюдаем: данная LED панель использует 12 сдвиговых регистров SM74HC595D, расположенных на её обратной стороне.

Сдвиговый регистр SM74HC595D светодиодной панели
Сдвиговый регистр 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)
GNDGND

Я не говорю, что это единственно возможный способ подключения светодиодной панели. Но если изучить техническое описание микросхемы HC595, то станет понятно, что для работы с выводами STB, CLK и DATA удобно использовать аппаратные ножки Arduino режима SPI (SS, SCK, MOSI). А для работы с выводами адресации (ADDR0..ADDR2) и разрешения записи (ENA) световой панели, в принципе, можно использовать любые цифровые пины Arduino.

Подключение Arduino Uno к разъёму управления светодиодной панели
Подключение Arduino Uno к разъёму управления светодиодной панели

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);
}

После загрузки и выполнения скетча получится что-то типа этого:

Управление светодиодной панелью с помощью Arduino
Управление светодиодной панелью с помощью Arduino

В динамике работа скетча со светодиодной панелью выглядит так:

Ключевые моменты в скетче следующие:

  • запись данных происходит построчно;
  • чтобы записать одну строку из 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);
}

В результате выполнения этого скетча получится вот такое изображение:

Вывод статического текста на светодиодную панель с помощью Arduino
Вывод статического текста на светодиодную панель с помощью Arduino
Вывод статического текста на светодиодную панель с помощью Arduino
Вывод статического текста на светодиодную панель с помощью Arduino
Вывод статического текста на светодиодную панель с помощью Arduino
Вывод статического текста на светодиодную панель с помощью Arduino

Конечно, всё это довольно занятно, но чаще всего такого рода панели используют для вывода текста в виде бегущей строки. Кроме того, довольно утомительно для каждого нового рисунка или надписи прописывать все 760 точек (95*8) матрицы вручную. Хотелось бы иметь какой-то механизм, который обеспечивал бы вывод текста в произвольном месте матрицы и автоматическое его перемещение. Этим и займёмся далее.

3Вывод динамического текста на LED панель с помощью Arduino

Продолжение следует…

Download attachments:

Last modified onСреда, 19 Февраль 2020 21:41 Read 1632 times
Ключевые слова: :

Поделиться

Print Friendly, PDF & Email

3 comments

  • SMaltsev
    SMaltsev Среда, 29 Январь 2020 06:07 Ссылка на комментарий

    Добрый день.
    А что собственно за панель? Где купить?

  • aave1
    aave1 Четверг, 30 Январь 2020 17:59 Ссылка на комментарий

    Решение подойдёт для любой LED-панели с подобным типом подключения. Конкретно это довольно старая модель, на печатной плате маркировка DISP95.PCB by ZHOU 2004/02/28, вряд ли её можно купить сегодня. Но такого типа панели используются там, где применяются дисплеи типа "бегущая строка".

  • Алексей
    Алексей Среда, 26 Февраль 2020 07:29 Ссылка на комментарий

    Отличный проект, ждем продолжение!

Leave a comment