View Sidebar
Яндекс.Метрика
 
Кириллица на экранах и Ардуино

Кириллица на экранах и Ардуино

24.02.2018 15:5910 комментариев

Про подключение экрана, например 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. Код очень похож на предыдущий.

Моим скриптом для онлайн кодирования строк по первому и второму вариантам кодировок можно воспользоваться тут.

Скачать исходники скрипта тоже можно.

Пишите комментарии...

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

  • Николай

    Все работает и сильно экономит время.
    Спасибо за скрипт!!!)

  • Владислав

    Лучшее решение проблемы с русскими буквами!

  • Алексей

    При использовании библиотеки LiquidCrystal_I2C, не работает

  • Данила

    Подскажите, как заставить работать с библиотекой LiquidCrystal_I2C ?
    Спасибо

  • Nastya

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

  • Виктор

    LiquidCrystal_I2C, не работает

  • Ярослав

    Шо вы меня запутали, мне так понравилось ваше решение, потому что та русифицированная библиотека не работает с ESP8266, а этот вариант прям крут, но сразу не пошло. А дело в том, что я использовал второй вариант скрипта, а он почему-то вообще другой, неправильный! Например, у буквы "П" там код 317, а не 250. Я что-то не так понял или у вас ошибка?
    Но за вдохновление спасибо! Очень крутое решение.

  • Ярослав

    А, вижу теперь, что таблицы разные. Я думал их отличие только в том, что там полный алфавит, а там с заменой. Теперь ещё труднее, но мы постараемся понять.

  • Павел

    Огромное вам спасибо!
    Всё работает прекрасно!

    Единственное буква "д" почему-то если писать её в слове пропускается. Пришлось отдельно её писать.

    Слово "вождь" записывается так:
    lcd.print("\263o\266");lcd.print("\343");lcd.print("\304");

    Почему так не знаю. Но работает.

  • Андрей

    Имею дисплеи фирмы PowerTip - 2402 и 1602. Вних есть встроенный русский шрифт. Спасибо автору за ваши таблицы, а то самому делать было лень, т.к. нужны не часто. И при использовании приходилось долго сидеть пыхтеть над восьмеричной перекодировкой по даташиту на эти дисплеи.
    Хотел ответить тем, у кого проблемы при выводе при использовании LiquidCrystal: вы не правильно строите строку, вот пример слова "Температура" в коде LiquidCrystal
    lcd.print("Te\274\276epa\277ypa");

Leave a reply to Виктор


css.php