ВИДЕО редактируется.
Вы могли наблюдать, что в предыдущих уроках №7 и №8 уже использовался Русский шрифт. В этом уроке мы разберём некоторые проблемные моменты с которыми можно столкнуться при выводе Русских букв на OLED дисплей.
Нам понадобится:
- Arduino Uno х 1шт.
 - Trema OLED дисплей х 1шт.
 - Trema Shield или Trema Set Shield х 1шт.
 
Для реализации проекта нам необходимо установить библиотеки:
- Библиотека iarduino_OLED_txt (текстовая) - для вывода текста и цифр на OLED дисплеи.
 - Дополнительно можно установить библиотеку iarduino_OLED (графическая), но в данном уроке она использоваться не будет.
Графическая библиотека поддерживает все функции текстовой и имеет дополнительные функции для работы с изображениями и графикой, но при этом она занимает больше памяти, как оперативной, так и памяти программ. 
О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.
Схема подключения:
OLED дисплей подключается к аппаратной или программной шине I2C Arduino.
| Вывод | Назначение | OLED дисплей | Arduino UNO | 
|---|---|---|---|
| SCL | Линия тактирования шины I2C | SCL | A5 | 
| SDA | Линия данных шины I2C | SDA | A4 | 
| Vcc | Питание (3,3 или 5 В) | Vcc | 5V | 
| GND | Общий | GND | GND | 

Схема установки дисплея при его подключении через Trema Set Shield.
Код программы:
#include <Wire.h>                                      // Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_OLED_txt.
#include <iarduino_OLED_txt.h>                         // Подключаем библиотеку iarduino_OLED_txt.
iarduino_OLED_txt myOLED(0x78);                        // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x78 (если учитывать бит RW=0).
                                                       //
extern const uint8_t SmallFontRus[];                   // Подключаем шрифт SmallFontRus.
                                                       //
void setup(){                                          //
    myOLED.begin();                                    // Инициируем работу с дисплеем.
    myOLED.setFont(SmallFontRus);                      // Указываем шрифт который требуется использовать для вывода цифр и текста.
//  myOLED.setCoding(TXT_UTF8);                        // Указываем кодировку текста в скетче. Если на дисплее не отображается Русский алфавит, то ...
}                                                      // раскомментируйте функцию setCoding и замените параметр TXT_UTF8, на TXT_CP866 или TXT_WIN1251.
                                                       //
void loop(){                                           //
    myOLED.clrScr();                                   // Чистим экран.
    myOLED.print( "Большие буквы:"    ,      0, 0);    // Выводим текст начиная с 0 столбца 0 строки.
    myOLED.print( "ABCDEFGHIJKLM"     , OLED_C, 2);    // Выводим текст по центру 2 строки.
    myOLED.print( "NOPQRSTUVWXYZ"     , OLED_C, 3);    // Выводим текст по центру 3 строки.
    myOLED.print( "АБВГДЕЁЖЗИЙКЛМНОП" , OLED_C, 5);    // Выводим текст по центру 5 строки.
    myOLED.print( "РСТУФХЦЧШЩЪЫЬЭЮЯ"  , OLED_C, 6);    // Выводим текст по центру 6 строки.
    delay(3000);                                       // Ждём 3 секунды.
                                                       //
    myOLED.clrScr();                                   // Чистим экран.
    myOLED.print( "Маленькие буквы:"  ,      0, 0);    // Выводим текст начиная с 0 столбца 0 строки.
    myOLED.print( "abcdefghijklm"     , OLED_C, 2);    // Выводим текст по центру 2 строки.
    myOLED.print( "nopqrstuvwxyz"     , OLED_C, 3);    // Выводим текст по центру 3 строки.
    myOLED.print( "абвгдеёжзийклмноп" , OLED_C, 5);    // Выводим текст по центру 5 строки.
    myOLED.print( "рстуфхцчшщъыьэюя"  , OLED_C, 6);    // Выводим текст по центру 6 строки.
    delay(3000);                                       // Ждём 3 секунды.
                                                       //
    myOLED.clrScr();                                   // Чистим экран.
    myOLED.print( "Символы:"          ,      0, 0);    // Выводим текст начиная с 0 столбца 0 строки.
    myOLED.print( "{}[]()<>?!#$%&*"   , OLED_C, 3);    // Выводим текст по центру 3 строки.
    myOLED.print( "~`'\"^_-+=,.:;|/"  , OLED_C, 5);    // Выводим текст по центру 5 строки.
    delay(3000);                                       // Ждём 3 секунды.
                                                       //
    myOLED.clrScr();                                   // Чистим экран.
    myOLED.print( "Цифры:"            ,      0, 0);    // Выводим текст начиная с 0 столбца 0 строки.
    myOLED.print( "1234567890"        ,      6, 2);    // Выводим текст начиная с 6 столбца 2 строки.
    myOLED.print( 1234567890          ,      6, 3);    // Выводим число начиная с 6 столбца 3 строки.
    myOLED.print(-1234567890          ,      0, 4);    // Выводим число начиная с 0 столбца 4 строки.
    myOLED.print( 12345.7890          ,      6, 5);    // Выводим число начиная с 6 столбца 5 строки.
    delay(3000);                                       // Ждём 3 секунды.
}                                                      //
Алгоритм работы программы:
В коде setup() происходит инициализация дисплея (подготовка дисплея к работе) и подключение шрифта «SmallFontRus» (в библиотеке имеется несколько предустановленных шрифтов, которые подключаются перед использованием). Со списком шрифтов и описанием всех функций библиотек iarduino_OLED и iarduino_OLED_txt, можно ознакомиться в разделе Wiki - OLED экран 128×64 / 0,96”.
Код loop() разбит на 4 части. Каждая часть начинается с очистки экрана функцией clrScr(), после чего следуют несколько функций print() для вывода текста или чисел на экран дисплея. Все части выполняются друг за другом с 3 секундной задержкой выполняемой функциями delay().
В результате на дисплее поочерёдно будут появляться: большие буквы (включая Русские), маленькие буквы (включая Русские), символы и цифры.
Проблемы при выводе Русских букв:
Кодировка:
Первая и основная проблема это кодировка в которой скетч передаётся компилятору. Разные версии Arduino IDE хранят скетч в различных кодировках. Даже последняя версия Arduino IDE 1.8.5 (на момент написания данного урока) для ОС Windows, передаёт компилятору скетч в кодировке UTF-8 (если скетч был сохранён в файл *.ino) или в кодировке Windows-1251 (если скетч не был сохранён). Но ни скетч, ни библиотеки используемые в нём, не знают в какой кодировке они будут переданы компилятору. Вот и получается что один и тот же скетч, оперируя Русскими буквами, может работать по разному.
Примечание:
Что такое кодировка?
Компьютер, как и контроллер (в т.ч. Arduino) хранит, получает и передаёт данные в виде 1 и 0. Из набора 1 и 0 можно точно составить числа, но нельзя однозначно составить буквы. Кодировка это представление букв числами (по их порядковому номеру), которыми уже может оперировать компьютер или контроллер. Например, «А» - 1, «Б» - 2, «В» - 3 и т.д., тогда слово «ПРИВЕТ» можно передать, принять или сохранить, как набор чисел: 17,18,10,3,6,20. Так как буквы можно располагать по разному (сначала символы или числа, или буквы другого языка и т.д.), то и порядковые номера (числа) у букв будут разные, вот и получилось, что придумано множество кодировок. Исторически сложилось что Латинские буквы имеют одинаковые порядковые номера в большинстве кодировок: «A»...«Z» = 65...90, «a»...«z» = 97...122, а Кириллические буквы не только имеют различные номера, но могут быть разбросаны, или вообще отсутствуют в кодировках.
Решение:
В библиотеках iarduino_OLED и iarduino_OLED_txt, мы предусмотрели функцию setCoding(), которая может принимать в качестве единственного аргумента, одно из значений: TXT_UTF8, TXT_CP866, TXT_WIN1251, определяющее текущую кодировку скетча. Эта функция закомментирована в 3 строке кода setup программы данного урока. Если Русский текст на дисплее отображается некорректно, то раскомментируйте строку с функцией setCoding и замените параметр TXT_UTF8, на TXT_CP866 или TXT_WIN1251. В большинстве случаев это решит проблему кодировок.
myOLED.setCoding(TXT_WIN1251); // Указываем что текст скетча представлен в кодировке Windows-1251.
Если функция setCoding() Вам не помогла, тогда вызовите функцию setCoding() с параметром false, а Русские буквы указывайте их кодом, как это показано в следующем разделе данного урока: «Недостаточно памяти». При желании укажите в комментариях к уроку свою версию ОС, версию Arduino IDE и какую кодировку использует Ваша Arduino IDE (если Вы не знаете какую кодировку использует Arduino IDE, то напишите какие символы отображаются на дисплее вместо строчных и прописных Русских букв). Мы постараемся добавить Вашу кодировку в библиотеки.
Недостаточно оперативной памяти:
Вторая, но не менее важная проблема заключается в том, что строки занимают много оперативной памяти. Каждая буква строки занимает минимум 1 байт. Особенно актуальна эта проблема при создании различных пунктов меню.
Решение:
Наиболее эффективным решением данной проблемы является хранение строк не в области оперативной памяти, а в области памяти программ, так как объем памяти программ гораздо больше. Для этого указывайте строки в качестве аргумента функции F(). Строки указанные таким образом будут храниться в области памяти программ:
myOLED.print( F("Строка для дисплея") );  // Вывод строки на дисплей.
Serial.print( F("Строка для монитора") ); // Вывод строки в монитор последовательного порта.
Недостаточно оперативной памяти или памяти программ:
Если Вы работаете со строками на Русском языке в Arduino IDE, которая хранит скетч в кодировке UTF-8. Вы уже храните строки в области памяти программ (или оставили строки в области оперативной памяти). Вы все равно можете освободить до половины памяти занимаемой строками!
Дело в том, что в кодировке UTF-8 каждая Русская буква занимает целых 2 байта. Если указывать Русские символы кодом в той кодировке, где они занимают 1 байт, можно освободить половину памяти занимаемой строками, вне зависимости от того, в каком типе памяти они хранятся.
Символы в шрифтах для библиотек iarduino_OLED и iarduino_OLED_txt располагаются в соответствии с кодировкой CP866, значит хранить и выводить Ваши строки на экран дисплея можно в этой кодировке:
myOLED.setCoding(false);                               // Отменяем текущую кодировку, так как Русские буквы будем указывать кодом.
myOLED.print("\200\340\244\343\250\255\256 iArduino"); // Выводим текст "Ардуино iArduino". Вместо Русских букв используем их код в кодировке CP866.
Примечание:
Как указывать символ или букву по его коду в строках скетчей?
Для начала нужно узнать коды всех символов той кодировки, в которой Вы желаете их указывать, таблицы символов различных кодировок можно найти в интернете. Для кодировки CP866, Русские символы имеют следующие коды:
| А | 128 \200  | 
	И | 136 \210  | 
	Р | 144 \220  | 
	Ш | 152 \230  | 
	а | 160 \240  | 
	и | 168 \250  | 
	р | 224 \340  | 
	ш | 232 \350  | 
	Ё | 240 \360  | 
| Б | 129 \201  | 
	Й | 137 \211  | 
	С | 145 \221  | 
	Щ | 153 \231  | 
	б | 161 \241  | 
	й | 169 \251  | 
	с | 225 \341  | 
	щ | 233 \351  | 
	ё | 241 \361  | 
| В | 130 \202  | 
	К | 138 \212  | 
	Т | 146 \222  | 
	Ъ | 154 \232  | 
	в | 162 \242  | 
	к | 170 \252  | 
	т | 226 \342  | 
	ъ | 234 \352  | 
	242 \362  | 
|
| Г | 131 \203  | 
	Л | 139 \213  | 
	У | 147 \223  | 
	Ы | 155 \233  | 
	г | 163 \243  | 
	л | 171 \253  | 
	у | 227 \343  | 
	ы | 235 \353  | 
	243 \363  | 
|
| Д | 132 \204  | 
	П | 140 \214  | 
	Ф | 148 \224  | 
	Ь | 156 \234  | 
	д | 164 \244  | 
	м | 172 \254  | 
	ф | 228 \344  | 
	ь | 236 \354  | 
	244 \364  | 
|
| Е | 133 \205  | 
	Н | 141 \215  | 
	Х | 149 \225  | 
	Э | 157 \235  | 
	е | 165 \245  | 
	н | 173 \255  | 
	х | 229 \345  | 
	э | 237 \355  | 
	245 \365  | 
|
| Ж | 134 \206  | 
	О | 142 \216  | 
	Ц | 150 \226  | 
	Ю | 158 \236  | 
	ж | 166 \246  | 
	о | 174 \256  | 
	ц | 230 \346  | 
	ю | 238 \356  | 
	246 \366  | 
|
| З | 135 \207  | 
	П | 143 \217  | 
	Ч | 151 \227  | 
	Я | 159 \237  | 
	з | 167 \247  | 
	п | 175 \257  | 
	ч | 231 \347  | 
	я | 239 \357  | 
	247 \367  | 
Для вывода любого символа нужно указать его код в 8-ричной системе счисления, которому должен предшествовать обратный слеш «\». Данное правило действует для любых строк в Arduino IDE. В строке «Ардуино iArduino» из примера выше, первая буква - «A», имеет код 128. Если перевести 128 в 8-ричную систему счисления, получится (200)8. Значит букву «А» можно записать как «\200», букву «р» как «\340», букву «д» как «\244» и т.д.
Для перевода чисел из 10-тичной в 8-ричную систему предлагаем воспользоваться стандартным калькулятором Windows. Откройте калькулятор, выберите вид калькулятора - «Программист» и введите число, Вы увидите его представление в разных системах счисления: HEX(16), DEC(10), OCT(8) и BIN(2).
Но если Вы желаете научиться быстро переводить числа между системами счисления 2, 4, 8, 10, 16, без калькулятора, то посмотрите Урок 32 - перевод чисел между системами счисления.

Обсуждение