Привет Ребятушки. Сегодня запилим бегущую строку на светодиодных модулях 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 миллисекунд.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#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, пиксели не высветятся на матрице!
Теперь напишем код, который отобразит на матрице смайл. Смайл зашифруем с помощью массива из восьми байт. Каждый байт массива будет отвечать за строку матрицы, а каждый бит в байте за точку в строке.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#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!».
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#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 практически готова. Настало время перейти к заключающей, программной части.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#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.
Если тебе понравилась статья, тогда поделись статьей со своими друзьями и оставь комментарий. Поддержи проект репостом или копеечкой.
русский не пашет!
Ну как это не пашет. Будьте внимательны и все получиться.
Русский работает из текста программы, из COM порта не читает правильную кодировку.
Здравствуйте, очень интересный проект! Начну с самой сути моей проблемы, я работаю на сборочной линии и после определенного количества производимой продукции мне приходится ходить в конец линии (около 10-15м,) каждые 15 минут. Счетчик есть только на пульте управления. Так вот мне бы хотелось собрать табло 16х64 из таких же матриц на ардуино с цифровой клавиатурой работающая без компьютера. Проблема лишь только в том что я почти ни чего в этом не понимаю, могу прошивку залить на дуино и спаять всё. Хотелось бы получить помощи или совета по созданию табло. За ранее спасибо.
P.S. Ардуино, матрица, клавиатура и блок питания.