LCD1602 RUS или НЕ RUS помогите определиться...

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

День добрый. Имеется дисплей 1602 вот такого вида:

Использую библиотеку LiquidCrystal_I2C при загрузке примера CustomChars

//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args)  write(args);
#else
#define printByte(args)  print(args,BYTE);
#endif

uint8_t bell[8]  = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
uint8_t note[8]  = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
uint8_t duck[8]  = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
uint8_t retarrow[8] = {	0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
  
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  
  lcd.createChar(0, bell);
  lcd.createChar(1, note);
  lcd.createChar(2, clock);
  lcd.createChar(3, heart);
  lcd.createChar(4, duck);
  lcd.createChar(5, check);
  lcd.createChar(6, cross);
  lcd.createChar(7, retarrow);
  lcd.home();
  
  lcd.print("Hello world...");
  lcd.setCursor(0, 1);
  lcd.print(" i ");
  lcd.printByte(3);
  lcd.print(" arduinos!");
  delay(5000);
  displayKeyCodes();
  
}

// display all keycodes
void displayKeyCodes(void) {
  uint8_t i = 0;
  while (1) {
    lcd.clear();
    lcd.print("Codes 0x"); lcd.print(i, HEX);
    lcd.print("-0x"); lcd.print(i+16, HEX);
    lcd.setCursor(0, 1);
    for (int j=0; j<16; j++) {
      lcd.printByte(i+j);
    }
    i+=16;
    
    delay(4000);
  }
}

void loop()
{

}

На экране выводит последовательно все символы зашитые в дисплей, если я это правильно понял... И среди прочего вот такие картинки:

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

sadman41
Offline
Зарегистрирован: 19.10.2016

http://robotosha.ru/electronics/lcd-hd44780.html  ->  Конвертер кириллицы

PRC
Offline
Зарегистрирован: 03.02.2019

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

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

PRC, ну вроде в природе существуют несколько вариантов данных экранок? В одних русский есть и работает без проблем, в других его нет совсем (по крайней мере на ю-тубе у людей по выше указанному скетчу он совсем не выводит ни одной русской буквы) и вот такой вариант как у меня - русские буквы вроде как есть, но без бубна не обойтись.... Или я не прав???

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

Блин ((((.... Лет 5-ть назад последний раз брал в руки сей модуль, в то время он был еще без I2C и вот точно помню, что мне кто то из добрых людей помог с библиотекой, которая отлично выводила русский текс без какого либо шаманства, без подмены русских букв английскими и прочего, но в этот промежуток времени вмешалась смена работы и все наработки остались на сторой работе, вот не забрал все с компа, не до того было... Плюс I2C внесло свои коррективы...

 

sadman41
Offline
Зарегистрирован: 19.10.2016

У меня натуральные Winstar и МЭЛТ имеются и в них точно такие же грабли с таблицами символов. С I2C, без I2C - вообще нет никакой разницы в связи код символа и его вида на экране. Напиши функцию табличной перекодировки и хоть с SD выводи буквы, хоть с ТВ-антенны.

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

sadman41 пишет:

 Напиши функцию табличной перекодировки и хоть с SD выводи буквы, хоть с ТВ-антенны.

Мне стыдно признаться, но не знаю как это сделать (((( Можно хотябы методику и кусочек скетча, чтобы я дальше по образу и подобию пытался добить проблемму???

sadman41
Offline
Зарегистрирован: 19.10.2016

Методика зависит от того, какая кодировка будет на входе в функцию - однобайтовая, двубайтовая, четырёхбайтовая.

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

Имеется текстовый файл на SD карте, строки длиной 2-3 слова, русскоязычные, хотелось бы читать построчно и выводить на экран строку с определенным номером... С реализацией в сериал порт проблем нет, а экран русские буковки увы не пишет (((

void loop() {
  while (Serial.available() == 0);                                // пока в порту ничего нет - ждем
    number = Serial.parseInt();                                   // появились данные - читаем
    Serial.println(number);
    if (number <= KolStr) {
      myFile = SD.open("test.txt");                               // открываем файл для считывания:
      int Str =0;                                                 // Обнуляем номер текущей строки
      while (myFile.available()) {                                // Пока не достигнут конец файла
        String buffer;                                            // Буфер для хранения считанной строки
        buffer = myFile.readStringUntil('\n');                    // считываем строку и пишем ее в буфер
        Str = Str + 1;                                            // увеличиваем номер текущей строки
        if (Str == number) {                                      // Если номер текущей строки совпадает с заданым
            Serial.println(buffer);                               // печатаем содержимое строки
            myFile.close();                                       // Закрываем файл
            return;                                               // прекращаем поиск
        }
      }
    }  
        Serial.print("Записей в файле - ");                       // Если введен не корректный номер строки
        Serial.println(KolStr);
        Serial.println("Введите корректное значение номера строки");           

}

Хотелось бы и на экран выводить buffer

sadman41
Offline
Зарегистрирован: 19.10.2016

Ещё раз: "какая кодировка будет на входе в функцию"? Arduino IDE рассматривает текст, как UTF-8. На SD-карте может быть и 866 и 1251 и KOI8-R. 

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

ААААА....  Семен Семеныч.... ))))

Файлик в UTF-8

sadman41
Offline
Зарегистрирован: 19.10.2016
GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

Всё утро бьюсь над попыткой понять смысл вашей отсылки... Дисплей то у меня совсем не такой как тот о чем идет в топике...

На сколько хватило моих мозгов - мне нужно забрать из вышеупомянутого топика функцию String utf8rus(String source)... Правильно или я совсем не туда???

Ну и если таки туда, то пока прикрутить его к своему дисплею не могу, все равно выводит иероглифы вместо русских букв (((

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно забрать, конечно.

И модифицировать так, чтобы она после перевода из юникода в однобайтовый код просто смотрела в таблицу соответствия (однобайтовый код -> дисплейный код символа) и подставляла результат в выходную строку. Это в том случае, если нельзя перевести однобайтный код в дисплейный простой математической функцией типа displayCode=rusCode-42;

PRC
Offline
Зарегистрирован: 03.02.2019

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

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

что то я все сильнее запутываюсь (((

При попытке сделать lcd.print(char(192)); на экране получаю кракозябру вместо "А", но вижу "А" если введу char(65) и последнее понятно это латиница... Если введу char(193), то вместо "Б" опять кракозябра и вот char(128) вижу "Б"...

PRC пишет:

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

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

PRC
Offline
Зарегистрирован: 03.02.2019

А открыть даташит на HD44780 и посмотреть таблицу символов русской раскладки что не позволяет? Тогда таких глупых вопросов возникать больше не будет.

sadman41
Offline
Зарегистрирован: 19.10.2016

По ходу дела в этом дисплее зашита какая-то специфическая таблица. В диапазоне 0x80..0x90 у винстара пустые клетки, а у МЭЛТ-а спецсимволы: http://www.melt.com.ru/docs/MT-16S2D.pdf (стр.#8)

Так что только вручную соответствие ставить. Сначала на бумажке разрисовать, потом перетаскивать в код. Или искать даташит на конкретную модель LCD.

Нашёл:

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

sadman41 пишет:

По ходу дела в этом дисплее зашита какая-то специфическая таблица. В диапазоне 0x80..0x90 у винстара пустые клетки, а у МЭЛТ-а спецсимволы: http://www.melt.com.ru/docs/MT-16S2D.pdf (стр.#8)

Так что только вручную соответствие ставить. Сначала на бумажке разрисовать, потом перетаскивать в код. Или искать даташит на конкретную модель LCD.

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

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

Спасибо!!!! Вроде моя табличка!!!!

Т.е. теперь если совсем глупо, то можно с помощью switch case сделать сопоставление на все символы и подменять считанный код элемента строки на соответствующий в таблице??? Ну это если совсем по дилетански????

sadman41
Offline
Зарегистрирован: 19.10.2016

На первое время пойдёт. Потом придумаете что-нить покомпактней.

PRC
Offline
Зарегистрирован: 03.02.2019

Лучше массив сделать. И быстрей и места мало. Тут наверное самый лучший вариант.

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

PRC пишет:

Лучше массив сделать. И быстрей и места мало. Тут наверное самый лучший вариант.

Массив размерностью по количеству русских букв и в каждой ячейке соответствующий код из правильной таблицы???

Я завис на получении кода символа строки...

String buffer;
  int i,k;
  char n;
   k = 17; i = 0;
  while (i < k) {
    n = buffer.charAt(i); i++;
Serial.println(n);}

получаю какуюто фигню в монитор

PRC
Offline
Зарегистрирован: 03.02.2019

Массив 256 байт, соответствия ASCII индикатору.

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно извернуться и только кириллицу хранить...

PRC
Offline
Зарегистрирован: 03.02.2019

Смысла крохобоничать из-за 128 байт нет))

sadman41
Offline
Зарегистрирован: 19.10.2016

Когда как... У человека там вон SDFat в планах.

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

SOS!!!

Почему я не получаю адекватно символ из строки??? Пост 21 - должен же получать... Если вывод как в посте Serial.println(n) - то получаю в монитор набор квадратиков; если Serial.println(n, HEX) -  то строки вида FFFFFFD0; если Serial.println(n, DEC) - то "-48", а хотелось бы, что то более похожее на код символа: D09A / 208 154 / 202 .... Указываю для первого символа найденой строки - "К"

sadman41
Offline
Зарегистрирован: 19.10.2016

У принта бывают закидоны. Не знаю, с чем связано, может компилятор неправильную реализацию функции подбирает (хотя с какого бы ему это делать...), но иногда приходится делать Serial.print((char) n) или Serial.print((byte) n);

По фрагменту кода непонятно что держите в buffer - UTF-8, ASCII...

kalapanga
Offline
Зарегистрирован: 23.10.2016

GVS, для работы с этими дисплеями есть библиотеки LiquidCrystal (в поставке IDE) и LiquidCrystal_I2C. Для первой есть версия с поддержкой кириллицы и UTF8 - LiquidCrystalRus (гуглится). Там есть вся эта перекодировка (таблицы конечно сверить надо). Посмотрите как это делается, а дальше хоть сделайте свою LiquidCrystalRus_I2C, хоть просто в скетч свой нужные функции вставьте.
 

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

Буфер это строка все того же файла с SD карты вроде как в формате UTF-8 в чем я уже совсем не уверен... Извратился костылем обозвав считываемый символ как uint8_t n; теперь получаю последовательно два байта от кода в формете UTF-8 DEC вида 208 192, отбрасываю первый байт, а по второму делаю выбор нужного символа из таблицы к дисплею и пытаюсь посимвольно выводить на дисплей, потому как собрать в строку у меня опять не получилось, дисплей выводит ересь (((

Собственно костыль:

uint8_t rusDispl(String source)
{
  int i=0;
  uint8_t n=0;
  #if defined(ARDUINO) && ARDUINO >= 100
  #define printByte(args)  write(args);
  #else
  #define printByte(args)  print(args,BYTE);
  #endif
  while (n != ' ') {
    n = source.charAt(i); i++;
    if (n != 208 || n!= 209){
      if ( n== 144) lcd.printByte(0x41) else // А
      if ( n== 145) lcd.printByte(0x80) else // Б
....
....
....
....
      if ( n== 142) lcd.printByte(0xB0) else // ю
      if ( n== 143) lcd.printByte(0xB4);     // я
    } 
  }
return;
}

И из него вопрос, потому как просто скомуниздил кусок, а что он значит не знаю.... Для чего вот это -

  #if defined(ARDUINO) && ARDUINO >= 100
  #define printByte(args)  write(args);
  #else
  #define printByte(args)  print(args,BYTE);
  #endif

 

GVS
GVS аватар
Offline
Зарегистрирован: 26.04.2018

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