Про подключение экрана, например LCD 1620, к Ардуино в интернете полно всего написано и переписано. Все очень просто, особенно, если использовать подключение по протоколу I2C через плату расширения портов. Трудности возникают при желании вывести на дисплей кириллицу.
Для своего удобства, я написал на PHP скрипт замены строки русских символов на коды. Моим скриптом можно воспользоваться тут. За подробностями зачем и почему читайте статью дальше.
Описанное в статье справедливо только для дисплеев, в которых кириллица изначально зашита. Вариант псевдо русификации с «динамической прошивкой» восьми пользовательских символов в память тут не рассматриваю.
Если на дисплей, с аппаратной поддержкой кириллицы, отправить команду
lcd.print("Привет мир");
то будут выведены крякозябры.
Проблема в том, что коды кириллических символов экрана и компилятора не совпадают. Идеально совпадают только цифры, латиница и основные знаки препинания.
Можно отправить на дисплей последовательность символов непосредственно в восьмеричных кодах
lcd.print("\250p\270\263e\277 \274\270p"); // Привет мир
Тогда всё будет ок! Получим на экране строку на нормальном русском.
Существуют библиотеки, которые позволяют вводить строки на русском языке. В этих библиотеках заложена функция замены русских букв на их корректные коды. Но я вижу в таком подходе минус.
Эта автоматическая перекодировка осуществляется не компилятором на компьютере, а возлагается на Ардуино. То есть каждый раз, перед тем как ваша программа в Ардуино захочет вывести текст (и не важно русский или английский), будет вызываться функция перекодировки. Это дополнительная память и лишние вычисления.
По мне, так лучше использовать стандартные библиотеки (LiquidCrystal и LiquidCrystal_I2C), а русскую строку просто изначально задать в кодах.
На основе даташита экрана я составил таблицу соответствия русских букв и их кодов. Это самая распространенная кодировка.
Символ | Восьм. код | Шестнад. код | Символ | Восьм. код | Шестнад. код |
---|---|---|---|---|---|
Б | 240 | A0 | и | 270 | B8 |
Г | 241 | A1 | й | 271 | B9 |
Ё | 242 | A2 | к | 272 | BA |
Ж | 243 | A3 | л | 273 | BB |
З | 244 | A4 | м | 274 | BC |
И | 245 | A5 | н | 275 | BD |
Й | 246 | A6 | п | 276 | BE |
Л | 247 | A7 | т | 277 | BF |
П | 250 | A8 | ч | 300 | C0 |
У | 251 | A9 | ш | 301 | C1 |
Ф | 252 | AA | ъ | 302 | C2 |
Ч | 253 | AB | ы | 303 | C3 |
Ш | 254 | AC | ь | 304 | C4 |
Ъ | 255 | AD | э | 305 | C5 |
Ы | 256 | AE | ю | 306 | C6 |
Э | 257 | AF | я | 307 | C7 |
Ю | 260 | B0 | Д | 340 | E0 |
Я | 261 | B1 | Ц | 341 | E1 |
б | 262 | B2 | Щ | 342 | E2 |
в | 263 | B3 | д | 343 | E3 |
г | 264 | B4 | ф | 344 | E4 |
ё | 265 | B5 | ц | 345 | E5 |
ж | 266 | B6 | щ | 346 | E6 |
з | 267 | B7 |
Как видно, некоторые русские буквы в ней отсутствуют. То, что отсутствует, предлагается заменять одинаковыми по написанию английскими буквами.
Для перевода русскоязычной строки в эквивалентные коды предлагаю вот такую функцию на PHP.
mb_internal_encoding('UTF-8'); // Установка внутренней кодировки в UTF-8 header("Content-Type: text/html; charset=utf-8"); function ReplaceRuCodePage( $s ){ //Заменяем в строке русские символы на одинаковые по написанию английские $arr_ru = array('А','а','В','С','с','Е','е','Н','К','М','О','о','Р','р','Т','Х','х','у'); $arr_en = array('A','a','B','C','c','E','e','H','K','M','O','o','P','p','T','X','x','y'); $s = str_replace($arr_ru, $arr_en, $s); ///////////// //Заменяем прочие русские символы на их коды //Таблица букв и кодов $ru = 'Б240 Г241 Ё242 Ж243 З244 И245 Й246 Л247 '; //240-247 БГЁЖЗИЙЛ $ru = $ru . 'П250 У251 Ф252 Ч253 Ш254 Ъ255 Ы256 Э257 '; //250-257 ПУФЧШЪЫЭ $ru = $ru . 'Ю260 Я261 б262 в263 г264 ё265 ж266 з267 '; //260-267 ЮЯбвгёжз $ru = $ru . 'и270 й271 к272 л273 м274 н275 п276 т277 '; //270-277 ийклмнпт $ru = $ru . 'ч300 ш301 ъ302 ы303 ь304 э305 ю306 я307 '; //300-307 чшъыьэюя $ru = $ru . 'Д340 Ц341 Щ342 д343 ф344 ц345 щ346'; //340-346 ДЦЩдфцщ $arr = explode ( ' ', $ru ); //Разбиваем строку в массив по разделителю "пробел" for ($i=0; $i<47; $i++) { //Пробегаемся по массиву, обрабатывая каждый символ отдельно $chr = mb_substr($arr[$i],0,1); //Получаем символ, который будем заменять на код $code = mb_substr($arr[$i],1); //Получаем код символа $s = str_replace($chr, '\\' . $code, $s); //Производим замену символа на код } return $s; }
Изначально я преследовал цель не оптимизации кода, а его удобочитаемости и возможности легкой адаптации.
От PHP-кода возвращаемся к кодированию на Ардуино.
Хочу заметить, что коды символов можно задавать не только в восьмеричном формате, но и в шестнадцатеричном.
Символ «Б» можно выводить и так
lcd.print("\240");
и так
lcd.print("\xA0");
Но всё-таки я отказался от использования шестнадцатеричного кодирования. Дело в том, что после «\x» символы «0-9, a-f» будут восприняты компилятором как часть шестнадцатеричного числа, а это может привести к неверной интерпретации того, символ с каким кодом надо вывести.
Например, слово «Чебурашка».
«Ч» мы заменим на код «\xAB», а русскую «e» на английскую «e».
Первые две буквы будут закодированы так:
«\\xABe»
Компилятор прочитает такое написание как одно число, и, вместо двух символов «Че», попытается вывести один символ с восьмеричным кодом 5276. Из-за переполнения старший разряд будет отброшен (xABE -> xBE) и получится символ с восьмеричным кодом «276», т.е. выйдет буква «п».
Также некорректно отобразится сочетание «ка».
«ка» -> xBAA (5625)-> xAA (252) -> «Ф»
«Чебурашка», закодированный строкой
lcd.print("\xABe\xB2ypa\xC1\xBAa");
превратится в «пбурашФ»
Если писать в восьмеричных кодах, то такой неразберихи не происходит.
Вот такой «Чебурашка»
lcd.print("\253e\262ypa\301\272a");
выйдет полноценным.
При желании использовать шестнадцатеричное кодирование, придется также заменять все символы из диапазона «0-9, a-f» на коды, а это необоснованно увеличивает длину кодированной строки. Можно заменять не все символы «0-9, a-f», а только в неоднозначных случаях. Но смыл?
Есть еще один вариант кодовой таблицы с кириллицей, которая встречается зашитой в экраны (например производства МЭЛТ). Также составил краткою табличку букв и кодов.
Символ | Восьм. код | Шестнад. код | Символ | Восьм. код | Шестнад. код |
---|---|---|---|---|---|
А | 300 | C0 | а | 340 | E0 |
Б | 301 | C1 | б | 341 | E1 |
В | 302 | C2 | в | 342 | E2 |
Г | 303 | C3 | г | 343 | E3 |
Д | 304 | C4 | д | 344 | E4 |
Е | 305 | C5 | е | 345 | E5 |
Ж | 306 | C6 | ж | 346 | E6 |
З | 307 | C7 | з | 347 | E7 |
И | 310 | C8 | и | 350 | E8 |
Й | 311 | C9 | й | 351 | E9 |
К | 312 | CA | к | 352 | EA |
Л | 313 | CB | л | 353 | EB |
М | 314 | CC | м | 354 | EC |
Н | 315 | CD | н | 355 | ED |
О | 316 | CE | о | 356 | EE |
П | 317 | CF | п | 357 | EF |
Р | 320 | D0 | р | 360 | F0 |
С | 321 | D1 | с | 361 | F1 |
Т | 322 | D2 | т | 362 | F2 |
У | 323 | D3 | у | 363 | F3 |
Ф | 324 | D4 | ф | 364 | F4 |
Х | 325 | D5 | х | 365 | F5 |
Ц | 326 | D6 | ц | 366 | F6 |
Ч | 327 | D7 | ч | 367 | F7 |
Ш | 330 | D8 | ш | 370 | F8 |
Щ | 331 | D9 | щ | 371 | F9 |
Ъ | 332 | DA | ъ | 372 | FA |
Ы | 333 | DB | ы | 373 | FB |
Ь | 334 | DC | ь | 374 | FC |
Э | 335 | DD | э | 375 | FD |
Ю | 336 | DE | ю | 376 | FE |
Я | 337 | DF | я | 377 | FF |
Ё | 250 | A8 | ё | 270 | B8 |
В этой кодировке реализован полный русский алфавит, то есть не надо прибегать к заимствованию английских букв.
Функцию для перекодирования строки в коды я также написал на PHP. Код очень похож на предыдущий.
Моим скриптом для онлайн кодирования строк по первому и второму вариантам кодировок можно воспользоваться тут.
Скачать исходники скрипта тоже можно.
Пишите комментарии...
at 00:12
Все работает и сильно экономит время.
Спасибо за скрипт!!!)
at 18:11
Лучшее решение проблемы с русскими буквами!
at 10:25
При использовании библиотеки LiquidCrystal_I2C, не работает
at 01:55
Подскажите, как заставить работать с библиотекой LiquidCrystal_I2C ?
Спасибо
at 19:57
Добрый вечер, не могу разобраться, как подключить представленный Вами код. Какие библиотеки нужны?
at 05:44
LiquidCrystal_I2C, не работает
at 22:48
Шо вы меня запутали, мне так понравилось ваше решение, потому что та русифицированная библиотека не работает с ESP8266, а этот вариант прям крут, но сразу не пошло. А дело в том, что я использовал второй вариант скрипта, а он почему-то вообще другой, неправильный! Например, у буквы "П" там код 317, а не 250. Я что-то не так понял или у вас ошибка?
Но за вдохновление спасибо! Очень крутое решение.
at 23:02
А, вижу теперь, что таблицы разные. Я думал их отличие только в том, что там полный алфавит, а там с заменой. Теперь ещё труднее, но мы постараемся понять.
at 20:27
Огромное вам спасибо!
Всё работает прекрасно!
Единственное буква "д" почему-то если писать её в слове пропускается. Пришлось отдельно её писать.
Слово "вождь" записывается так:
lcd.print("\263o\266");lcd.print("\343");lcd.print("\304");
Почему так не знаю. Но работает.
at 12:44
Имею дисплеи фирмы PowerTip - 2402 и 1602. Вних есть встроенный русский шрифт. Спасибо автору за ваши таблицы, а то самому делать было лень, т.к. нужны не часто. И при использовании приходилось долго сидеть пыхтеть над восьмеричной перекодировкой по даташиту на эти дисплеи.
Хотел ответить тем, у кого проблемы при выводе при использовании LiquidCrystal: вы не правильно строите строку, вот пример слова "Температура" в коде LiquidCrystal
lcd.print("Te\274\276epa\277ypa");