Показаны сообщения с ярлыком LCD. Показать все сообщения
Показаны сообщения с ярлыком LCD. Показать все сообщения

01.03.2021

LiquidCrystalRus - небольшое обновление

Недавно в проект LiquidCrystalRus на GitHub пришло issue по поводу того, что функция print при попытке выводить некоторые неалфавитно-цифровые символы из знакогенератора дисплеев на основе HD44780U, несправедливо их калечит. И я решил скорректировать алгоритм трансляции - чтобы он применялся строго к символам русского алфавита. Чуть больше кода из-за проверок, но зато можно так:

lcd.print("Дисковод 5\xf0");

На экране мы увидим:  Дисковод 5¼

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

Надеюсь, кому-то пригодится )

30.03.2015

LiquidCrystalRus для 1.6.1

Недавно вышла очередная ArduinoIDE 1.6.1, одним из новшеств которой выступил новый gcc версии 3.4.5. И поскольку с каждой версией gcc синтаксис становится всё строже и строже - без неприятностей не обошлось.

В частности, перестала компилироваться библиотека поддержки вывода русского языка LiquidCrystalRus, из-за неверного (с точки зрения gcc) использования директивы PROGMEM, о чем ко мне посыпались сообщения от уважаемых пользователей (за что им хочу выразить особую благодарность).

Изменения там совсем крошечные, но если после установки новой ArduinoIDE ваш проект с LiquidCrystalRus в составе перестал компилироваться, не паникуйте, а скачайте и установите LiquidCrystalRus-1.6.0.zip.

Напоминаю, что проект также доступен на GitHub: https://github.com/mk90/LiquidCrystalRus.

UPDATE: подобно оригинальному LiquidCrystal, LiquidCrystalRus не умеет работать с дисплеями, подключенными как-то иначе, чем к пинам Arduino (например, по I2C), но зато и не требует для работы дополнительных библиотек: и в результате поддержка русского языка обходится дополнительно в 500 байт flash и 7 байт SRAM. 

25.05.2010

LiquidCrystalRus для 0018

В развитие темы с LCD...

Выражаю сердечную благодарность пользователю a-monstr за внимание к моему решению по русификации, и специально для него и других желающих заставить дисплеи разговаривать по-русски - новая версия LiquidCrystalRus для ArduinoIDE 0018, сюда же вошли изменения для WH1601 из предыдущего поста.  Но в отличие от предыдущего варианта, этот не заменяет, а сосуществует с оригинальным LiquidCrystal. Для установки создайте каталог libraries в своем каталоге со скетчами и распакуйте туда содержимое архива.

Кстати - может быть сделать также и украинизированную версию?

23.05.2010

Однострочный LCD в двухстрочном режиме

С помощью библиотеки LiquidCrystal, входящей в стандартный комплект ArduinoIDE 0018, можно выводить алфавитно-цифровую информацию на LCD-дисплеи, совместимые с контроллером HD44780U. В Россию, например, импортируется большое количество дисплеев WinStar - они доступны по цене и неприхотливы в использовании.

Однако, существует пара досадных проблем, среди которых отсутствие поддержки русских букв (вроде как решена) и плохая работа с однострочными дисплеями - именно про нее пойдет повествование ;)

Дело в том, что у HD44780U максимальный размер алфавитно-цифрового дисплея составляет 80 знакомест. И хотя производители изготавливают дисплеи на любой вкус (2 строки по 20 символов, 1 строка по 16, 2 по 8 и т.д.), контроллер всегда оперирует памятью DDRAM размером в 80 байт. А вот по поводу  того, сколько на самом деле физический дисплей имеет строк и колонок, должен заботиться программист: например, записывать символы только в те ячейки памяти, за которыми закреплены физические знакоместа в ЖКИ.

Всё это было мне невдомек, пока однажды я не познакомился с дисплеем WH1601A-NGG-CT, 16 знакомест в один ряд:



У него есть небольшая особенность - логически он представляет собой двухстрочный дисплей по восемь символов в строке. На это красноречиво указывает документация, просто надо внимательно читать перед покупкой:



Таким образом, интуитивно правильно написанный скетч (вариация на тему примера "HelloWorld" к библиотеке LiquidCrystal):

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 1);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
}


Дает вот такой огорчающий результат:



Как я уже упоминал, дисплей логически работает в двухстрочном режиме, поэтому для отображения второй половины надо обязательно вызывать конструктор как lcd.begin(16, 2), в противном случае мы вообще никогда ничего во второй половине не увидим. Зато можно разбивать все строки попалам и перед отображением второй половины ставить lcd.setCursor(0, 1), хотя, на мой взгляд - это насилие над личностью программиста. Про что-то подобное возмущался пользователь abend в форуме arduino, его направили читать документацию - и, видимо, он до сих пор ее читает.

Так как же быть? Если бы это был логически однострочный дисплей, то вывод в ячейки памяти DDRAM с адресами 0x0 - 0x0f отобразился бы на экране. У нас же диапазон прерывается - сначала от 0x0 до 0x7, а далее - от 0x40 до 0x47. Всё, что потребуется - "подменить" обращения к адресам 0x08-0x0f на 0x40 - 0x47, но так, чтобы основная программа ни о чем не догадалась. Неприятный момент заключается в том, что адресный регистр работает в режиме автоинкремента и придется перед каждым выводом в память проверять, не попали ли мы в запрещенный диапазон 0x08-0x0f - иначе говоря, читать содержимое адресного регистра.

С точки зрения схемы, потребуется подключить пин RW к какому-то из свободных цифровых выходов Arduino, потому что именно он управляет направлением передачи данных по шине. Если раньше можно было спокойно вешать его на GND (всегда вывод в дисплей), теперь про такую экономию придется забыть.

Библиотечное API расширено функцией setDRAMModel(uint8_t), которой надо передать в качестве аргумента константу режима трансляции - в данном случае - LCD_DRAM_WH1601, после чего результат команды print будет уже гораздо более ожидаемым:

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 10, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 2);
  // set translation mode
  lcd.setDRAMModel(LCD_DRAM_WH1601);
  // Print a message to the LCD.
  lcd.print("hello, world! :)");
}

void loop() {
}




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

Файл-архив LiquidCrystal-WH1601-0018.zip надо распаковать в arduino-0018/libraries/, желательно предварительно сохранив старый каталог LiquidCrystal - на всякий случай.

24.05.2009

Arduino и ЖКИ-модуль H1313/120D

На прошлой неделе по случаю купил индикатор ЖКИ.

Купил просто так, из спортивного интереса - на вопрос о документации продавцы только печально развели руками: нету, дескать. Я решил, что с помощью Arduino смогу его "оседлать", пусть даже путем экспериментирования. Мысленно окрестив себя безумным тинкером, я безропотно выложил деньги за непонятный девайс.

Модуль выглядит так:



С обратной стороны висит кварц в цилиндрическом корпусе и керамический конденсатор. Единственное, что позволяло его идентифицировать - надпись H1313/120D на печатной плате:



Конечно же, Гугл про него ничего вразумительного не сказал. Зато удалось найти упоминание о таком дисплее на "Молотке", но увы - текст аукциона был перемещен в архив, прояснилось только, что это - модуль индикации телефонного аппарата.

К счастью, названия сигналов были подписаны на колодке сверху:



Слева направо: HK, DI, Vss, SK, T и еще один безымянный. Коллеги на работе указали на то, что Vss и безымянный - это питание, DI и SK - линия данных и синхронизация, по поводу остального предположений не было. Я остался один на один с непонятным дисплеем и могучим Интернетом. Ответ отыскался спустя часа полтора, в виде статьи "ЖКИ модули со встроенным контроллером HT1611/2" Леонида Ивановича Ридико.

Это - действительно дисплей телефонного аппарата. Основная особенность - наличие встроенного таймера, который отображается после того, как вы благополучно набрали номер телефона. Таймер живет своей обособленной жизнью и никак не доступен для считывания или установки по шине (разве что, можно его сбросить). Зато, по последовательной шине можно передавать набор из 16 разных символов - новый символ появляется справа, остальные сдвигаются влево, самый левый пропадает. Вот знакогенератор:



В статье рассматриваются контроллеры HT1611/HT1613, производимые фирмой Holtek Semiconductors Inc, вот страница с документацией у производителя. Мой же, похоже, оказался сильно урезанной версией, без часов, кнопок и прочих излишеств.

HK - это кнопка "поднятие трубки" (Hook). Если там 0 - это значит, что трубку сняли, дисплей начинает индикацию. Если там 1 - трубку повесили, и отображать ничего не надо (я немного упростил, но суть - правильная). Данные засылаются последовательным кодом (от старшего бита к младшему):



Данные записываются по спаду SK, при этом время установки ta> 1мкс, а время удержания данных tb> 2 мкс. Главная хитрость - после передачи оставить SK в состоянии логического 0, в противном случае, через 5 секунд бездействия наша информация пропадет и покажется злосчастный таймер, который начнет отсчитывать секунды разговора.

Дисплей - суперэкономичный, питается от напряжения около 1,6 В, поэтому для согласования с пятивольтовым МК Arduino пришлось сделать простой делитель на резисторах - на питание и на сигналы SK/DI. Получилась несложная схема:



Для работы требуется минимум две линии Arduino - я выбрал digital 5 и 6, к которым подключены SK и DI. Чтобы не плодить провода, я решил запитать его от digital 4 и digital 7, создав на них разность потенциалов. Для начала, я собрал схему на макетной плате:



Запустилось сразу же:



Маленький кусочек макетки, резисторы, колодки и вилки PBS/PLS - и получается компактный переходник:





Скетч, выводящий знакогенератор на дисплей:

 
#define DI 5
#define SK 6
#define VCC 7
#define GND 4
#define HK 3

void setup() {
pinMode(DI,OUTPUT);
pinMode(SK,OUTPUT);
pinMode(GND,OUTPUT);
pinMode(VCC,OUTPUT);
digitalWrite(GND,LOW);
digitalWrite(VCC,HIGH);
digitalWrite(SK,LOW);
pinMode(HK,OUTPUT);
digitalWrite(HK,LOW);
}

void writeDigit(byte d) {
for (int i=0;i<4;i++) {
digitalWrite(SK,HIGH);
digitalWrite(DI, d & (1 << (3-i)));
delayMicroseconds(1);
digitalWrite(SK,LOW);
delayMicroseconds(5);
}
}

void loop() {
digitalWrite(HK,LOW);
for (int i=0;i<16;i++) {
writeDigit(i);
delay(500);
}
digitalWrite(HK,HIGH);
delay(5000);
}


Итак, в результате экспериментов, мы получили 10-разрядный цифровой дисплей с последовательной записью для Arduino. Без статьи это сделать можно было бы, но ушло бы гораздо больше времени. Вывод напрашивается сам собой - для подобных экспериментов было бы неплохо иметь логический анализатор. Я его уже заказал, по традиции - выписал из-за границы. Как получу - обязательно напишу обзор ;)

Скачать архив со скетчем для Arduino и схемой.

02.05.2009

Arduino и русский LCD

Ранее я уже писал о том, как подключить популярные ЖКИ-дисплеи Winstar с контроллером Hitachi HD44780U к Arduino. Если честно, особенно и рассказывать-то было не о чем: все элементарно.

Если на дисплей требуется выводить кириллицу, надо решить две проблемы:

1. Arduino IDE по причине своей Java-природы транслирует русские буквы в UTF-8 в процессе компиляции sketch-а (на фазе генерации промежуточного С-исходника), в то время как дисплей понимает только однобайтовые символы и понятие не имеет, что такое схемы кодирования юникода;

2. Китайские товарищи добавили в знакогенератор дисплея только набор дополнительных кириллических символов, никак не позаботившись о соблюдении вообще какой-либо кодировки. То есть, символ "Б" есть, а вот букву "А" надо использовать из английского набора. Зато есть дроби, значок евро, а также украинское "Г". Наверное, они рассуждали так: "напихаем побольше разных символов, а эти славяне со своей письменностью сами разберутся".

Первую проблему, скорее всего, можно решить правкой настроек Arduino IDE, чтобы она транслировала UTF-8 в однобайтное представление. Но даже если это и получится сделать, остается неясность с тем, в какую именно кодировку транслировать этот самый UTF-8 (вторая проблема). То есть, на самом деле - это не две проблемы, а одна ;)

Конечно, дисплей поддерживает загрузку произвольного знакогенератора, НО: его надо сначала сформировать (скачать и подкорректировать или нарисовать свой собственный), и, если только память дисплея не энергонезависимая, загружать каждый раз при подаче питания на дисплей.

Самое простое решение - добавить в библиотеку декодирование UTF-8 и таблицу трансляции, что я и сделал, вот результат: LiquidCrystalRus.zip. Надо распаковать в С:\Program Files\arduino-0015\hardware\libraries\, при создании скетчей импортировать вместо стандартной LiquidCrystal. Внутри есть пара примеров: "Hello, world!" по-русски и вывод всего русского алфавита: сначала проверьте, что дисплей имеет идентичный знакогенератор, прежде чем начинать меня ругать ;)

Несколько слов о том, как все это работает. В памяти программ (а вовсе не в ОЗУ, которого катастрофически мало) создается таблица трансляции. В метод send добавлен код, который при попадании в него старшего и младшего символа кодированного UTF-8 производит необходимые вычисления и посылает нужный байт в дисплей.

Собственно, главная тонкость - это подключить процедуры работы с памятью программ #include avr/pgmspace.h и объявить массив трансляции таким образом:

PROGMEM prog_uchar utf_recode[] = {...};

затем к нему можно обращаться так:

pgm_read_byte_near(utf_recode+index);

Особого распухания кода не происходит, потому что подключается не библиотека, а макросы, которые разворачиваются в ассемблерные вставки.

Пожалуй, теперь уже недостает каких-то мелочей, типа задания количества строк дисплея, но об этом в следующий раз.

19.04.2009

LCD для Arduino

Ранее я уже расписывал, как подключить семисегментный дисплей к Arduino.

Семисегментный LED-дисплей прежде всего хорош тем, что имеет достаточно простую и надежную конструкцию, а при опытно подобранном токе через сегменты, легко читаем и с нескольких метров, и в кромешной темноте ;)

Дальше начинаются минусы: высокий ток потребления, необходимость схемы мультиплексирования разрядов, ограниченный набор синтезируемых символов. Все эти недостатки можно обойти в той или иной степени, с использованием экзотических (читаем: дорогих) компонентов.

Но гораздо проще использовать знакосинтезирующие ЖКИ-дисплеи, которые благодаря китайскому трудолюбию можно приобрести теперь на каждом углу.

Для экспериментов возьмем WinStar WH1602B-YYH-CTK:







Как видите, на самом деле - это модуль, состоящий из совместимого с Hitachi HD44780U контроллера, ЖКИ-матрицы и светодиодной подсветки.

Дисплей имеет две строки по 16 знакомест в каждой, параллельный интерфейс доступа, память, русский шрифт и даже возможность загрузить свой собственный знакогенератор.

Главное - не забыть, что на него подается три питания: одним питается контроллер со всей логикой (обязательно), вторым - LED-подсветка (опционально), а третьим - сам LCD-дисплей, и последнее напряжение надо уметь регулировать.

Для начала, вооружимся datasheet-ом и соберем типовую схему:



Мне для этого потребовался фрагмент вилки PLS на 16 контактов, чтобы дисплей легко стыковался с беспаечной макетной платой:



Таким образом, взять в руки паяльник придется - по крайней мере, один раз:



Дальше надо выбрать ширину параллельного интерфейса: 8 или 4 бит. Дело, конечно, не в скорости обмена, а в количестве цифровых входов Arduino, которые будут потеряны после подключения дисплея. Если выбрать 8-битный режим, то потребуется 11 выходов: к 8-битной шине данных добавляются линии RS, R/W и E(nable).

4-битная шина, соответственно, займет 7 выходов (если цифровых выходов все-таки не хватает, можно использовать и аналоговые, после переключения их в соответствующий режим), передача байта происходит в два цикла по линиям DB7-DB4, сначала старший ниббл, потом младший.

Хорошая новость состоит в том, что все эти тонкости нам не особенно важны: в основном, благодаря библиотеке LiquidCrystal (входит в Arduino IDE). Вот простой способ соединить Arduino и LCD-дисплей без паяльника:



В качестве тестового скетча можно использовать HelloWorld.pde из LiquidCrystal:

#include <LiquidCrystal.h>

// LiquidCrystal display with:
// rs on pin 12
// rw on pin 11
// enable on pin 10
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

void setup()
{
// Print a message to the LCD.
lcd.print("hello, world!");
}

void loop()
{
}

Самая главная строка - это конструктор объекта lcd. Параметрами надо указать, к каким цифровым выходам Adruino подключены соответствующие выводы дисплея. Основное тело loop() пустое, поскольку инициализация и вывод текста в дисплей целиком происходит в setup(). Для нас это означает, что sketch отработает один раз после нажатия на reset, сразу после включения питания или же сразу после загрузки sketch-а в Arduino.

Итак, все готово, можно включать. Если дисплей пуст, обратите внимание на VO (питание сегментов, пин 3). Я взял потенциометр 20К, включил его между GND и 5V, а среднюю точку подключил к VO. Немного повращав отверткой ползунок, я легко добился читаемости символов:



Светодиодная подсветка "сидит" на двух последних пинах дисплейной колодки: 15 и 16 (анод и катод). Подключать ее вовсе не обязательно, но, при желании можно также воспользоваться типовой схемой:



Я использовал R = 34 Ом, яркость была средняя...

Подводя итог: LCD к Arduino можно подключить довольно быстро: есть библиотека для работы, хоть и максимально упрощенная (читать из дисплея, а также загружать знакогенератор она не умеет). Если верить документации, ток потребления дисплея = 1,2 мА, а LED-подсветки @ 4,2 В = 130 мА.

Встречаются модификации с разным цветом и типом подсветки (или вообще без нее), другим количеством рядов (1,2,4), другим количеством знакомест в ряду (8,16). Если все равно не хватает, надо подумать о графическом дисплее, но про это - как-нибудь в другой раз ;)