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

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

Краткие итоги предыдущих 100 постов

Для русификации библиотеки Adafruit-GFX требуется:
- скачать любой из приведённых ниже архивов;
- заменить файл glcdfont.c в Adafruit-GFX;
- добавить функцию utf8rus() в скетч;
- вставить в начале скетча команду: display.cp437(true);

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

В архивах примеры и библиотеки, различающиеся по виду дисплея:

0.96" OLED 128x64
https://yadi.sk/d/dd7ULuRftVcRV

2.8" TFT Touch Shield 320x240
https://yadi.sk/d/FgUr5NPztVcRd

Nokia 5110 84x48
https://yadi.sk/d/yJOAk50yoTxF4

Более подробная информация в предыдущих постах.
 

Genri5
Offline
Зарегистрирован: 31.05.2016

И что, в папке "NokiaRus" библиотеки не переделанные? Вы читали мой пост перед Вами?

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

Genri5 пишет:

arduinec, загрузил на другой комп превью Arduino IDE, установил библиотеки из папки "NokiaRus" и запустил тест. На строчку - "display.cp437(true);" - уже неругается, но выдает другую ошибку - " 

Arduino: 1.6.10 Hourly Build 2016/07/20 04:33 (Windows XP), Плата:"Arduino Nano, ATmega328"

C:\Documents and Settings\Orlovsky_G\Рабочий стол\Чек\NokiaRus\NokiaRus\NokiaRusTest\NokiaRusTest.ino: In function 'void setup()':

NokiaRusTest:91: error: 'testdrawline' was not declared in this scope

exit status 1
'testdrawline' was not declared in this scope "

Чего-то, блин еще не хватает ?

Arduino IDE может брать библиотеки из своего каталога и из папки libraries, которая находится в основной папке со скетчами. В посту 99 я написал, как можно поискать откуда берутся библиотеки.

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

У меня всё нормально компилируется в Arduino IDE версии 1.0.5.

Genri5
Offline
Зарегистрирован: 31.05.2016

Извините, IDE 1.05. вчерашний день. Может из этой версии все и скампилируется, откуда скачать превью этой версии? 

Это ,конечно, недостаток или не доработка самой IDE. 

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

В Arduino IDE версии 1.6.5 тоже компилируется.

Предыдущие версии можно взять здесь: https://www.arduino.cc/en/Main/OldSoftwareReleases

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

Установил Arduino IDE 1.6.9, и там компилируется всё без проблем.
В этой версии пути к библиотекам записываются в файл stdout.txt в папке console с цифрами и расширением .tmp, создающейся при компиляции во временном каталоге Windows.

Genri5
Offline
Зарегистрирован: 31.05.2016

Если Вы установили ардуино на тото же компьютер, то не трудно догаться почему у Вас компилируется. У меня никак. Ругаться начинает с -testdrawline();, а если закоментировал идет дальше - testdrawrect();, доходит до- display.println(utf8rus("Шрифт 1")); и т.д. Остается только печать английских. Вообщем хрень какая-то.

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

Genri5 пишет:

Если Вы установили ардуино на тото же компьютер, то не трудно догаться почему у Вас компилируется. У меня никак. Ругаться...

Вы не можете разобраться с библиотеками на своём компьютере, но "догадались" что происходит на моём. На текущий момент у меня стоит 4 Arduino IDE и все работают не мешая друг другу.

Ругается потому, что у вас неправильно установлены (подключены) библиотеки. Вместо моего скетча для проверки можете использовать pcdtest из примера к библиотеке Adafruit_PCD8544 - там те же самые функции testdrawline(), testdrawrect() и т.д.

Genri5
Offline
Зарегистрирован: 31.05.2016

Они не мешают, а дополняют друг друга. Вот у меня заработал скетч :

[code]
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

#include <Wire.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(3, 4, 5, 7, 6);
void setup()
{

display.begin();
display.cp437(true);
display.setContrast(60);
display.clearDisplay();
}

void loop()
{
display.clearDisplay();
display.display();

display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0);
display.println(utf8rus("АБВГДЕжзиклмн"));
display.display();
}
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;
}

[/code]

Да и вообще мне не важен тест. Главное, что свои портативные часы с барометром руссифицировать таки удалось и не без Вашей помощи, за что спасибо. В Arduino IDE существоет два места, где она хранит библиотеки и пока я их не продублировал не хотел компелироваться.

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

Genri5 пишет:

В Arduino IDE существоет два места, где она хранит библиотеки и пока я их не продублировал не хотел компелироваться.

Что я делаю не так? В папке librares в папке с IDE лежат сток либы поставляемые с IDE. В отдельной папке в dropbox лежат мои подключаемые либы. Ни чего ни где не дублируется.

Genri5
Offline
Зарегистрирован: 31.05.2016

Стоковые либы лежат в Program Files86>Arduino>librares и Документы>Arduino>librares. У меня 7-й Виндос.

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

Genri5 пишет:

Стоковые либы лежат в Program Files86>Arduino>librares и Документы>Arduino>librares. У меня 7-й Виндос.

Ну у меня каталоги переопределены, но суть такая. Повторюсь, я ни чего не дублирую. Т.е. если я качаю либу из дуньки, то она ложится в папку с IDE. Если я качаю свою либу, то кидаю в ту что у тебя в документах. и ни что ни куда не дублирую. Приоритет у библиотек расположенных в папке с IDE. т.е. поиск ведется так - AVR, библиотеки в папке IDE, бибилиотеки в документах. Если гдето- находится, то дальше поиск не идет.

Eugen_S
Offline
Зарегистрирован: 27.08.2016

Начинаю только курить тему с Arduino. Обзавёлся TFT 1.8. Заработал, запустил его, рисую, меню ваяю, нужны русские символы, и тут у меня всё колом встало!!! Я никак не могу добиться русских символов. Уже всяко разно менял файлы, танцевал с бубном, курил бамбук, мухоморы кушал... одни иерогливы, то только буквы С или с и всё, задолбался уже колдовать. Чего не так делаю то? По всем постам уже прошёлся, все способы перепробывал, и не получается (.

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

Eugen_S пишет:

Обзавёлся TFT 1.8. Заработал, запустил его, рисую, меню ваяю

С библиотекой Adafruit-GFX или с другой?

Eugen_S
Offline
Зарегистрирован: 27.08.2016

С Adafruit-GFX. Разобрался. В глазах уже "мошки" летают, второй час ночи... балин.. добил ))). 8 часов сидел колдовал, но мухоморы понравились ))). Первые слова, возникшие, на экране, были маты ))), нормальные русские маты по-Русски!!!

Я правда вообще не понял что за тарабарщина написана в файле utf8rus.ino , но думаю, когда-нить буду понимать, разберусь всё же. Спасибо тем кто разжевал, но даже разжёванное мне пришлось долго понимать ))).

Genri5
Offline
Зарегистрирован: 31.05.2016

Мне больше понравилась библиотека  U8glib. В ней заложена поддержка многих дисплеев, есть примеры на разную тематику, легко подключается кириллица - http://arduino.ru/forum/programmirovanie/russkie-shrifty-dlya-biblioteki-u8glib#comment-213536. Дисплей с этой библиотекой работает быстрее. Советую.

Vo_Van_163
Vo_Van_163 аватар
Offline
Зарегистрирован: 10.10.2014

Отличный русификатор! Спасибо

Сделал часики на русифисифицированной по вашей схеме нокии и esp8266 (синхронизация времени по интернет)

Описание процесса создания часов в моей группе вконтакте (вступаем, не стесняемся)

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

Vo_Van_163 пишет:

Описание процесса создания часов в моей группе вконтакте (вступаем, не стесняемся)

 

Зачем часам руссификатор? Это раз. И второе - почему группа ардуйня а в ней только ESP?

Плюс опять же в чем смысл таких часов? Они мелкие.

Плюс скетч кривоват... В смысле расхода ресурсов.

Во первых отрисовка каждые 200мс + время на запросы и отрисовку. Зачем так часто? 1 раз в секунду. Отрисовку делают по таймеру. Во вторых синхронизаци надо делать только 1 раз в setup(). Дальше заводим таймер на каждые 1000мс и каждые 1000мс плюсуем секунды и т.д., запускаем отрисовку и то не всю, а только изменившихся эдементов. Зачем отрисовывать весь экран? Вы думаете винда каждый раз отрисовывает весь экран? Так не принято.

Оптья же в сети... Кто так делает? ну соединился ты с wifi сетью, а интернет там есть? А что будет с часами когда упадет wifi сеть? Реконнекта то нету? Лучше тогда уж в углу значек и пинговать на доступность скажем тот сервер от куда берется время и в зависимости от ответа отрисовывать иконку и то в случае изменения только.

Так что публиковать такое не стоит, потому что это тупое ctrl+c, ctrl+v без понимания смысла и вообще без алгоритма. Тем более подобной инфы именно с часами на той же ESP просто уйма. И те же домашние метеостанции и прочее и прочее. Не надо плодить 100 раз инфу которой и так вагон.

Vo_Van_163
Vo_Van_163 аватар
Offline
Зарегистрирован: 10.10.2014

sirota пишет:

Так что публиковать такое не стоит, потому что это тупое ctrl+c, ctrl+v без понимания смысла и вообще без алгоритма. Тем более подобной инфы именно с часами на той же ESP просто уйма. И те же домашние метеостанции и прочее и прочее. Не надо плодить 100 раз инфу которой и так вагон.

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

Что касается вашей реплике по группе вк. Не вижу противоречия. Лично я прошиваю esp с помощью Arduino ide.

Понятно, что у вас включился умняк, после чего вы решили поразбрасываться словами "тупой" и "не нужный". В большей степени это относится как раз таки к вашему посту. 

Теперь о частоте отрисовки. Действительно, получать время с сервера вполне достаточно и раз в день, либо при первом включении. Так и должно быть. Но в пустышке, коей является мой скетч это все лишне. С точки эстетики, на данном этапе развития данного скетча единственное, что видет юзер на экране - это часы. Синхронизация времени занимает некоторое время, и если даже поставить delay (500) в цикле, то секунды перескакивают, что выглядит не очень.

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

Vo_Van_163 пишет:

поставить delay (500) в цикле, то секунды перескакивают, что выглядит не очень

От delay  в часах лучше избавиться: http://arduino.ru/tutorials/BlinkWithoutDelay

И ещё, не хочется обижать Vo_Van_163, но я бы группу назвал Ардуиня (хотя бы). Ну не те ассоциации возникают при ...уйня.

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

Vo_Van_163 пишет:

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

Это говно код! Рассказываю как обстоит дело.

void setup() {
}

void loop() {
}

Это у нас фундамент.

#include <Adafruit_GFX.h>

Это кирпичик.

#include <utf8rus.h>

Это костыль. Я взял кирпичик и внедрил в него недостающую часть по руссификации. Сейчас у меня есть кирпичик. Полновесный. А вы юзаете кирпичик подпирая костылем. Это пока вы пользуетесь им как текстовым экраном и не расчитываете ширину выводимого текста. А если дать Вам графический экран на который надо выводить по центру контролла текст не известно заранее какой и какой длины и от краев текста до краев контролла должно быть сколько-то пикселей? Будете искать другой костыль? Вот то то же. Такое выставлять на показ ну совсем не камильфо. Тем паче выдавая говнокод за достижение. Автор этой либы красавец. Он сделал свою часть работы - выдал работающий код по конвертации и отладил. Теперь его надо интегрировать в используемую Вами библиотеку для удобства конечного пользования. Это будет кирпичек. У Вас не кирпичик. А хреновая стенка. Она не достроена, кривая и вот-вот развалится. И потом кто-то будет ее пользовать? Вы бы стали пользоваться этй библиотекой если бы время от времени она вместо "Привет" на экран выдавала "Сосать"? Я ни в коем разе не возношу себя. Я тоже ошибаюсь. И я очень рад когда кто-то указывает мне на мои ошибки. Я бы на вашем месте переписал бы код и сказал спасибо. После этого бы у Вас поучилась бы заготовка, шаблон, но не кирпичек.

Vo_Van_163 пишет:

Что касается вашей реплике по группе вк. Не вижу противоречия. Лично я прошиваю esp с помощью Arduino ide.

Прошиваете вы не с помощью Arduibo IDE. Arduibo IDE - графическая оболочка. Прошивается она с помощью скажем AVR ISP. Я к примеру пользуюсь Sublime Text с плагином для интеграции Arduino IDE. 

Vo_Van_163 пишет:

Понятно, что у вас включился умняк, после чего вы решили поразбрасываться словами "тупой" и "не нужный". В большей степени это относится как раз таки к вашему посту. 

Еще раз - вы наваяли копированием кривой "Hello World!". не более. Таких в поиске https://www.google.ru/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=esp8266%20%D1%87%D0%B0%D1%81%D1%8B вагон! Вы изобретали велосипед! При чем изобрели кривой! Я вот к чему Вас веду! То чего вы достигли - ни как не предмет гордости. Это можно выставить как скажем летопись развития себя. Но ни как "кирпичек" для того что бы кто-то пользовался. Как оснвоа по тому как делать не стоит - более чем шикарный мануал. Не подумайте что я оскорбляю. Я просто показываю направление развития. Знаете чем отличается хороший программист от плохого? Не знанеим языка/языков, а умением логически правильно думать! Это есть изначально у всех, у кого-то больше, у кого-то меньше. Расскажу на своем примере. В 2007 году я пишу программу, она конвертирует из 2-х разных бд данные, оперирует ими и заливает в 3-ю бд (ядра бд разные). В общем обработка входных данных размером 500МБ на 2-х процессорном сервере по 2,4ГГц каждое на 10к винтах в raid10 с выдачей результата в 100МБ занимала 4 часа. Потом в 2008 году я понял что я изначально тяну слишком много данных, многие я вообще по итогу не использую. А еще я понял что не стоит делать приложение в 1 кнопку. Надо вывести 10 кнопок, делать архивы баз каждый раз и иметь возможность быстро вернутся скажем из пункта 5 в пункт 2 с данными полученными после пункта 1 (дела бухгалтерские и там скажем много ошибок бухов, которые как сумма на первом этапе выглядят красиво, но как итог для меня они не корректны). Время с 4 часов сократилось до 2-х. Т.е. от пп1 до пп10 скажем. Плюс через скажем час пройдя пп1-пп5 я знаю что результат уже будет не верен и не трачу час на пустые манипуляции. В 2014 году мне и это надоело и программа еще была оптимизирована. Но получилось так что мои познания языка не увеличились (утрирую, что-то новое я узнал, но оно не существенно), но вот качество написания кода возрасло (алгоритмизация). так вот переписать тот код красиво не вышло (это был реально говнокод). Я просто писал код полностью с нуля. Он получился более модульный с большим количеством параметров входных и т.д. Но обработка этиж же данных занимала уже 45 минут. Некоторые шаги были упраздены, я понял что нет смысла считать весб объем данных когда есть возможность заранее предугадать ошибки на случайно выборке и т.д. и т.п. И если бы кто-то в том 2007 году мне сказал что вот это и вот это плюс вот то и вот то изначально не верно, то я бы в 2014 году не просидел 2 недели втыкая в монитор переписывая код с нуля. Я был бы этому рад.

Vo_Van_163 пишет:

Теперь о частоте отрисовки. Действительно, получать время с сервера вполне достаточно и раз в день, либо при первом включении. Так и должно быть. Но в пустышке, коей является мой скетч это все лишне. С точки эстетики, на данном этапе развития данного скетча единственное, что видет юзер на экране - это часы. Синхронизация времени занимает некоторое время, и если даже поставить delay (500) в цикле, то секунды перескакивают, что выглядит не очень.

Вот и исправьте все это. Тогда можно будет о чем-то говорить. У Вас есть таймер. Пользуйте его. Вызывайте его каждые 1000мс и перерисовывайте экрна. Не будет перескока. Заведите еще таймер на час скажем и берите время с сервера, корректируйте со своим временем, но отрисовку делайте все равно в таймер отрисовки. И т.д. и тп..

Vo_Van_163
Vo_Van_163 аватар
Offline
Зарегистрирован: 10.10.2014

Спасибо за справедливую критику и советы. И прошу прощения за некоторую резкость.

Выяснилось, что мини-библиотека Timeclient.h, используемая мной, имеет интересное свойство. После первой синхронизации времени с сервером не надо ничего высчитывать. Достаточно делать запрос текущего времени при помощи соответствующей функции, расчет производится автоматически.  В общем, все круто. От delay избавился. После синхронизации времени, выводится уведомление.

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

Архив перезалил, заменив файлы на текущую версию

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

#include <ESP8266WiFi.h>

#include "Wire.h"
#include "TimeClient.h"


Adafruit_PCD8544 display = Adafruit_PCD8544(14, 13, 12, 5, 4);

float utcOffset = 4; // enter your UTC
TimeClient timeClient(utcOffset);

String ssid = "Tenda";

int clockDelay = 1000 ; // clock update period
int updateDelay = 30*60*1000 ; // time server verify period min*sec*millis
unsigned long clockUpdate = 0 ; // 
unsigned long timeUpdate = 0 ; //
 
void syncPrint () ;
void timePrint ();

void setup()   {
  Serial.begin(9600);
  Serial.println();
  Serial.println();

  

  // initialize dispaly
  display.begin();
  // init done
  display.cp437(true);


  // you can change the contrast around to adapt the display
  // for the best viewing!
  display.setContrast(50);

/*  display.display(); // show splashscreen
  delay(2000);
  display.clearDisplay();   // clears the screen and buffer
*/
  WiFi.begin("Tenda", "12345678");

  display.setTextColor(BLACK);

  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    Serial.print(".");
    display.setTextSize(1);
    display.clearDisplay();
    display.setCursor(0,0);
    display.print(utf8rus("Соединяем х"));
    display.display();

    delay(250);
    Serial.print(".");
    display.clearDisplay();
    display.setCursor(0,0);
    display.print(utf8rus("Соединяем +"));
    display.display();
  }

    display.clearDisplay();
    display.setCursor(0,0);
    display.print(utf8rus("Ура!!!"));
    display.setCursor(0,10);
    display.print(utf8rus("Мы в сети:"));
    display.setCursor(0,20);
    display.print(ssid);
    display.display();

    delay (2000);

    clockUpdate = millis () ; // 
    timeUpdate = millis () ; // 

    timeClient.updateTime();

    
}

void loop () {
  unsigned long currentMillis = millis();

   if ((currentMillis - timeUpdate) < 3000){
    syncPrint ();
   }
   
   if ((currentMillis - timeUpdate) > updateDelay) {
   timeClient.updateTime();
   timeUpdate = millis ();
   }
  
  if ((currentMillis - clockUpdate) >= clockDelay ) {
  
 
  timePrint ();
 
  clockUpdate = millis ();
  }
   display.display();
}

void timePrint () {

//  String time = timeClient.getFormattedTime();
  String H = timeClient.getHours();
  String M = timeClient.getMinutes();
  String S = timeClient.getSeconds();
  display.clearDisplay();
  
  display.setCursor(1,24);
//  display.print(time);
  display.setTextSize(3);
  display.print(H); 
//  display.setTextSize(2);
//  display.print("-"); 
  display.setCursor(47,24);
  display.setTextSize(3);
  display.print(M);
  display.setTextSize(1);
  display.setCursor(35,24);
  display.print(S);
  display.display ();
  
}

void syncPrint () {
//   display.clearDisplay();
   display.setTextSize(1);
   display.setCursor(0,0);
   display.print(utf8rus("Сверим часы с")); 
   display.setCursor(0,8);
   display.print("time.nist.gov"); 
   display.display ();
}
  

 

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

sirota пишет:

Я ни в коем разе не возношу себя.

У меня сложилось иное впечатление.

Меня на этом форуме поражает отношение к новичкам. Написал человек рабочий скетч (пусть и не самый хороший). Тут же на него наезжает "специалист", утверждающий, что код у новичка дерьмо, а самому новичку нужно идти изучать матчасть.
Даже на меня наезжали, и самое смешное (для меня), что пытались "научить" меня Си (на котором я программирую с прошлого века). После конкретных примеров, "учителя" как правило сдувались.

Если человек что-то в скетче сделал не так, то можно спокойно (без понтов) ему на это показать. Чтобы у новичка был стимул развиваться дальше.
Когда маленький ребёнок подходит и говорит: "Папа, посмотри какую я машинку из конструктора собрал". И ответ в стиле нашего форума: "Ты чё урод, не мог сделать машинку получше? Иди книжки читай, а конструктор не трогай!"

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

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

arduinec пишет:

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

Нужно развиваться. ЧЕловек просто скопипастил не разобравшись. Сейчас же он узнал кое какие тонкости работы используемой библиотеки и т.д. А то что у Вас сложилось... бывает.

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

Vo_Van_163 пишет:

Спасибо за справедливую критику и советы. И прошу прощения за некоторую резкость.

Все нормально. Сам так реагирую бывает.

Код уже лучше. но есть недочеты. Почему ssid выведен как переменная, а пароль нет? Плюс опять же зачем:

String ssid = "Tenda";

Не стоит так не рационально юзать память. Забудьте про string в мире МК! Это расточительство! Юзайте в вашем случае

#define SSID TENDA
#define SSID_PASS 12345678

НА сколкьо я помню данная библа все таки юзает стринги, по этому в вашем случае размер не изменится сильно, но это задел на будущее.

Vo_Van_163
Vo_Van_163 аватар
Offline
Зарегистрирован: 10.10.2014

sirota пишет:

Почему ssid выведен как переменная, а пароль нет? 

 

Пробовал вставить пароль и ssid в  WiFi.begin("Tenda", "12345678"); в качестве переменной, но почему-то выдало ошибку. Поэтому ввел строчное название сети для дальнейшего вывода на печать. А воодще-то это ведь константа, так что надо исправить...

За define спасибо, буду разбираться, я пока не совсем врубился, что это, хотя оно сплошь и рядом. Я в детстве бейсик учил под руководством отца (пк 01 Львов), затем в школе БК-01 было, ну и zx Spectrum (куда без него). И вот спустя десятилетия - ардуина. Так что пытаюсь развиваться на досуге  :)

 

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

Vo_Van_163 пишет:

За define спасибо, буду разбираться, я пока не совсем врубился, что это, хотя оно сплошь и рядом. Я в детстве бейсик учил под руководством отца (пк 01 Львов), затем в школе БК-01 было, ну и zx Spectrum (куда без него). И вот спустя десятилетия - ардуина. Так что пытаюсь развиваться на досуге  :)

define - подстановка. Т.е. это не переменная и не константа. При компиляции значение физически будет вживлено в код. Т.е. этот как буд-то вы руками везде его ввели. Есть плюсы - не расходуется память на переменные и остается возможность быстро изменить какое-то значение везде в коде исправив только в одном месте. но есть и минус - растет размер кода, ну и нельзя изменить значение в ходе выполнения программы.

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

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

Vo_Van_163 пишет:

За define спасибо, буду разбираться, я пока не совсем врубился, что это, хотя оно сплошь и рядом. Я в детстве бейсик учил под руководством отца (пк 01 Львов), затем в школе БК-01 было, ну и zx Spectrum (куда без него). И вот спустя десятилетия - ардуина. Так что пытаюсь развиваться на досуге  :)

define - подстановка. Т.е. это не переменная и не константа. При компиляции значение физически будет вживлено в код. Т.е. этот как буд-то вы руками везде его ввели. Есть плюсы - не расходуется память на переменные и остается возможность быстро изменить какое-то значение везде в коде исправив только в одном месте. но есть и минус - растет размер кода, ну и нельзя изменить значение в ходе выполнения программы.

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

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

Vo_Van_163 пишет:

За define спасибо, буду разбираться, я пока не совсем врубился, что это, хотя оно сплошь и рядом.

В книге Белецкого "Энциклопедия языка Си" про них целая глава 10 написана:
https://yadi.sk/d/7p0JU1dev2mFN
 

Joiner
Offline
Зарегистрирован: 04.09.2014

arduinec пишет:

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

..................................
Функция 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("Тест"));

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

https://yadi.sk/d/FWO6Y1NwiqLVu

УРАААА!!!!! Почти получилось!

Захотелось руссифицировать дисплейчик ILI9163C. Подсунул в библиотеку Adafruit_GFX ваш файл со шрифтом, применил Вашу функцию. Дисплей стал говорить на русском...но символы вычисляются, как я понял, со сдвигом на один символ. Слово "Тест" выводится на экран "Ужту".

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

Уж очень хочется, чтобы текст выводился на русском.

DarkGenius
Offline
Зарегистрирован: 09.07.2015

display.cp437(true); в сетап добавь

Joiner
Offline
Зарегистрирован: 04.09.2014

DarkGenius пишет:

display.cp437(true); в сетап добавь

DarkGenius, спасибо ОГРОМНОЕ!!!!!!

Теперь слово "Тест" выводится "Тест". УРАААА!!!!!

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

И еще увидел, что с помощью этой функции можно в ардуиновский сериал монитор выводить слова на русском.

Спасибо.

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

Joiner пишет:

DarkGenius пишет:

display.cp437(true); в сетап добавь

Немного жаль, что не понимаю что означает подсказанная Вами строчка

В старой библиотеке Adafruit-GFX была ошибка, и в новых библиотеках они её таким образом исправляют.

Joiner
Offline
Зарегистрирован: 04.09.2014

arduinec пишет:

В старой библиотеке Adafruit-GFX была ошибка, и в новых библиотеках они её таким образом исправляют.

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

Спасибо!

negavoid
Offline
Зарегистрирован: 09.07.2016

Как сконвертировать любые кириллические шрифты Windows для использования с Adafruit GFX

Подготовка (1 раз):

- glcdfont.c заменять не обязательно, если не планируем выводить кириллицу шрифтом по умолчанию

- у меня всё работает и без вызова display.cp437(true), возможно, вам всё же понадобится её вызвать в скетче

- устанавливаем любую виртуальную машину, vmware, virtualbox (https://www.virtualbox.org/wiki/Downloads)

- ставим туда линукс, у меня уже была готовая машина с убунтой (http://www.ubuntu.com/download/desktop), я её и использовал, вы же смело можете проклацать по умолчанию все этапы установки в виртуалку - далее, далее, далее... Не забываем также после установки системы установить дополнения для виртуальной машины, чтобы нам было удобно копировать и вставлять файлы.

- заходим в папку [ скетчи/libraries/ваш-adafruit-gfx/fontconvert/ ], заменяем содержимое файла fontconvert.c на вот это (чуть подправил его для корректной работы с юникодом, таблицу взял здесь http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT):

fontconvert.c (с таблицей перекодировки для Windows-1251)

/*
TrueType to Adafruit_GFX font converter.  Derived from Peter Jakobs'
Adafruit_ftGFX fork & makefont tool, and Paul Kourany's Adafruit_mfGFX.

NOT AN ARDUINO SKETCH.  This is a command-line tool for preprocessing
fonts to be used with the Adafruit_GFX Arduino library.

For UNIX-like systems.  Outputs to stdout; redirect to header file, e.g.:
  ./fontconvert ~/Library/Fonts/FreeSans.ttf 18 > FreeSans18pt7b.h

REQUIRES FREETYPE LIBRARY.  www.freetype.org

Currently this only extracts the printable 7-bit ASCII chars of a font.
Will eventually extend with some int'l chars a la ftGFX, not there yet.
Keep 7-bit fonts around as an option in that case, more compact.

See notes at end for glyph nomenclature & other tidbits.
*/

#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <ft2build.h>
#include FT_GLYPH_H
#include "../gfxfont.h" // Adafruit_GFX font structures

#define DPI 141 // Approximate res. of Adafruit 2.8" TFT

// Accumulate bits for output, with periodic hexadecimal byte write
void enbit(uint8_t value) {
	static uint8_t row = 0, sum = 0, bit = 0x80, firstCall = 1;
	if(value) sum |= bit;    // Set bit if needed
	if(!(bit >>= 1)) {       // Advance to next bit, end of byte reached?
		if(!firstCall) { // Format output table nicely
			if(++row >= 12) {        // Last entry on line?
				printf(",\n  "); //   Newline format output
				row = 0;         //   Reset row counter
			} else {                 // Not end of line
				printf(", ");    //   Simple comma delim
			}
		}
		printf("0x%02X", sum); // Write byte value
		sum       = 0;         // Clear for next byte
		bit       = 0x80;      // Reset bit counter
		firstCall = 0;         // Formatting flag
	}
}

int main(int argc, char *argv[]) {
	int                i, j, err, size, first=' ', last='~',
	                   bitmapOffset = 0, x, y, byte;
	char              *fontName, c, *ptr;
	FT_Library         library;
	FT_Face            face;
	FT_Glyph           glyph;
	FT_Bitmap         *bitmap;
	FT_BitmapGlyphRec *g;
	GFXglyph          *table;
	uint8_t            bit;

	// Parse command line.  Valid syntaxes are:
	//   fontconvert [filename] [size]
	//   fontconvert [filename] [size] [last char]
	//   fontconvert [filename] [size] [first char] [last char]
	// Unless overridden, default first and last chars are
	// ' ' (space) and '~', respectively

	if(argc < 3) {
		fprintf(stderr, "Usage: %s fontfile size [first] [last]\n",
		  argv[0]);
		return 1;
	}

	size = atoi(argv[2]);

	if(argc == 4) {
		last  = atoi(argv[3]);
	} else if(argc == 5) {
		first = atoi(argv[3]);
		last  = atoi(argv[4]);
	}

	if(last < first) {
		i     = first;
		first = last;
		last  = i;
	}

	ptr = strrchr(argv[1], '/'); // Find last slash in filename
	if(ptr) ptr++;         // First character of filename (path stripped)
	else    ptr = argv[1]; // No path; font in local dir.

	// Allocate space for font name and glyph table
	if((!(fontName = malloc(strlen(ptr) + 20))) ||
	   (!(table = (GFXglyph *)malloc((last - first + 1) *
	    sizeof(GFXglyph))))) {
		fprintf(stderr, "Malloc error\n");
		return 1;
	}

	// Derive font table names from filename.  Period (filename
	// extension) is truncated and replaced with the font size & bits.
	strcpy(fontName, ptr);
	ptr = strrchr(fontName, '.'); // Find last period (file ext)
	if(!ptr) ptr = &fontName[strlen(fontName)]; // If none, append
	// Insert font size and 7/8 bit.  fontName was alloc'd w/extra
	// space to allow this, we're not sprintfing into Forbidden Zone.
	sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7);
	// Space and punctuation chars in name replaced w/ underscores.  
	for(i=0; (c=fontName[i]); i++) {
		if(isspace(c) || ispunct(c)) fontName[i] = '_';
	}

	// Init FreeType lib, load font
	if((err = FT_Init_FreeType(&library))) {
		fprintf(stderr, "FreeType init error: %d", err);
		return err;
	}
	if((err = FT_New_Face(library, argv[1], 0, &face))) {
		fprintf(stderr, "Font load error: %d", err);
		FT_Done_FreeType(library);
		return err;
	}

	// << 6 because '26dot6' fixed-point format
	FT_Set_Char_Size(face, size << 6, 0, DPI, 0);

	// Currently all symbols from 'first' to 'last' are processed.
	// Fonts may contain WAY more glyphs than that, but this code
	// will need to handle encoding stuff to deal with extracting
	// the right symbols, and that's not done yet.
	// fprintf(stderr, "%ld glyphs\n", face->num_glyphs);

	printf("const uint8_t %sBitmaps[] PROGMEM = {\n  ", fontName);

	// Process glyphs and output huge bitmap data array
	for(i=first, j=0; i<=last; i++, j++) {

		// Mapping for Windows-1251
		int utf[128] =
		{
			0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
			0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
			0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
			0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
			0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
			0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
			0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
			0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
		};

		int ch = ( i > 127 ) ? utf[ i - 128 ] : i ;

		// MONO renderer provides clean image with perfect crop
		// (no wasted pixels) via bitmap struct.
		if((err = FT_Load_Char(face, ch, FT_LOAD_TARGET_MONO))) {
			fprintf(stderr, "Error %d loading char '%c'\n",
			  err, ch);
			continue;
		}

		if((err = FT_Render_Glyph(face->glyph,
		  FT_RENDER_MODE_MONO))) {
			fprintf(stderr, "Error %d rendering char '%c'\n",
			  err, i);
			continue;
		}

		if((err = FT_Get_Glyph(face->glyph, &glyph))) {
			fprintf(stderr, "Error %d getting glyph '%c'\n",
			  err, i);
			continue;
		}

		bitmap = &face->glyph->bitmap;
		g      = (FT_BitmapGlyphRec *)glyph;

		// Minimal font and per-glyph information is stored to
		// reduce flash space requirements.  Glyph bitmaps are
		// fully bit-packed; no per-scanline pad, though end of
		// each character may be padded to next byte boundary
		// when needed.  16-bit offset means 64K max for bitmaps,
		// code currently doesn't check for overflow.  (Doesn't
		// check that size & offsets are within bounds either for
		// that matter...please convert fonts responsibly.)
		table[j].bitmapOffset = bitmapOffset;
		table[j].width        = bitmap->width;
		table[j].height       = bitmap->rows;
		table[j].xAdvance     = face->glyph->advance.x >> 6;
		table[j].xOffset      = g->left;
		table[j].yOffset      = 1 - g->top;

		for(y=0; y < bitmap->rows; y++) {
			for(x=0;x < bitmap->width; x++) {
				byte = x / 8;
				bit  = 0x80 >> (x & 7);
				enbit(bitmap->buffer[
				  y * bitmap->pitch + byte] & bit);
			}
		}

		// Pad end of char bitmap to next byte boundary if needed
		int n = (bitmap->width * bitmap->rows) & 7;
		if(n) { // Pixel count not an even multiple of 8?
			n = 8 - n; // # bits to next multiple
			while(n--) enbit(0);
		}
		bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8;

		FT_Done_Glyph(glyph);
	}

	printf(" };\n\n"); // End bitmap array

	// Output glyph attributes table (one per character)
	printf("const GFXglyph %sGlyphs[] PROGMEM = {\n", fontName);
	for(i=first, j=0; i<=last; i++, j++) {
		printf("  { %5d, %3d, %3d, %3d, %4d, %4d }",
		  table[j].bitmapOffset,
		  table[j].width,
		  table[j].height,
		  table[j].xAdvance,
		  table[j].xOffset,
		  table[j].yOffset);
		if(i < last) {
			printf(",   // 0x%02X", i);
			if((i >= ' ') && (i <= '~')) {
				printf(" '%c'", i);
			}
			putchar('\n');
		}
	}
	printf(" }; // 0x%02X", last);
	if((last >= ' ') && (last <= '~')) printf(" '%c'", last);
	printf("\n\n");

	// Output font structure
	printf("const GFXfont %s PROGMEM = {\n", fontName);
	printf("  (uint8_t  *)%sBitmaps,\n", fontName);
	printf("  (GFXglyph *)%sGlyphs,\n", fontName);
	printf("  0x%02X, 0x%02X, %ld };\n\n",
	  first, last, face->size->metrics.height >> 6);
	printf("// Approx. %d bytes\n",
	  bitmapOffset + (last - first + 1) * 7 + 7);
	// Size estimate is based on AVR struct and pointer sizes;
	// actual size may vary.

	FT_Done_FreeType(library);

	return 0;
}

/* -------------------------------------------------------------------------

Character metrics are slightly different from classic GFX & ftGFX.
In classic GFX: cursor position is the upper-left pixel of each 5x7
character; lower extent of most glyphs (except those w/descenders)
is +6 pixels in Y direction.
W/new GFX fonts: cursor position is on baseline, where baseline is
'inclusive' (containing the bottom-most row of pixels in most symbols,
except those with descenders; ftGFX is one pixel lower).

Cursor Y will be moved automatically when switching between classic
and new fonts.  If you switch fonts, any print() calls will continue
along the same baseline.

                    ...........#####.. -- yOffset
                    ..........######..
                    ..........######..
                    .........#######..
                    ........#########.
   * = Cursor pos.  ........#########.
                    .......##########.
                    ......#####..####.
                    ......#####..####.
       *.#..        .....#####...####.
       .#.#.        ....##############
       #...#        ...###############
       #...#        ...###############
       #####        ..#####......#####
       #...#        .#####.......#####
====== #...# ====== #*###.........#### ======= Baseline
                    || xOffset

glyph->xOffset and yOffset are pixel offsets, in GFX coordinate space
(+Y is down), from the cursor position to the top-left pixel of the
glyph bitmap.  i.e. yOffset is typically negative, xOffset is typically
zero but a few glyphs will have other values (even negative xOffsets
sometimes, totally normal).  glyph->xAdvance is the distance to move
the cursor on the X axis after drawing the corresponding symbol.

There's also some changes with regard to 'background' color and new GFX
fonts (classic fonts unchanged).  See Adafruit_GFX.cpp for explanation.
*/

- далее копируем внутрь виртуальной машины (куда-нибудь в home) целиком всю папку с библиотекой [ваш-adafruit-gfx]

- внутри виртуалки открываем консоль, заходим в папку fontconvert, собираем бинарник

cd ~/adafruit-gfx/fontconvert
sudo apt-get install libfreetype6-dev
make

Конвертация:

Идём в c:/windows/fonts, выбираем шрифт по вкусу. Копипастим файл шрифта внутрь убунты, в нашу папку fontconvert. Например, я взял шрифт Segoe Script, лежащий в файле SEGOESC.TTF

Запускаем конвертер в терминале виртуальной машины:

./fontconvert SEGOESC.TTF 10 20 255 > SEGOESC10pt8b.h

где 10 - это желаемый нами базовый размер шрифта, а 20 и 255 означают коды первого и последнего символов для конвертации. Если мы для экономии места хотим, чтобы в получившемся шрифте были *ТОЛЬКО* русские символы, вместо 20-255 можно указать диапазон 128-255.

Копируем получившийся заголовочный файл SEGOESC10pt8b.h из убунты в папку со скетчем

И, наконец-то, подключаем шрифт к скетчу, и пользуемся им с помощью функции utf8rus

(позвольте скопировать её в это сообщение ещё раз, чтобы всё было в одном месте)

utf8rus.h

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;
}

 

#include "utf8rus.h"

#include "SEGOESC10pt8b.h"
tft.setFont( &SEGOESC10pt8b );

tft.println( utf8rus( "АаБбВвГгДдЕеЁёЖжЗзИиЙй" ) );
tft.println( utf8rus( "КкЛлМмНнОоПпРрСсТтУуФф" ) );
tft.println( utf8rus( "ХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя" ) );
tft.println( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
tft.println( "abcdefghijklmnopqrstuvwxyz" );

 

Если сконвертированный шрифт на вашем дисплее всё же выглядит слегка убого, в 27 строке файла fontconvert.c задаётся DPI дисплея. Можете попробовать изменить это значение под ваш дисплей и пересобрать утилиту, снова набрав в консоли команду make.

#define DPI 141 // Approximate res. of Adafruit 2.8" TFT

Ещё, Adafruit напоминает, что при работе с такими шрифтами автоматическое закрашивание бэкграунда не работает, при перерисовке закрашивать фон придётся самим, определяя размер rect-а через функцию getTextBounds (https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts):

int16_t  x1, y1;
uint16_t w, h;
tft.getTextBounds(string, x, y, &x1, &y1, &w, &h);

 

mobez
Offline
Зарегистрирован: 05.11.2016

Долго думал как использовать эту tft.getTextBounds(string, x, y, &x1, &y1, &w, &h); х..ню, вот написал небольшой void: 

void send_tft(String text){
int str_len = text.length()+1; 
 char char_array[str_len];
text.toCharArray(char_array, str_len);
int16_t x1, y1;
uint16_t w1, h1; 
tft.getTextBounds(char_array, tft.getCursorX(), tft.getCursorY(), &x1, &y1, &w1, &h1);
tft.fillRect(x1,y1, w1, h1, ST7735_BLACK);
tft.println(text);
}

Можно еще добавить изменение цвета.


void send_tft(String text, uint16_t color){
int str_len = text.length()+1; 
 char char_array[str_len];
text.toCharArray(char_array, str_len);
int16_t x1, y1;
uint16_t w1, h1; 
tft.getTextBounds(char_array, tft.getCursorX(), tft.getCursorY(), &x1, &y1, &w1, &h1);
tft.fillRect(x1,y1, w1, h1, color);
tft.println(text);
}

 

Zehar
Offline
Зарегистрирован: 12.11.2016

если еще актуально, то я изменил библиотеки именно под линейки из 4 модулей Max7219 и добавил русский шрифт. надо полностью удалить установленные библиотеки Adafruit-GFX-Library-master и arduino-Max72xxPanel-master. из архива https://cloud.mail.ru/public/5yjk/u3DrFZ5UQ установить библиотеки в каталог  Arduino\libraries и изменить в файле C:\Users\ИМЯ_ПОЛЬЗОВАТЕЛЯ\AppData\Roaming\Arduino15\preferences.txt строку preproc.substitute_unicode=true на preproc.substitute_unicode=false. все действия проводить при закрытой программе Arduino. проверено на arduino-1.6.5-r5, система win8.1 x64.

в примерах arduino-Max72xxPanel-master будет Z_Scroll_Max7219, точно работает. все остальные тоже должны работать без переделки под эти модули.

Apofez
Offline
Зарегистрирован: 23.11.2016

Привет всем. Подскажите изза чего дисплей показывает через строчку? Он их как будто не видит

это квадрат должен быть 16х16

Apofez
Offline
Зарегистрирован: 23.11.2016

Всем спасибо) Разобрался сам. Оказывается в файле Adafruit_SSD1306.h надо было выбрать свой дисплей.



/*=========================================================================
    SSD1306 Displays
    -----------------------------------------------------------------------
    The driver is used in multiple displays (128x64, 128x32, etc.).
    Select the appropriate display below to create an appropriately
    sized framebuffer, etc.
 
    SSD1306_128_64  128x64 pixel display
 
    SSD1306_128_32  128x32 pixel display
 
    SSD1306_96_16
 
    -----------------------------------------------------------------------*/
   #define SSD1306_128_64
// #define SSD1306_128_32
//   #define SSD1306_96_16
/*=========================================================================*/
pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

Я тут на днях получил олед экранчик 0.96` 128х64 монохромный. Решил его подцепить/проверить. В качестве МСU использовался ESP8266 (wemos d1 mini). Так вот сходу в лоб нифига не заработало. А именно либа фруктовая под есп не компилится. Пришлось брать отсюда https://github.com/somhi/ESP_SSD1306 С ней заработало все как доктор прописал. Еще раз спасибо arduinec за русификацию. Ща буду пробовать шрифты. Вот еще кто нибудь бы поделился нормальным русификатором для lcd1602 с I2C переходником на PCF8574 (lcd со встроенной в знакогенератор кирилицей) У меня вылазит трабла с определением длины строки функцией string.length(); из-за того, что кирилица имеет размер 2 байта. Если писать строки кодами - то все замечательно, но в программе код становится не читабельным.

pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

Zehar пишет:

если еще актуально, то я изменил библиотеки именно под линейки из 4 модулей Max7219 и добавил русский шрифт. надо полностью удалить установленные библиотеки Adafruit-GFX-Library-master и arduino-Max72xxPanel-master. из архива https://cloud.mail.ru/public/5yjk/u3DrFZ5UQ установить библиотеки в каталог  Arduino\libraries и изменить в файле C:\Users\ИМЯ_ПОЛЬЗОВАТЕЛЯ\AppData\Roaming\Arduino15\preferences.txt строку preproc.substitute_unicode=true на preproc.substitute_unicode=false. все действия проводить при закрытой программе Arduino. проверено на arduino-1.6.5-r5, система win8.1 x64.

в примерах arduino-Max72xxPanel-master будет Z_Scroll_Max7219, точно работает. все остальные тоже должны работать без переделки под эти модули.

у мну без этих костылей все заработало

  matrix.setIntensity(3); // Use a value between 0 and 15 for brightness
  matrix.setRotation(matrix.getRotation() + 3); //1 - 90  2 - 180   3 - 270
  matrix.cp437(true);
  matrix.setTextSize(1);
  matrix.setTextWrap(false); // Allow text to run off right edge
  matrix.fillScreen(LOW);
  matrix.setCursor(1, 0);
  if (eeprom_data.rus_disp) matrix.print(utf8rus("Салют"));
  else matrix.print("Hello");
  matrix.write();

 

pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

negavoid пишет:

Как сконвертировать любые кириллические шрифты Windows для использования с Adafruit GFX

а не поделитесь парой тройкой готовых шрифтов размером 5х7 на попробывать?

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

pilnikov пишет:

а не поделитесь парой тройкой готовых шрифтов размером 5х7 на попробывать?

В посте 27 приводится скетч, с помощью которого можно редактировать шрифты.

pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

arduinec пишет:

В посте 27 приводится скетч, с помощью которого можно редактировать шрифты.

Спасибо попробую. Для этого придется делать цикл и рисовать живьем все буквы - оно достаточно трудозатратно.

arduinec не могли бы вы как спец по переводу подсказать возможное решение?

Как вырезать субстроку из строки, состоящей из символов разной длины (1 или 2 байта)?

Спасибо.

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

pilnikov пишет:

Спасибо попробую. Для этого придется делать цикл и рисовать живьем все буквы - оно достаточно трудозатратно.

Символы уже нарисованы и находятся в файле glcdfont.c, который находится в моих архивах (прилагаемых в этой теме).

pilnikov пишет:

Как вырезать субстроку из строки, состоящей из символов разной длины (1 или 2 байта)?

http://arduino.ru/Reference/StringSubstring

pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

Имхуется мне, что индексы from и to - это ни что иное как номера байтов в строке, а не номера символов

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

pilnikov пишет:

Имхуется мне, что индексы from и to - это ни что иное как номера байтов в строке, а не номера символов

С точки зрения строки символы и байты - это практически одно и то же. Строка (как массив) не знает однобайтовые в ней символы или многобайтовые.

utf8rus() же возращает строку, состоящую только из однобайтовых символов.

pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

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

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

Пример бегущей строки с большими символами на LCD 1602:
http://arduino.ru/forum/programmirovanie/etyud-2-stroki-po-40-simvolov-n...
 

pilnikov
pilnikov аватар
Онлайн
Зарегистрирован: 28.08.2015

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

моя бегущая строка работает крайне просто - на экран выводится вырезка из строки в 16 символов. с каждым новым сканом вырезка сдвигается на один символ вправо. в первый скан отображаются символы с 0 по 15 во второй с 1 по 16 и тд.