Привет Ребятушки. Сегодня запилим бегущую строку на светодиодных модулях MAX7219 и Arduino. Задача очень простая и не потребует от нас больших знаний в области электроники и программирования. Для начала предлагаю изучить немного теории по устройству светодиодной матрицы, принципу ее подключения и посмотреть видео результата к которому мы будем стремиться на протяжении всей статьи.

Светодиодная матрица — это графический индикатор, который можно использовать для вывода простых изображений, букв и цифр. Я не ставлю задачу подробно разобраться с устройством матричных индикаторов, однако стоит заметить, что по сути матрица состоит и 8х8 светодиодов. По сути все сводиться к динамической индикации. Основываясь на этом, понятно, что группировать несколько матриц вместе задача не из простых. На каждый новый ряд или колонку матриц, нужно добавлять новый сдвиговый регистр вместе с проводами и резисторами, а по-хорошему еще и микросхему ULN2003.

К счастью, инженеры давно уже разработали специализированные микросхемы для управления разного рода индикаторами. В этой статье мы рассмотрим матричный модуль с микросхемой MAX7219. Как станет понятно позже, работать с таким модулем одно удовольствие.

Модуль светодиодной матрицы с микросхемой MAX7219

Модуль представляет из себя плату с микросхемой, необходимой для неё обвязкой и, собственно, матричным индикатором. Обычно индикатор не впаивают в плату, а вставляют в разъем. Это сделано для того, чтобы группу модулей можно было сначала закрепить на какой то поверхности винтами, а затем вставить в них матрицы.

[rev_slider Max7219]

У модуля есть пять выводов на каждой стороне. С одной стороны данные входят в модуль, с другой стороны данные выходят из модуля и передаются в следующий. Это позволяет соединять матрицы у цепочку.

Входной разъем / Выходной разъем :

  • VCC, GND — питание;
  • DIN — вход данных;
  • CS — выбор модуля (chip select);
  • CLK — синхроимпульс.

Работает модуль от напряжения 5 Вольт.

Вывод пикселей с помощью библиотеки Max72xxPanel

Для управления микросхемой MAX7219 воспользуемся библиотекой Max72xxPanel. Скачать её можно по ссылкам в конце статьи.

Установим библиотеку и напишем небольшой код, который будет выводить на дисплей всего одну точку с координатами x=3 и y=4. Точка будет мигать с периодом 600 миллисекунд.

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>

int pinCS = 10;
int numberOfHorizontalDisplays = 1; // количество матриц по-горизонтали
int numberOfVerticalDisplays = 1; // количество матриц по-вертикали

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

void setup() {
    matrix.setIntensity(4); // яркость от 0 до 15
}

void loop() {
    matrix.drawPixel(3, 4, HIGH); // зажигаем пиксель с координатами {3,4}
    matrix.write(); // вывод всех пикселей на матрицу
    delay(300);
    matrix.drawPixel(3, 4, LOW); // гасим пиксель
    matrix.write();
    delay(300);
}

Как уже говорилось ранее, матричные модули с микросхемой MAX7219 можно легко объединять. Именно для этой цели в начале программы мы задаем количество матриц по-горизонтали и по-вертикали. В данном случае используется одна матрица, так что оба этих параметра будут равны 1.

Важно отметить, что после включения и выключения пикселей с помощью функции drawPixel, необходимо вызвать функцию write. Без функции write, пиксели не высветятся на матрице!

Теперь напишем код, который отобразит на матрице смайл. Смайл зашифруем с помощью массива из восьми байт. Каждый байт массива будет отвечать за строку матрицы, а каждый бит в байте за точку в строке.

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>

int pinCS = 10;
int numberOfHorizontalDisplays = 1; // количество матриц по-горизонтали
int numberOfVerticalDisplays = 1; // количество матриц по-вертикали

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

const byte data[8] = {
    0b00111100,
    0b01000010,
    0b10100101,
    0b10000001,
    0b10100101,
    0b10011001,
    0b01000010,
    0b00111100
};

void setup() {
    matrix.setIntensity(7); // яркость от 0 до 15

    matrix.fillScreen(LOW); // очистка матрицы
    for ( int y = 0; y < 8; y++ ) {
        for ( int x = 0; x < 8; x++ ) {
            // зажигаем x-й пиксель в y-й строке
            matrix.drawPixel(x, y, data[y] & (1<<x));
        }
    }
    matrix.write(); // вывод всех пикселей на матрицу
}

void loop() {
}

Примечание. В библиотеке Max72xxPanel есть функция setRotation, которая задает ориентацию изображения на матрице. Например, если мы захотим повернуть смайл на 90 градусов, нужно будет сразу после вызова функции setIntensity вызвать setRotation с соответствующими аргументами:

matrix.setRotation( 0, 1 );

первый параметр — это индекс матрицы, в нашем случае он равен нулю; второй параметр — количество поворотов на 90 градусов.

Вывод текста с помощью библиотеки Adafruit-GFX-Library

Подобным же образом можно выводить на матрицу и любой другой символ, например, букву. Но чтобы иметь возможность отображать любую букву английского алфавита, нам необходимо будет определить в программе целых 26 восьмибайтных массива! Это очень муторно, и разумеется кто-то это уже сделал до нас.

В популярной библиотеке Adafruit-GFX-Library помимо функций для работы с графикой и текстом, имеется и база латинских букв в верхнем и нижнем регистрах, а также все знаки препинания и прочие служебные символы. Ссылка на библиотеку есть в конце статьи.

Отобразить символ на матрице можно с помощью функции drawChar.

drawChar( x, y, символ, цвет, фон, размер );

Первые два параметра функции отвечают за координаты верхнего левого угла символа. Третий параметр — это сам символ. Цвет символа в нашем случае будет равен 1 или HIGH, так как матрица двухцветная. Фон равен 0 или LOW. Последний параметр «размер» сделаем равным 1.

Напишем программу, которая будет по-очереди выводить на матрицу все буквы фразы: «HELLO WORLD!».

#include <SPI.h> 
#include <Adafruit_GFX.h> 
#include <Max72xxPanel.h>

int pinCS = 10;
int numberOfHorizontalDisplays = 1;
int numberOfVerticalDisplays = 1;

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

String tape = «HELLO WORLD»;
int wait = 800;

void setup() {
matrix.setIntensity(1); // яркость от 0 до 15
}

void loop() {
for ( int i = 0 ; i < tape.length(); i++ ) {
matrix.fillScreen(LOW);
matrix.drawChar(0, 0, tape[i], HIGH, LOW, 1);
matrix.write();
delay(wait);
}
}

Примечание. В библиотеке Adafruit_GFX имеется множество функций для работы с графикой. Например, drawCircle( 3, 3, 2, HIGH ) начертит окружность с центром {3,3} и радиусом 2. Последний параметр — цвет, но в случае монохромной матрицы он равен 1 или HIGH. Функция drawLine( 0, 0, 3, 6, HIGH ) начертит отрезок между точками {0,0} и {3,6}.

Бегущая строка на max7219

И так надеюсь мы разобрались с устройством и принципом вывода на одиночную матрицу. Теперь перейдем непосредственно к бегущей строке.

Что потребуется?

Для реализации идеи потребуется совсем немного деталей:

  • два светодиодных модуля, состоящих из четырёх матриц 8 на 8 пикселей;
  • соединительные провода;
  • плата Arduino Nano;

Схема

На печатной плате используемого светодиодного модуля расположено 4 матрицы размером 8 на 8 пикселей. Каждое светодиодное табло управляется микросхемой  MAX7219.

[rev_slider MAX7219BY8]

MAX7219 представляет собой контроллер управления led-дисплеями, матрицами с общим катодом и дискретными светодиодами в количестве до 64 шт. Для более комфортного восприятия информации, выводимой на светодиодное табло, рекомендуется устанавливать несколько модулей. Для этого их объединяют в последовательно включенные группы, то есть выход первого модуля (out) подключают к входу второго модуля (in). Моя сборка состоит из двух модулей (16 матриц), длины которых вполне хватит для удобного прочтения целых предложений. При этом подключение сборки к Arduino производиться точно также как и к одиночному модулю.

Программирование бегущей строки.

Бегущая строка из Arduino и светодиодных модулей под управлением MAX7219 практически готова. Настало время перейти к заключающей, программной части.

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>

int pinCS = 10; // Подключаем CS к 10-му пину, DIN к MOSI и CLK к SCK 
int numberOfHorizontalDisplays = 1; // Количество модулей по горизонтали
int numberOfVerticalDisplays = 8; // Количество модулей по вертикали
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

String tape = "";
int wait = 10; // Скорость прокрутки в миллисикундах

int spacer = 1; // Промежуток между символами (кол-во точек)
int width = 5 + spacer; // Ширина символа 

/* Перекодировка русского шрифта из UTF-8 в Windows-1251 */

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;
  while (i < k) {
    n = source[i]; i++;
    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB7; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
/* Код для работы с com-портом */
String Serial_Read() {
  unsigned char c; // переменная для чтения сериал порта
  String Serial_string = ""; // Формируемая из символов строка
  while (Serial.available() > 0) { // Если в сериал порту есть символы
    c = Serial.read(); // Читаем символ
    //Serial.print(c,HEX); Serial.print(" "); Serial.print(c);
    if (c == '\n') {  // Если это конец строки
          return Serial_string; // Возвращаем строку 
    }
    if (c == 0xB8) c = c - 0x01;  // Коррекция кодов символа под таблицу ???? так как русские символы в таблице сдвинуты относительно стандартной кодировки utf на 1 символ
    if (c >= 0xBF && c <= 0xFF) c = c - 0x01;
    Serial_string = Serial_string + String(char(c)); //Добавить символ в строку
  }
  return Serial_string; 
}

void setup() {
  Serial.begin(9600);
  tape = utf8rus("QSY.BY Amateur Radio WorkShop"); // Этот текст выводиться при включении или если в com-порт не пришла информация 
  matrix.setIntensity(3); // Яркость от 0 до 15
  matrix.setRotation(matrix.getRotation()+3); //1 - 90  2 - 180   3 - 270

}
void loop() {

  if (Serial.available()){
    tape=Serial_Read();
  } 
  for ( int i = 0 ; i < width * tape.length() + matrix.width() - 1 - spacer; i++ ) 
       {
    matrix.fillScreen(LOW);

    int letter = i / width; // Номер символа выводимого на матрицу 
    
    int x = (matrix.width() - 1) - i % width;  
    int y = (matrix.height() - 8) / 2; // Центрируем текст по вертикали

    while ( x + width - spacer >= 0 && letter >= 0 ) {
      if ( letter < tape.length() ) {
        matrix.drawChar(x, y, tape[letter], HIGH, LOW,1);
      }
      letter--;
      x -= width;
    }
    matrix.write(); // Вывод сообщения на экран
    delay(wait);
  }
}

Расписывать код не вижу смысла. Он и так хорошо прокомментирован. Однако есть некоторые особенности, о которых стоит упомянуть.

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

Кусок кода для работы с com-портом, нужен для того чтобы оперативно менять текст сообщения выводимого на светодиодный модуль. Однако он нужен нам не только для этого. В дальнейшем посредством этой функции мы свяжем наш Telegram Bot и бегущую строку на Arduino.

Если тебе понравилась статья, тогда поделись статьей со своими друзьями и оставь комментарий. Поддержи проект репостом или копеечкой.

4 КОММЕНТАРИИ

  1. Здравствуйте, очень интересный проект! Начну с самой сути моей проблемы, я работаю на сборочной линии и после определенного количества производимой продукции мне приходится ходить в конец линии (около 10-15м,) каждые 15 минут. Счетчик есть только на пульте управления. Так вот мне бы хотелось собрать табло 16х64 из таких же матриц на ардуино с цифровой клавиатурой работающая без компьютера. Проблема лишь только в том что я почти ни чего в этом не понимаю, могу прошивку залить на дуино и спаять всё. Хотелось бы получить помощи или совета по созданию табло. За ранее спасибо.
    P.S. Ардуино, матрица, клавиатура и блок питания.

ОСТАВЬТЕ ОТВЕТ

Пожалуйста, введите ваш комментарий!
пожалуйста, введите ваше имя здесь

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.