Русификация библиотеки Adafruit-GFX и вывод русских букв на дисплей в кодировке UTF-8 из Arduino IDE

arduinec
Offline
Зарегистрирован: 01.09.2015

Русификация библиотеки Adafruit-GFX и вывод русских букв на дисплей в кодировке UTF-8 из Arduino IDE

При этом русские буквы вводятся стандартным способом через русскую клавиатуру и отображаются в Arduino IDE как русские символы.

Мне понравились библиотеки Adafruit-GFX и Adafruit-SSD1306 (https://github.com/adafruit) для OLED Display 0.96 128x64 (http://arduino-project.net/oled-l2c-arduino-uno/).
Но (как и следовало ожидать) в них не оказалось русского шрифта. Добавить его оказалось несложно: нужно лишь заменить в файле glcdfont.c из Adafruit-GFX некоторые символы на русские буквы (в нужной кодировке).
Но шрифт рассчитан на однобайтовую кодировку букв, а Arduino IDE использует (для русских букв) двухбайтовую кодировку UTF-8.
Однако, при внимательном рассмотрении (и чтении Википедии) оказалось, что в русской кодировке UTF-8 прослеживается определенная последовательность. И она позволяет несложным путем перекодировать из UTF-8 в однобайтовую русскую кодировку Windows-1251, которая и была выбрана для замены букв.

Функция utf8rus() получает исходную строку, символы с кодами 0x00-0xBF пропускает без изменения в выходную строку, а в оставшихся кодах отбирает русские буквы и перекодирует их.

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

Применять ее можно внутри команд печати строк:
display.println(utf8rus("Тест"));

Саму функцию можно добавить в скетч, либо в виде отдельного файла положить в каталог скетча (как и сделано в примере).

В архиве utf8rus.zip прилагаются:
- файл glcdfont.c с русскими буквами для замены в Adafruit-GFX;
- пример OledRusTest для демонстрации русских (и других) символов и работы функции utf8rus();
- пример OledSymbolTest для демонстрации использования динамических символов.
Обращаю внимание в примерах на то, что мой дисплей подключается через SPI.

https://yadi.sk/d/FWO6Y1NwiqLVu

 

arduinec
Offline
Зарегистрирован: 01.09.2015

 В примере OledRusTest первые два экрана отображают все символы, которые заложены в glcdfont.c
На первом экране стандартная ASCII-кодировка. Не отображаются символы 0x0A (воспринимается как перевод строки) и 0x0D (игнорируется), поэтому вместо них выводятся пробелы.

На втором экране русские буквы, другие символы из кодировки Windows-1251 и дополнительные символы для дисплея.
Так как в glcdfont.c нашлись свободные места, добавил туда цифры для указания степени числа и некоторые символы для динамических эффектов.

Третий и четвертый экраны отображаются с использованием utf8rus()
 

arduinec
Offline
Зарегистрирован: 01.09.2015

При выборе динамических символов для примера OledSymbolTest руководствовался картинкой экрана MP3-плеера.

Получилось 7 динамических объектов и несколько статичных картинок.

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

 

 

arduinec
Offline
Зарегистрирован: 01.09.2015

Ещё в примере для библиотеки Adafruit-SSD1306 заменил звезду на снежинку:

static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000001, B00000000,
  B00000101, B01000000,
  B00000011, B10000000,
  B00100001, B00001000,
  B11000001, B00000110,
  B00110001, B00011000,
  B01001101, B01100100,
  B00000011, B10000000,
  B00000011, B10000000,
  B01001101, B01100100,
  B00110001, B00011000,
  B11000001, B00000110,
  B00100001, B00001000,
  B00000011, B10000000,
  B00000101, B01000000,
  B00000001, B00000000 };

Падающие снежинки выглядят намного лучше, чем падающие звезды.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Skayl
Offline
Зарегистрирован: 26.01.2014

А можно как то переделать шрифт для библиотек Adafruit_ST7735 и Adafruit-GFX. Хотелось писать на русском в проекте. Дисплей 1.8 TFT. Подключение к Nano Pro Mini по SPI.

Спасибо!

arduinec
Offline
Зарегистрирован: 01.09.2015

Skayl пишет:

А можно как то переделать шрифт для библиотек Adafruit_ST7735 и Adafruit-GFX. Хотелось писать на русском в проекте. Дисплей 1.8 TFT. Подключение к Nano Pro Mini по SPI.

Спасибо!

Библиотека Adafruit_ST7735 для вывода шрифта использует библиотеку Adafruit-GFX, а в ней для вывода русских букв нужно заменить файл glcdfont.c, который (с примерами) прилагается выше.

Skayl
Offline
Зарегистрирован: 26.01.2014

Пробовал, но как только в программе вводишь русские символы, на экране они занимают 2 знакоместа или 2 байта, не знаю как правильно объяснить...

Во второй строчке экрана, набраны буквы "АБВГД". Вот что он отображает, перед каждой буквой какой то значок. Букву "А" перерисовал в редакторе, отображается правильно. Остальные не трогал.

arduinec
Offline
Зарегистрирован: 01.09.2015

Для того, чтобы русские буквы нормально выводились, нужно использовать функцию utf8rus(). Она есть в архиве и в примере показано как она работает.

Судя по фотографии, файл glcdfont.c не заменён, то есть русских букв в Adafruit-GFX нет.

Skayl
Offline
Зарегистрирован: 26.01.2014

Я вставлял ваш файл glcdfont.c, но вот воспользоваться функцией utf8rus() не получается, при компиляции скетча выдается ошибка на эту строчку. Возможно я что то не так делаю...

tft.println(utf8rus("АБВГД")); пытался вот так ее использовать

/***************************************************
  This is a test sketch for 1.8" SPI display.

Wiring:
TFT display -> Arduino Nano
VCC -> 5V
GND -> GND
CS -> D10
RESET -> D12
A0 -> D8
SDA -> D11
SCK -> D13
LED -> D9

  Based on Limor Fried/Ladyada for Adafruit Industries.
 ****************************************************/

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>

// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS     10
#define TFT_RST    12  // you can also connect this to the Arduino reset
// in which case, set this #define pin to 0!
#define TFT_DC     8

const int ledPin =  9;
int backlit = 100;     //backlit

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

void setup(void) {
  pinMode(ledPin, OUTPUT);
  analogWrite(ledPin, backlit);
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
}

void loop() {
  tft.setRotation(3);
  tft.setTextWrap(false);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST7735_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_YELLOW);
  tft.setTextSize(2);
  tft.println("АБВГД");
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(15000);
}

 

arduinec
Offline
Зарегистрирован: 01.09.2015

Skayl пишет:

Я вставлял ваш файл glcdfont.c, но вот воспользоваться функцией utf8rus() не получается, при компиляции скетча выдается ошибка на эту строчку. Возможно я что то не так делаю...

Какую ошибку выдаёт компилятор?

Если на отсутствие функции, то скорее всего функция не добавлена к скетчу. Как добавить функцию описано в первом посте данной темы.

arduinec пишет:

Саму функцию можно добавить в скетч, либо в виде отдельного файла положить в каталог скетча (как и сделано в примере).

 

Sur
Offline
Зарегистрирован: 02.09.2015

preproc.substitute_unicode=false в преференсах IDE, добавить win1251 шрифты в glcdfont.c и везде по русски, проверял на 5110 экране.

Skayl
Offline
Зарегистрирован: 26.01.2014

Ну что ж... Спасибо, разобрался через несколько часов проб и ошибок. Все получилось, только пришлось немного переписать код. Отличия минимальны, поменял пару адресов:

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xBF){
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB7; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

Ну и соответственно сделал ее библиотекой. Русифицированный файл glcdfont.c оставил от arduinec 

arduinec
Offline
Зарегистрирован: 01.09.2015

Skayl пишет:

Ну что ж... Спасибо, разобрался через несколько часов проб и ошибок. Все получилось, только пришлось немного переписать код. Отличия минимальны, поменял пару адресов:

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xBF){
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB7; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

Ну и соответственно сделал ее библиотекой. Русифицированный файл glcdfont.c оставил от arduinec 

Отличия, вероятнее всего, связаны с тем, что в старой библиотеке Adafruit-GFX в шрифте файла glcdfont.c было 255 символов - отсутствовал символ B0 (=176). В новой же библиотеке и моём файле glcdfont.c там 256 символов.

 

Skayl
Offline
Зарегистрирован: 26.01.2014

Arduinec, я вот только так и не понял, куда в знакогенераторе спряталась маленькая "я". Получилось как в том анекдоте: "Ты суслика видишь?...")))

arduinec
Offline
Зарегистрирован: 01.09.2015

Небольшие изменения для новой версии библиотеки Adafruit-GFX

В старой версии библиотеки Adafruit-GFX в файле со шрифтами glcdfont.c было 255 символов - отсутствовал символ 0xB0 (=176). В новой версии библиотеки (https://github.com/adafruit/Adafruit-GFX-Library) данный символ добавили, но для совместимости со старыми версиями в код добавили пропуск данного символа по умолчанию. При этом была добавлена и функция cp437(), которая при аргументе true позволяет выводить указанный символ.
В моём файле glcdfont.c с русскими шрифтами изначально были все 256 символов, и в старой библиотеке всё отображалось.

Для того, чтобы в новой библиотеке символ 0xB0 (=176) отображался (в кодировке Windows-1251 ему соответствует символ градуса) нужно в начале скетча (после инициализации дисплея) применить функцию cp437() с аргументом true:
display.cp437(true);

Функция utf8rus() для перекодирования русского шрифта остаётся без изменения.
Применять функцию можно внутри команд печати строк:
display.println(utf8rus("Тест"));

Инструкция по русификации Adafruit-GFX остаётся прежней:
- скачиваем архив utf8rus2.zip по приведённой ниже ссылке;
- заменяем файл glcdfont.c в Adafruit-GFX;
- функцию utf8rus() добавляем в скетч, или в виде отдельного файла utf8rus.ino копируем в каталог скетча (как и сделано в примере);
- смотрим примеры OledRusTest и OledSymbolTest (фотографии к ним остались прежними).

https://yadi.sk/d/kdjXv7-ziwFL5
 

P.S. Для старой версии библиотеки Adafruit-GFX нормально работает вариант из первого поста данной темы.

arduinec
Offline
Зарегистрирован: 01.09.2015

Skayl пишет:

Arduinec, я вот только так и не понял, куда в знакогенераторе спряталась маленькая "я". Получилось как в том анекдоте: "Ты суслика видишь?...")))

Надеюсь вышеприведенные изменения решат все проблемы с отображением русских букв и других символов.

Маленькая "я" в кодировке Windows-1251 (и у меня в файле) имеет код 0xFF (=255).

MacSim
Offline
Зарегистрирован: 28.11.2012

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

http://arduino.ru/forum/obshchii/adafruit-biblioteka-dlya-raboty-s-oled-...

Volfram
Offline
Зарегистрирован: 20.10.2015

А у меня та же проблема на таком же 1.8 дисплее маленькая "з" нету

Volfram
Offline
Зарегистрирован: 20.10.2015

Вернее не нету, а вместо нее маленькая "х"

arduinec
Offline
Зарегистрирован: 01.09.2015

Volfram пишет:

А у меня та же проблема на таком же 1.8 дисплее маленькая "з" нету
Вернее не нету, а вместо нее маленькая "х"

Выполнено всё, что в пункте #15 описано?

Volfram
Offline
Зарегистрирован: 20.10.2015

Сделал все кроме 

display.cp437(true);

 выдавала ошибку изменил tft.cp437(true);

начали крокозяблы вместо слов писать, потом убрал эту строку и о чудо маленькая з появилась сама по себе о_О ниче не понятно) мож я сам в начале протупил

Volfram
Offline
Зарегистрирован: 20.10.2015

Skayl пишет:

Ну что ж... Спасибо, разобрался через несколько часов проб и ошибок. Все получилось, только пришлось немного переписать код. Отличия минимальны, поменял пару адресов:

String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xBF){
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB7; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

Ну и соответственно сделал ее библиотекой. Русифицированный файл glcdfont.c оставил от arduinec 

 

Спасибо без Вас пришлось бы писать латиницей!!!

А можно по подробней? Я как вставил это в начале скетча перед setup все отлично заработало. А вы пишите что вы сделали из этого библиотеку, т.е. убрали кучу строк кода в одну строку #include ???? 

Skayl
Offline
Зарегистрирован: 26.01.2014

Volfram, сохранил этот код в файл с именем utf8rus.h, и потом вставил как библиотеку #include <utf8rus.h>

Suho
Offline
Зарегистрирован: 16.11.2015

Здравствуйте, arduinec.

Спасибо за ваши труды.

Ваша последняя модификация utf8rus2 работает, но с символом "°" - "B0" у меня есть проблема.

Если его скопировать из Word, то на экране от всегда отображается как "В°".

как единственный символ "°" получилось вставить как "/xB0".

arduinec
Offline
Зарегистрирован: 01.09.2015

Suho пишет:

Ваша последняя модификация utf8rus2 работает, но с символом "°" - "B0" у меня есть проблема.

Если его скопировать из Word, то на экране от всегда отображается как "В°".

как единственный символ "°" получилось вставить как "/xB0".

В Word этот символ возможно имеет другой код (не проверял).

В Си для нестандартных символов можно использовать комбинацию "\xNN", где NN - шестнадцатиричный код символа. При этом их можно комбинировать с обычными символами.

Например: 19 градусов Цельсия = "19\xB0C".

 

Rolan_Che
Offline
Зарегистрирован: 19.11.2015

 arduinec, хочу поблагодарить за тему, все получилось с дисплеем 2.2 дюйма на LI9341, и даже символ градуса )) со второй попытки, да )

но, если можно, объясните на пальцах, или отправьте что почитать, о том как вы создавали русские символы, и дополнительные тоже, как помещали и вместо чего в файл glcdfont.c 

необходимы свои спец символы

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

arduinec
Offline
Зарегистрирован: 01.09.2015

Rolan_Che пишет:

но, если можно, объясните на пальцах, или отправьте что почитать, о том как вы создавали русские символы, и дополнительные тоже, как помещали и вместо чего в файл glcdfont.c 

необходимы свои спец символы

Прошу прощения за задержку с ответом (проходил обследование в больнице).

Есть какие-то программы, которые позволяют шрифты рисовать. Мне было проще написать программку на Си, которая позволила изменить шрифты.

Ниже скетч, который преобразует коды символа Й в визуальный формат и обратно:

void setup()
{
  byte i, j, cOut;
  unsigned char cBin[8] =
  { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };

  unsigned char cInp[5] =
  {
  0x7C, 0x21, 0x12, 0x09, 0x7C
  };
  char sInp[8][14] =
  {
  "    *   *    ",
  "      *      ",
  "  *       *  ",
  "  *     * *  ",
  "  *   *   *  ",
  "  * *     *  ",
  "  *       *  ",
  "             "
  };

  Serial.begin(9600);

  for(i=0; i<8; i++) {
    Serial.print("\"  ");
    for(j=0; j<5; j++) {
      if((cInp[j] & cBin[i]) > 0) Serial.print("* ");
      else Serial.print("  ");
    }
    Serial.println(" \",");
  }
  Serial.println();

  for(j=0; j<5; j++) {
    cOut = 0;
    for(i=0; i<8; i++) {
      if(sInp[i][j*2+2] == '*') cOut = cOut + cBin[i];
    }
    Serial.print("0x");
    if(cOut < 0x10) Serial.print("0");
    Serial.print(cOut, HEX);
    Serial.print(", ");
  }
  Serial.println();
}

void loop()
{
}

 

Skayl
Offline
Зарегистрирован: 26.01.2014

Для изменения шрифтов я использовал программу FontEditor. С ее помощью открываешь файл glcdfont.c и можно его подредактировать

Rolan_Che
Offline
Зарегистрирован: 19.11.2015

спасибо за ответ, по скетчу понятно, только не понятно куда именно в файл glcdfont.c полученый кусок в хексе поместить, подозреваю, что можно просто бегло просмотрев найти именно свой символ и его заменить ))

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

но все равно спасибо, возможно и передумаю и вернусь обратно к символам в самом фонте..  

и еще, выздоравливайте )

Skayl  ,я не смог найти редактор о котором вы говорили )

 

и еще по картинке можно догадаться что я тут пытаюсь построить ))

очередной огород на кухню ))

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

в общем пока бодаюсь с новым оборудованием, сейчас уперся в картридер sd карты, который на платке дисплея бонусом, не получается запустить пока, пытаюсь разобраться с интерфейсом SPI

Rolan_Che
Offline
Зарегистрирован: 19.11.2015

извиняюсь за кривую фотку, на форуме только зарегистрировался

arduinec
Offline
Зарегистрирован: 01.09.2015

Rolan_Che пишет:

только не понятно куда именно в файл glcdfont.c полученый кусок в хексе поместить, подозреваю, что можно просто бегло просмотрев найти именно свой символ и его заменить

Для примера используем ту же букву Й:

В кодировке Windows-1251 код символа Й = 0xC9, в десятичной системе = 201. В файле glcdfont.c (из архива utf8rus2.zip) массив символов начинается со строки 16. Сложив 16 и 201 получаем, что символ Й находится в строке 217.

Rolan_Che
Offline
Зарегистрирован: 19.11.2015

arduinec пишет:

.. Сложив 16 и 201 получаем, что символ Й находится в строке 217.

вот теперь понял ) 

sirota
Offline
Зарегистрирован: 18.08.2015

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

sirota
Offline
Зарегистрирован: 18.08.2015

Rolan_Che пишет:

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

И как же?

Rolan_Che
Offline
Зарегистрирован: 19.11.2015

sirota пишет:

И как же?

вот здесь человек показал как, правда для другого дисплея http://robotclass.ru/tutorials/graphics-lcd-nokia-5110/

в общем создаем в Paint графический файл нужного размера, обязательно сохраняем как 256-цветный рисунок с расширением bmp, затем нам нужно его конвертировать в hex формат, для этого можно использовать программы (их есть в сети, но я не надыбал простой и без установки), поэтому воспользовался ссылкой в статье, http://robotclass.ru/tutorials/graphics-lcd-nokia-5110/  работает. выбираем наш шестнадцатиричный формат (хотя можно и в двоичной системе), указываем путь к нашему файлу bmp, и получаем код картинки.

затем копируем в массив, прописываем свое имя, а потом и выводим на экран, не забывая указывать реальный размер картинки.

вот скетч для примера



#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

// For the Adafruit shield, these are the default.
// определяем пины для дисплея, у меня мега, не уно
#define TFT_DC 49
#define TFT_CS 53
#define TFT_RST 48

// Color definitions , определяем цвета, для удобства
#define BLACK 0x0000 
#define BLUE 0x001F 
#define RED 0xF800 
#define GREEN 0x07E0 
#define CYAN 0x07FF 
#define MAGENTA 0xF81F 
#define YELLOW 0xFFE0 
#define WHITE 0xFFFF 

// Use hardware SPI (on MEGA #49, #53, #48) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);


// создаем массив во флеш память, не изменяемый массив, в нем наша картинка в hex формате
// размер картинки 25х40 - соответсвует символу размера 5 нашего шрифта из Adafruit
const unsigned char PROGMEM ValveBmp[] = {
0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x0, 
0x7c, 0xf, 0x80, 0x0, 
0x7e, 0xdf, 0x80, 0x0, 
0x7f, 0xff, 0x80, 0x0, 
0x7f, 0xff, 0x80, 0x0, 
0x7e, 0xdf, 0x80, 0x0, 
0x7c, 0xcf, 0x80, 0x0, 
0x0, 0xc0, 0x0, 0x0, 
0x0, 0xc0, 0x0, 0x0, 
0x0, 0xc0, 0x0, 0x0, 
0x0, 0xc0, 0x0, 0x0, 
0x1, 0xe0, 0x0, 0x0, 
0x7, 0xf8, 0x0, 0x0, 
0xff, 0xff, 0xf0, 0x0, 
0xff, 0xff, 0xf8, 0x0, 
0xff, 0xff, 0xfc, 0x0, 
0xff, 0xff, 0xfc, 0x0, 
0xff, 0xff, 0xfc, 0x0, 
0xff, 0xff, 0xfc, 0x0, 
0x7, 0xf9, 0xfc, 0x0, 
0x1, 0xe0, 0xfc, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x30, 0x0, 
0x0, 0x0, 0x30, 0x0, 
0x0, 0x0, 0x78, 0x0, 
0x0, 0x0, 0x78, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x1, 0xfe, 0x0, 
0x0, 0x1, 0xfe, 0x0, 
0x0, 0x0, 0xfc, 0x0, 
0x0, 0x0, 0x78, 0x0
};

void setup() {
  
  tft.begin();
  tft.cp437(true);
  tft.setRotation(1);
  
  
}

void loop(){

  tft.fillScreen(ILI9341_BLACK); // заливаем экран черным
   
  tft.drawBitmap(150, 50, ValveBmp, 25, 40, CYAN);  // выводим нашу BMPкартинку
  // (на позицию 150, 50, имя_массива_Bmp, размер, цвет)

  delay(20000);
}

 

arduinec
Offline
Зарегистрирован: 01.09.2015

Ну уж если использовать картинки вместо букв, то у меня недавно появился дисплей TFT SPI (http://ru.aliexpress.com/item/Free-Shipping-1-8-Serial-SPI-TFT-LCD-Modul...). Там уже приделан слот для SD-карты, с которой выводятся на дисплей картинки в формате bmp. Таким образом можно создать любой набор картинок с буквами и символами и выводить их в нужном порядке в любое место дисплея.

sirota
Offline
Зарегистрирован: 18.08.2015

Rolan_Che пишет:

sirota пишет:

И как же?

вот здесь человек показал как, правда для другого дисплея http://robotclass.ru/tutorials/graphics-lcd-nokia-5110/

Спасибо большое! Так и буду делать. И символы все на месте и картинки вроде быстро рисует.

sirota
Offline
Зарегистрирован: 18.08.2015

arduinec пишет:

Ну уж если использовать картинки вместо букв, то у меня недавно появился дисплей TFT SPI (http://ru.aliexpress.com/item/Free-Shipping-1-8-Serial-SPI-TFT-LCD-Module-Display-PCB-Adapter-Power-IC-SD-Socket/1906735103.html). Там уже приделан слот для SD-карты, с которой выводятся на дисплей картинки в формате bmp. Таким образом можно создать любой набор картинок с буквами и символами и выводить их в нужном порядке в любое место дисплея.

У меня почти тоже самое, только не SPI как я понял. У меня там есть слот, так же можно читать и т.д. Но мне грубо говоря в проект добавить 6 картинок 32*32 максимум и все.

Rolan_Che
Offline
Зарегистрирован: 19.11.2015

arduinec пишет:

Таким образом можно создать любой набор картинок с буквами и символами и выводить их в нужном порядке в любое место дисплея.

)) ну перебор конечно, а вот типа иконок парочку можно, мне кажется.

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

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

arduinec
Offline
Зарегистрирован: 01.09.2015

В последнее время на форуме было несколько крупных публикаций по поводу экономного расходования оперативной памяти. Класс String был забракован из-за излишнего потребления ресурсов. Более экономным для работы со строками является использование массивов char. Настала пора модифицировать функцию для перекодирования русского шрифта utf8rus().

Для сохранения перекодированной строки требуется массив char. Чтобы его не определять при каждом вызове функции, создадим его один раз в глобальных переменных. Длину массива определим исходя из максимального размера строки, выводимой на дисплей.
В исходном варианте дисплей имеет ширину 128 пикселей. Ширина каждой буквы составляет 5 пикселей плюс интервал между буквами (6-й пиксель). В итоге, поделив 128 на 6, получаем, что максимальная длина выводимой строки составляет 21 символ плюс ещё один знак для нулевого символа конца строки.
Надо сказать, что библиотеки Adafruit позволяют разбивать длинные строки на несколько строк дисплея, но на маленьких экранчиках это редко нужно, поэтому данный вариант не рассматривается.

Чтобы не выскочить за пределы массива в функцию utf8rus() теперь встроена проверка на превышение максимального размера строки (более длинная строка просто отсекается).

#define maxString 21
char target[maxString + 1] = "";

char *utf8rus(char *source)
{
  int i,j,k;
  unsigned char n;
  char m[2] = { '0', '\0' };

  strcpy(target, ""); k = strlen(source); i = j = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }

    m[0] = n; strcat(target, m);
    j++; if (j >= maxString) break;
  }
  return target;
}

Вызов функции utf8rus() для перекодирования русского шрифта остаётся без изменения:
display.println(utf8rus("Тест"));

Инструкция по русификации Adafruit-GFX остаётся прежней:
- скачиваем архив utf8rus3.zip по приведённой ниже ссылке;
- заменяем файл glcdfont.c в Adafruit-GFX;
- функцию utf8rus() добавляем в скетч, или в виде отдельного файла utf8rus.ino копируем в каталог скетча;
- смотрим примеры OledRusTest и OledSymbolTest (фотографии к ним остались прежними).

https://yadi.sk/d/-eYXcQ1KnqEZt
 

sirota
Offline
Зарегистрирован: 18.08.2015

arduinec, Я бы добавил только пару моментов :

1. определение массива все таки внес в функцию.

2. Его размер сделал бы так: char target[sizeof(source)];

3. Функцию utf8rus внес бы в класс AdafruitGFX и вызов был бы так: tft.println(tft.utf8rus("ТЕКСТ"));

arduinec
Offline
Зарегистрирован: 01.09.2015

sirota пишет:
Я бы добавил только пару моментов

По пункту 3: Код открытый и каждый может делать с ним всё что угодно. Я же старался модифицировать библиотеку минимально, чтобы при изменении версии библиотеки не пришлось много менять.
Кстати, в последних версиях библиотеки Adafruit-GFX-Library появились разноразмерные шрифты (кириллицы там разумеется нет).

По пунктам 1 и 2: Если мы на вход utf8rus() подаем строку из 30 русских букв (60 символов), то следовательно target тоже определится размером в 60 символов. На выходе же мы получим строку из 21 символа.

Кроме того, я не знаю точно, что вернёт return target (если target будет определен в стеке), так как при завершении функции стек должен быть очищен. Я предполагаю, что в этом случае return target вернёт указатель на массив символов за пределами указателя стека и вызов любой другой функции может затереть эту строку.
Если же target определяется в куче, то кто (или что) его там чистит (удаляет). Мы же за экономию оперативной памяти боремся :)

sirota
Offline
Зарегистрирован: 18.08.2015

arduinec, я то давно переписал себе на array of char, но выложить как-то забыл. А потом сильно столкнулся с обработкой текстовых строк (2 устройства обмениваются информацией), и я долго старался строки массивами соимволов ставить, но потом понял что слишком много лишней потуги и перешел на string. И занимаемое место проекта с 89% упало до 70%, при том удалось еще скинуть 10% глобальных переменных. Пока в Protues проблем вроде нет. ПРобовал отладочно на пол часа запускать в железе, работает, вылетов нет. И вышло так что стринг позволил мне разместить функцию контроля входной строки, функцию ожидания ответа и повторной отправки, и еще много чего ) Еще и место осталось ) Так что конечно все зависит от обстоятельств. Скажем если до этого я только в одном месте использовал string (эта функция), то подгрузка этого класса и его методов конечно норм съедали памяти (всей) и игра не стоила свеч, но скажем если я уже где-то пользуюсь стринг и он легче и быстрее в работе чем char[], то разницы уже грубо говоря и нет )

И длину строки я считал отдельной функцией, она пробегала по массиву и если встречался символ из кирилицы уменьшара размерность target на 1.

revlerik
Offline
Зарегистрирован: 26.12.2015

Здравствуйте,вот хочу русифицыровать дисплей tft 2.4 на контроллере SPFD5408,но не совсем получается,буквы русские он пишет но вместо тех что я пишу в скетче он мне пишет совсем другое,все делал как описано в первом посте,в чем может быть косяк?

arduinec
Offline
Зарегистрирован: 01.09.2015

revlerik пишет:

Здравствуйте,вот хочу русифицыровать дисплей tft 2.4 на контроллере SPFD5408,но не совсем получается,буквы русские он пишет но вместо тех что я пишу в скетче он мне пишет совсем другое,все делал как описано в первом посте,в чем может быть косяк?

Возможно решение описано в посте 15.

arduinec
Offline
Зарегистрирован: 01.09.2015

Появился у меня недавно 2.8" TFT Touch Shield для Uno и Mega

Сначала пришлось поискать к нему библиотеки с примерами. Когда же всё нашлось и заработало, то легко решился вопрос с его русификацией, так как библиотеки основаны на Adafruit-GFX.

Вызов функции utf8rus() для перекодирования русского шрифта остаётся без изменения:
display.println(utf8rus("Тест"));

Инструкция по русификации Adafruit-GFX остаётся прежней:
- скачиваем архив TTFrus.zip по приведённой ниже ссылке;
- заменяем файл glcdfont.c в Adafruit-GFX;
- функцию utf8rus() добавляем в скетч, или в виде отдельного файла utf8rus.ino копируем в каталог скетча;
- далее смотрим пример TTFRusTest.

Обращаю внимание на то, что при использовании новых версий библиотеки Adafruit-GFX (описано в посте 15) в начале скетча нужно выполнять команду:
display.cp437(true);

TTFrus.zip
https://yadi.sk/d/Li8N0FDUoRH3z

На всякий случай выкладываю полный набор библиотек и примеров для указанного TFT Touch Shield:
https://yadi.sk/d/xNv6ovluoJVU9

revlerik
Offline
Зарегистрирован: 26.12.2015

Спасибо помогло,что то я пропустил этот пост.

revlerik
Offline
Зарегистрирован: 26.12.2015

Пробую руссифицировать дисплей 5110,при компиляции ошибка:

exit status 1
'class Adafruit_PCD8544' has no member named 'cp437'

Как победить?

arduinec
Offline
Зарегистрирован: 01.09.2015

revlerik пишет:

Пробую руссифицировать дисплей 5110,при компиляции ошибка:
exit status 1
'class Adafruit_PCD8544' has no member named 'cp437'
Как победить?

У меня ни на что не ругается. Немного переделал скетч (прилагается с библиотеками) из примера к библиотеке Adafruit-PCD8544: добавил функцию utf8rus, заменил падающие звёздочки на снежинки, вставил переход goto к отображению русских шрифтов, а также добавил display.cp437(true).

NokiaRus.zip
https://yadi.sk/d/yJOAk50yoTxF4
 

pilnikov
pilnikov аватар
Offline
Зарегистрирован: 28.08.2015

arduinec огромное спасибо Вам за проделанную работу. 

Я пытаюсь научить "великому и могучему" lcd панель 32х16. Получается с трудом.

В моем случае происходит сдвиг на один символ т.е. вместо строки "абвгд" выдает строку "бвгде".

Причем только на саму панель. В serial.print(utf8rus(str)); - при этом все корректно выводит.

P.S. все разобрался почитал пост №15 сделал matrix.cp437(true);