При создании собственного устройства не редко возникает необходимость оперативного вывода разнообразной информации. Например, если вы создаёте контроллер умного дома, то разумно оснастить прибор устройством вывода, позволяющим быстро узнать текущее состояние систем. Лучшим решением является жидкокристаллический дисплей. Энергопотребление при отключённой подсветке минимально а работа с дисплеем предельно проста и не требует сильного вмешательства в код программы. Фактически, вывод информации на ЖК дисплей не многим отличается от вывода в серийный порт. В статье рассмотрено подключение знакогенерирующего дисплея на базе популярного чипа HD44780 к контроллеру Arduino.
Как работает жидкокристаллический текстовый дисплей
Для понимания некоторых нюансов полезно знать как работает знакогенерирующий дисплей. Особенностью работы дисплеев такого типа является наличие своего контроллера с собственной памятью. DDRAM — память дисплея. Для вывода символа на экран необходимо загрузить символ в ячейку памяти, а затем передать команду на отображение ячейки памяти. При передаче символы кодируются ASCII кодами. Например, при записи в память кода 0×31 на дисплей будет выведен символ «1». Соответствие кода символа его отображению на экране (т.е. «картинке» символа) хранится в памяти CGROM. CGROM не изменяемая память. Поэтому, дисплей может отображать только те символы, которые «зашиты» в контроллер. Именно поэтому не каждый дисплей способен отображать, например, русские символы. Есть ещё CGRAM память. Она изменяемая. Мы можем создавать собственные символы и отображать их на дисплее. Стоит учитывать, что можно создать не более восьми символов.
Вся эта «подкапотная» работа важна только для понимания некоторых нюансов. Для Arduino существует простая и понятная библиотека, которая выполняет за вас всю черновую работу, позволяя контролировать вывод на дисплей легко и просто.
Подключение жидкокристаллического дисплея к Arduino
Для подключения дисплея его, разумеется, нужно установить на макетную плату. Передача данных на дисплей может быть организована двумя способами: по 4 или по 8 бит за раз. Соответственно, потребуется либо 4, либо 8 выводов Arduino. На практике, выигрыша в скорости при использовании восьмибитного интерфейса не будет. Поэтому, нам потребуется только 4 цифровых вывода для передачи данных. Ещё 3 вывода потребуются для задания режима работы дисплея. Итого для подключения дисплея понадобится всего 7 цифровых выходов контроллера. Контакты на дисплее подписаны, что позволит не запутаться при подключении:
Выводы нумеруем слева направо:
- 1-(VSS) Земля дисплея. Подключается к рельсе земли.
- 2-(VDD) Питание дисплея. Подключается к рельсе питания.
- 3-(VO) Вход потенциометра (входит в комплект). С помощью потенциометра регулируется контрастность дисплея. К выводу дисплея подключается средний выход потенциометра.
- 4-(RS) Вход «командного» сигнала. Подключается к любому цифровому выводу Arduino. В примере подключён к выводу №12.
- 5-(RW) Устанавливает режим «чтения» или «записи». Мы собираемся записывать. Подключаем контакт к земле.
- 6-(E) Enable. Ещё один «командный» вывод. Когда на вывод подаётся единица, дисплей выполняет переданную ранее команду. Подключается к любому цифровому выводу. В примере подключен к выводу №11.
- 7-10 (D0-D3) оставляем не подключёнными. Это контакты передачи данных, который используются в восьмибитном интерфейсе. Нам не нужны.
- 11-14 (D4-D7) Контакты для передачи данных в четырёхбитном режиме. Подключаются опять таки к любым цифровым выводам. В примере подключены соответственно к 5,4,3 и 2 выводам (D4 к 5 выводу, D5 к 4 и т.д.).
- 15 (A) Анод светодиода подсветки. Токоограничительный резистор уже установлен в дисплее, поэтому анод подключается просто к рельсе питания. Поскольку в подсветке используется самый обычный светодиод, вы можете подключить его к любому выводу, поддерживающему ШИМ и управлять яркостью подсветки программно.
- 16 (K) Катод подсветки. Подключается к рельсе земли.
Визуальная схема подключения:
Программирование
Вместе с Arduino IDE поставляется прекрасная библиотека для жидкокристаллических дисплеев — LiquidCrystal. Библиотека содержит примеры, полностью раскрывающие возможности экрана. Для начала воспользуйтесь стандартным примером «HelloWorld» (Файл -> Примеры -> LiquidCrystal -> HelloWorld) или загрузите в плату следующий код:
/* *RS вывод дисплея к 12 выводу arduino *Enable вывод дисплея к 11 выводу arduino *D4 вывод дисплея к 5 выводу arduino *D5 вывод дисплея к 4 выводу arduino *D6 вывод дисплея к 3 выводу arduino *D7 вывод дисплея к 2 выводу arduino *R/W вывод дисплея к земле *Выход потенциометра к VO выводу дисплея */ // подключаем библиотеку: #include ; // Инициализируем дисплей // Перечисляем выводы arduino к которым подключены // RS, E, D4, D5, D6, D7 контакты дисплея LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { // Указываем количество столбцов и строк дисплея: lcd.begin(16, 2); // Выводим сообщение на дисплей. lcd.print("hello, world!"); } void loop() { // устанавливаем курсор в 0 (нулевой) столбец первой строки // фактически курсор установится во вторую (нижнюю) строку // нумерация строк и столбцов начинается с нуля lcd.setCursor(0, 1); // выводим на дисплей количество секунд, // прошедших с момента загрузки платы: lcd.print(millis()/1000); }
После загрузки этого кода в плату Arduino на экране отобразится надпись «hello, world!»(англ. «привет, Мир!») на первой строке и таймер, отсчитывающий секунды на второй строке.
Как обычно и бывает, код простой и понятный. Однако, мы всё же разберём его более подробно:
- LiquidCrystal lcd(12, 11, 5, 4, 3, 2) — эта строка создаёт объект дисплея, с которым мы будем работать в будущем. В скобках в качестве аргументов передаются номера пинов, к которым подключены контакты дисплея. Соответственно: RS, E, D4, D5, D6, D7. Как уже отмечалось выше, номера выводов при подключении можно выбирать совершенно произвольно.
- lcd.begin(16, 2) — здесь мы настроили размеры дисплея. В данном примере 16 столбцов и 2 строки. Для нашего дисплея 20Х4 эта строчка выглядела бы так: lcd.begin(20, 4).
- lcd.print(«hello, world!») — выводит текст на дисплей. После указания размера дисплея (lcd.begin) курсор устанавливается в левый верхний угол дисплея. Поэтому, этот текст будет выведен на первой (верхней) строке слева.
- lcd.setCursor(0, 1) — устанавливает курсор на указанную позицию. В данном случае указана крайняя левая позиция второй строки. В скобках задаётся номер столбца, затем номер строки. И строки и столбцы нумеруются с нулевой позиции. Таким образом: lcd.setCursor(0, 0) — установит курсор в левый верхний угол, lcd.setCursor(15, 0) — правый нижний.
- lcd.print(millis()/1000) — уже описано выше. Здесь вместо текста в качестве параметра передаётся формула для вычисления. Результат выводится на экран.
Теперь, когда мы разобрались с простейшим примером, можно перейти к примерам посложнее. Кстати, заказать такой дисплей можно по ссылке. Доступны несколько цветов текста и фоновой подстветки.
Обзор других примеров библиотеки LiquidCrystal
В стандартных примерах, поставляющихся вместе с библиотекой LiquidCrystal можно найти следующие скетчи:
- Autoscroll — демонстрирует возможность прокрутки текста в автоматическом режиме. Некое подобие бегущей строки. При выводе символа предыдущие символы сдвигаются. Таким образом, новый символ выводится на одном и том же месте.
- Blink — демонстрирует возможность включить отображение мигающего курсора в виде прямоугольника.
- Cursor — демонстрирует возможность включить отображение курсора в виде мигающей горизонтальной черты.
- CustomCharacter — показана возможность создания собственных символов для отображения их на дисплее. Кстати, в этом скетче ошибка. Подробности ниже.
- Display — показывает способ «выключать» дисплей. То есть показывать или скрывать выведенный текст.
http://youtu.be/7Ducq4omsPk
- Scroll — демонстрирует возможность прокрутки текста в ручном режиме.
- SerialDisplay — отображает на экране текст, напечатанный в окне монитора порта (т.е. текст, передающийся через серийный порт).
- setCursor — заполняет дисплей буквами, демонстрируя возможность установки курсора в любую позицию экрана.
- TextDirection — демонстрирует возможность изменять направление вывода текста (с права налево или слева направо).
Рассмотрим более подробно процедуры, возможности которых демонстрируют эти примеры:
lcd.autoscroll()
После вызова этой процедуры, текст на экране будет автоматически прокручиваться. Для остановки прокрутки, следует вызвать lcd.noAutoscroll().
lcd.blink()
После вызова процедуры курсор примет вид мигающего прямоугольника. Для отключения следует вызвать lcd.noBlink(). Курсор снова станет невидимым.
lcd.cursor()
После вызова процедуры курсор примет вид мигающей горизонтальной черты. Для отключения следует вызвать lcd.noСursor(). Курсор снова станет невидимым.
lcd.createChar()
Процедура загружает в изменяемую таблицу символов экрана (в память CGRAM) символ, описанный в виде байтового массива. В качестве аргумента передаётся номер символа и массив байт, описывающий символ. Остановимся на этом более подробно. Внести в память дисплея можно не более восьми символов. Для добавления своего символа нужно:
- Создать байтовый массив, описывающий символ.
- Записать символ в память дисплея, присвоив ему номер в таблице символов. Символы нумеруются в диапазоне от нуля до семи.
- Вывести символ на экран с помощью процедуры lcd.write() (не путать с lcd.print() ), в качесте аргумента которой передать номер символа.
Баг среды разработки и особенности библиотеки вылились в невозможность вывести на экран символ под номером 0 (ноль). Компилятор повстречав строку lcd.write(0) выдаст ошибку: «call of overloaded ‘write(int)’ is ambiguous«. Именно такая строка встречается в примере CustomCharacter библиотеки. При попытке скомпилировать стандартный пример, вы получите ошибку:
CustomCharacter.ino: In function ‘void setup()’: CustomCharacter:115: error: call of overloaded ‘write(int)’ is ambiguous /home/nazarovd/arduino-1.0.5/libraries/LiquidCrystal/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t) /home/nazarovd/arduino-1.0.5/hardware/arduino/cores/arduino/Print.h:49: note: size_t Print::write(const char*)
Для устранения ошибки достаточно изменить строку lcd.write(0) на lcd.write((byte)0).
Теперь небольшой пример по созданию своего символа. Давайте выведем на дисплей символ рубля.
// Подключаем библиотеку #include ; // Инициализируем дисплей LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Описываем свой символ. // Просто "рисуем" символ единицами // Единицы при выводе на экран окажутся закрашенными точками, нули - не закрашенными byte rubl[8] = { 0b00000, 0b01110, 0b01001, 0b01001, 0b01110, 0b01000, 0b11110, 0b01000, }; void setup() { // записываем свой символ в память экрана // аргументами передаём номер символа // и байтовый массив, описывающий наш символ lcd.createChar(0, rubl); // настраиваем дисплей lcd.begin(16, 2); } void loop() { // устанавливаем курсор в левый верхний угод экрана lcd.setCursor(0,0); // выводим символ с номером ноль на экран lcd.write((byte)0); // ничего не делаем 10 секунд delay(10000); }
lcd.noDisplay()
«Выключает» дисплей. На самом деле, просто скрывает выведенные на экран символы. Вызов процедуры lcd.display() «включает» дисплей. Все символы снова отображаются. Обратите внимание: не происходит очистки дисплея. Символы именно перестают отображаться.
lcd.scrollDisplayLeft(); lcd.scrollDisplayRight();
Позволяют прокручивать длинные строки текста в ручном (управляемом) режиме. lcd.scrollDisplayLeft() прокручивает строку на один символ влево, lcd.scrollDisplayRight() прокручивает строку на один символ вправо.
lcd.rightToLeft(); lcd.leftToRight();
Устанавливает направление отображения текста. lcd.rightToLeft() устанавливает режим отображения справа на лево, lcd.leftToRight() заставляет текст отображаться слева направо.
lcd.clear()
Очищает экран.
Заказать такой дисплей можно по ссылке. Доступны несколько цветов текста и фоновой подстветки.
А ещё я собираю большой список проверенных продавцов. Ознакомиться можно здесь.