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);

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

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

10 комментариев:

  1. Пятерка!
    Сам придумывал пару дней функцию преобразования юникод-код символа LCD...

    Только не нашел как вывести произвольный код символа, вроде значка градусов Цельсия. Поэтому дописал свою функцию:

    LiquidCrystalRus.h:
    void symbol(uint8_t value);

    LiquidCrystalRus.cpp:
    void LiquidCrystalRus::symbol(uint8_t value) {
    uint8_t out_char=value;
    send(out_char, HIGH);
    }
    Пример:
    lcd.symbol(0xDF); //C degree sign

    Может кому и пригодится...

    ОтветитьУдалить
  2. Отличная работа!
    Очень "недостает каких-то мелочей, типа задания количества строк дисплея", у меня дисплей 16х2, как выводить текст на вторую строчку?

    ОтветитьУдалить
  3. Спасибо за библиотеку и пояснения я давно искал возможность писать по русски на LCD.

    ОтветитьУдалить
  4. Отличный код! Заработало с полпинка!
    Не удержался, вставил Вашу функцию в текущую версию arduino-0018 (там много новых вкусностей), выложил сюда: http://stream.ifolder.ru/17694767

    Для тех кто будет пользоваться - просто заменить папку ..\arduino-0018\libraries\LiquidCrystal на такую же из архива и можно
    использовать русские буквы в функциях LCD, типа:

    lcd.print ("Великий и могучий!");

    Честно говоря, предложил бы выложить русскую версию библиотеки куда-нибудь на freeduino.ru, если Вы не против - очень нужная вещь.

    ОтветитьУдалить
  5. Ух! Первый раз мне кто-то решил помочь ;) Постараюсь выложить прямо здесь ;) Спасибо!

    ОтветитьУдалить
  6. Да там моей помощи шиш да маленько... я просто тоже несколько дней назад приобрел freeduino (опыт построения электронных схем - нулевой), сижу вот, разбираюсь, обложенный умными книжками).

    ОтветитьУдалить
  7. Спасибо за библиотеку, но в ней нет функции "lcd.createChar".

    ОтветитьУдалить
  8. Кирилл, на здоровье! ;) А по поводу createChar - поробуйте более поздний вариант библиотеки, здесь.

    ОтветитьУдалить