Бегущая строка на дисплее 1602. Уроки Arduino: создаем бегущую строку с помощью микроконтроллера. Программирование бегущей строки

Бегущая строка в LCD на HD44780.

Поиск "готового решения" бегущей строки на Си результата не дал. Поэтому пришлось делать самому.

Этот "кусок" кода позволяет выводить бегущую строку (справа-налево), в любом месте и с использованием любого количества знакомест, в LCD индикаторах с контроллером HD44780 или аналогичном.

Первое, на чем нужно остановиться, это то, что язык Си не позволяет работать со строками "напрямую". То есть невозможно скопировать символ из одной строки в другую при помощи оператора присваивания (= )... для этого нужно использовать специальную функцию strncpy() . Вообще говоря, для работы со строками в Си используются несколько функций. В самоМучителях использованию этих функций посвящена отдельная глава. В Help"e на CV_AVR описание функций для работы со троками находится в разделе " String Functions" . Прототипы этих функций находятся в файле string.h .

"...исходная строка..." - строка символы из которой нужно выводить в "бегущей" строке;

"...отображаемые символы..." - собственно "бегущая строка".

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

1. Отображаемые символы сдвигаются справо налево. Крайний левый при этом "теряется".

2. После сдвига, в крайний правый символ копируется очередной символ из исходной строки.

3. При достижении конца исходной строки, очередным становится первый символ исходной строки.

Для сдвига символов - для сдвигаемой ячейки считывается код символа из экранного ОЗУ (DDRAM) HD44780 и записывается в левостоящую ячейку ОЗУ.

Согласно DataSheet на HD44780 левый символ верхней строки имеет адрес в DDRAM - 0x00, а левый символ нижней строки - 0x40. При этом нужно помнить, что для того чтобы обратиться именно к экранному ОЗУ (а не к ОЗУ знакогенератора) необходимо чтобы бит RS был равен 1 (RS является старшим битом в байте адреса см.DataSheet).

В итоге получаем, что для того чтобы "обратиться" ко второму слева символу верхней строки необходимо "работать" с адресом 0x01 | 0x80 = 0x81 .

Функции записи и чтения "внутреннего содержимого" HD44780 есть в библиотеке (прототипы в lcd.h ).... поэтому..собственно программа:

/* для CV_AVR

В данном примере бегущая строка выводиться в разряды с 8 (0xC7) по 16 нижней строки 16-ти разрядного индикатора.

. ......

#include

unsigned char n_sim=1,m_end=43; //43 - дина строки в примере
...........

beg_stroka(){
unsigned char i;

// сдвиг бегущей строки

if(beg_str){
for(i=0;i<9;i++)lcd_write_byte(0xC7+i,lcd_read_byte(0xC8+i));
beg_str=0;

// запись очередного символа в крайний правую позицию

lcd_gotoxy(15,1);
lcd_putchar(ish_str);
if(++n_sim>m_end)n_sim=1;
}
}

Глоссарий:

n_sim - указатель положения текущего символа в исходной строке;

m_end - общее количество символов в исходной строке;

beg_str - бит "разрещающий" сдвиг. C его помощью можно регулировать скорость "бега";

ish_str - исходная строка.

Скорее всего, в каждом из существующих компиляторов Си имеются библиотечные функции для работы с HD44780. Поэтому "переделать" программу под "свой" компилятор не составит труда.

Исходную строку я "готовлю" при помощи известной утилиты "HD44780.exe". При ее использовании, в коментариях, указывается длина строки: "/* Maximum length of a line: 43 byte */"

QAPASS LCD 1602 русский шрифт не поддерживает, но можно вывести кириллицу на Arduino с помощью создания собственных символов. Рассмотрим, как сделать любые символы и буквы на кириллице на LCD дисплее Ардуино. Для этого нам потребуется использовать в скетче переменную byte и функцию lcd.createChar () . Сразу отметим, что объем памяти на Ардуино для знаков ограничен всего восемью символами.

Как вывести свой символ на LCD 1602

Вывести свой символ или кириллическую букву на дисплей поможет таблица знакогенератора (CGROM). Такой вид памяти в Ардуино, как CGRAM, может хранить собственные символы, но размер памяти ограничен и может вместить лишь 8 собственных символов. Один из нестандартных символов, который пригодится для создания домашней метеостанции — знак градуса. Давайте нарисуем символ.


Для начала возьмите листок бумаги и нарисуйте на нем таблицу, где будет 5 столбцов и 8 строчек. Далее заштрихуйте в таблице клеточки (смотри фото выше), которые должны высвечиваться на дисплее. Дело в том, что каждый символ на дисплее состоит из пикселей (5 пикселей в ширину и 8 пикселей в высоту). Далее представим наш символ в виде массива данных, состоящего из восьми элементов — восьми строк.

Выводим на LCD 1602 собственный символ

Для занятия нам понадобятся следующие детали:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • LCD монитор 1602;
  • провода «папа-мама».

Подключение LCD дисплея по I2C производится четырьмя проводами «папка-мамка» - 2 провода данных и 2 провода питания. Если вы подключаете дисплей Ардиуно УНО, используйте следующую схему — вывод SDA подключается к порту A4, вывод SCL – к порту A5 и два провода питания — GND и 5V. Если QAPASS 1602 подключается по шине I2C к Arduino Mega , то на плате имеются соответствующие порты — SDA и SCL.

Скетч для создания символа на LCD I2C

#include #include // создаем свой символ и присваиваем ему имя "simvol" byte simvol = { 0b01100, 0b10010, 0b10010, 0b01100, 0b00000, 0b00000, 0b00000, 0b00000 }; void setup () { lcd.init (); // инициализация LCD дисплея lcd.backlight (); lcd.createChar (1, simvol); lcd.setCursor (0,0); // ставим курсор на 1 символ первой строки lcd.print (char (1)); // печатаем символ на первой строке } void loop () { }

Пояснения к коду:

  1. с помощью массива byte simvol = { }; мы зашифровали знак градуса, который нарисовали ранее на листочке бумаги;
  2. функция lcd.createChar(num, data); создает пользовательский символ для LCD, где в скобках указан num — номер символа и data — данные о массиве.
  3. каждая строка массива начинается с 0b — «нуль» и прописная «b».

Выводим на LCD 1602 русский шрифт

QAPASS дисплей поддерживает 8 новых символов (пронумерованных от 0 до 7) размером 5 на 8 пикселей. Букву на кириллице, как и символ, можно задать массивом из восьми байт, характеризующих соответствующую строку. Можно добавить до 8 символов, поэтому используйте при выводе сочетание латинских и кириллических букв, как на примере. Загрузите скетч с надписью «Я ❤ сайт»

Скетч с русскими буквами на LCD I2C

#include // библиотека для управления устройствами по I2C #include // подключаем библиотеку для LCD 1602 LiquidCrystal_I2C lcd(0x27,20,2); // присваиваем имя lcd для дисплея 20х2 // создаем символ сердца и четырех букв на кириллице byte heart = { 0b00000, 0b01010, 0b11111, 0b11111, 0b11111, 0b01110, 0b00100, 0b00000 }; byte I = { 0b01111, 0b10001, 0b10001, 0b01111, 0b00101, 0b01001, 0b10001, 0b00000 }; byte B = { 0b11111, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110, 0b00000 }; byte N = { 0b10001, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b10001, 0b00000 }; byte F = { 0b01110, 0b10101, 0b10101, 0b10101, 0b01110, 0b00100, 0b00100, 0b00000 }; void setup () { lcd.init (); // инициализация LCD дисплея lcd.backlight (); // включение подсветки дисплея // присваиваем символам порядковый номер lcd.createChar (1, heart); lcd.createChar (2, I); lcd.createChar (3, B); lcd.createChar (4, N); lcd.createChar (5, F); lcd.setCursor (6,0); // устанавливаем курсор на 6 символ первой строки lcd.print (char (2)); lcd.print (" "); lcd.print (char (1)); lcd.setCursor (0,1); // устанавливаем курсор на начало второй строки lcd.print ("P"); lcd.print ("O"); lcd.print (char (3)); lcd.print ("O"); lcd.print ("T"); lcd.print ("E"); lcd.print ("X"); lcd.print ("H"); lcd.print (char (4)); lcd.print ("K"); lcd.print ("A"); lcd.print ("1"); lcd.print ("8"); lcd.print ("."); lcd.print ("P"); lcd.print (char (5)); } void loop () { }

Пояснения к коду:

  1. Массивы строк в функции byte simvol = { }; можно прописывать в строку;
  2. Слово сайт использует набор русских и латинских букв.
  3. Процедура void loop() в скетче не используется, но все равно присутствует.

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

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

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

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

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

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

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

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

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

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

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

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

#include #include #include 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 #include #include int pinCS = 10; int numberOfHorizontalDisplays = 1; // количество матриц по-горизонтали int numberOfVerticalDisplays = 1; // количество матриц по-вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); const byte data = { 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<

Примечание. В библиотеке 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 #include #include 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.

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

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

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

#include #include #include 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 = { "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 = 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("сайт 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, HIGH, LOW,1); } letter--; x -= width; } matrix.write(); // Вывод сообщения на экран delay(wait); } }

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

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

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