• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Часы на Nokia 5110 и esp8266 (русификация в комплекте)

Vladimir761

New member
Всем привет!
Хочу поделиться наработкой. Результат вечернего копания в сети - часики на дешевом дисплее Nokia 5110 с русификацией и Esp8266 в качестве мозга.


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

Помимо стандартной для такого комплекта библиотеки Adafruit GFX, там имеется нужная Adafruit PCD8544 Nokia 5110 LCD library с примером pcdtest, в котором помимо всего хорошо разжевана распиновка подключения экрана к микроконтроллеру



Код:
/******************************************************************
== Connection ==

USB TTL     Huzzah      Nokia 5110  Description
            ESP8266     PCD8544

            GND         GND         Ground
            3V          VCC         3.3V from Huzzah to display
            14          CLK         Output from ESP SPI clock
            13          DIN         Output from ESP SPI MOSI to display data input
            12          D/C         Output from display data/command to ESP
            #5          CS          Output from ESP to chip select/enable display
            #4          RST         Output from ESP to reset display
                        LED         3.3V to turn backlight on

******************************************************************/

Когда тест прогнан, приступаем к русификации библиотеки. Причем русифицируется сама библиотека Adafruit GFX. Таким образом, русифицируются все экраны, работа которых основана на этой библиотеке.

Спасибо форуму, подарившему нам русификацию!

План русификации таков:

Сначала качаем авторский русификатор utf8rus

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

Здесь следует отметить, что не совсем сработала русификация. Причина такова, что с момента написания автором функции русификатора, библиотека Adafruit-GFX была модернизирована. Чтобы все исправить, достаточно добавить всего одну строчку :

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





Далее. После русификации надо было превратить экранчик в часы. Для этого пришлось распотрошить модный ныне скетч прогноза погоды для есп и мелкого олед - дисплея. Изначально я и стал заморачиваться с Nokia 5110, чтобы вставить его вместо этой мелюзги:


Нокификация данного проекта предстоит еще.

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

Ну вот, собственно, что получилось:
Код:
/
#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 ();
}
Не забываем, что этот скетч использует дополнительные файлы и состоит не из одной вкладки. Качаем архив с папкой скетча. Это уже как раз то, что накропал я на базе приведенных выше первоисточников.

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

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

Vladimir761

New member
После ряда критических замечаний, скетч был существенно переработан и перезалит (качается из первого сообщения)
 

Ksiw

New member
- функцию utf8rus() добавляем в скетч, или в виде отдельного файла utf8rus.ino копируем в каталог скетча (как и сделано в примере);
Что, и не инклюдить никак? О_о
Процедуры/объекты сами могут вызываться из соседних файлов?
 

Junkie

Member
у меня в демке символы выводятся со сдвигом в один, тоесть алфавит печатается начиная с буквы Б и слово РАЗМЕР пишется как СБИНЖС т.е. виден сдвиг на один символ вперед. как испрвить не подскажите?
 

Junkie

Member
Код:
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F; //было 30
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F; //было 70
          break;
        }
      }
Нашел где подкрутить, может кому пригодится, испрвлял в функции utf8rus
 

Ksiw

New member
Код:
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F; //было 30
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F; //было 70
          break;
        }
      }
Нашел где подкрутить, может кому пригодится, испрвлял в функции utf8rus
Очень интересно, почему у вас вообще возникла эта проблема. Я использовал библиотеки, которые привел автор этой темы, все чудесно работает.
 

Junkie

Member
может дисплей с кривой прошивкой, я не знаю, у меня он как на фото у вас красный, и в начале тоже цветок показывает. сейчас дума как русские символы из ком порта на него вывести, но это так, чисто академическая задача. пока что код таков
Код:
int pos = 0;
char txt[78];
void loop() {
  if (Serial.available()) {
    if(pos==77) {
      arrLeft(txt,78);
      txt[pos] = Serial.read();
    } else {
      txt[pos] = Serial.read();
      pos++;
    }
  }
  display.setCursor(0,0);
  display.clearDisplay();
  display.print(txt);
  display.display();
}
  void arrLeft(char array[], int size) {
  register int i, temp = array[0];
  for (i = 0, size--; i < size; i++) array[i] = array[i+1];
  array[size] = temp;
  }
И еще, я посчитал первым шрифтом на экран помещается 78 (13х6) символов, хотел сделать чтобы когда экран заполняется то весь текст сдвигался бы на одну букву влево, однако сначало экран заполняется, потом пробегает пустота по всем строкам и только потом достигается желаемый эффект печати со сдвигом. может где с массивом прогадал, подскажите если не трудно.
 

Junkie

Member
Все с циклом разобрался. осталось только буквы читать научится с com
Код:
char txt[79] = "";
int pos = 0;
void loop() {
  if(Serial.available()) {
    if(pos==78) {
      arrLeft(txt,78);
      txt[77] = Serial.read();
    } else {
      txt[pos] = Serial.read();
      pos++;
    }
    display.setCursor(0,0);
    display.clearDisplay();
    display.print(txt);
    display.display();
  }
}
  void arrLeft(char array[], int size) {
     register int i; char temp = array[0];
     for (i = 0, size--; i < size; i++) array[i] = array[i+1];
     array[size] = temp;
  }
 

Ksiw

New member
Ага, у меня такой же экран.
Лого цветка - это библиотека адафрут, я в своем коде ее вырезал ради экономии памяти и ускорения загрузки.
Сдвиг букв - это итерация массива видеобуфера. Кстати, массив одномерный, достаточно сдвигать вправо насколько надо и делать обновление экрана функцией
display.display();
Слегка заслоупочил, вижу Вы уже справились.
 
Последнее редактирование:

Junkie

Member
А не знаете как бегущую строку сделать? Вот так буквы в лево уезжают но с правой стороны они переносятся на вторую строку а не появляются из-за границы экрана
Код:
  display.begin();
  display.clearDisplay();
  display.setContrast(60);
  display.setTextColor(BLACK);
  display.setTextSize(3);
  for(int i=100; i>-100; i--) {
  display.setCursor(i,0);
  display.print("HELLO");
  display.display();
  delay(100);
  display.clearDisplay();
  }
 

Junkie

Member
А все разобрался, просто добавить display.setTextWrap(false) и будет справо выезжать
 

AVG

New member
Не компилируется.
Выводит такое сообщение:
sketch\TimeClient.cpp: In member function 'long int TimeClient::getCurrentEpochWithUtcOffset()':
TimeClient.cpp:117:67: error: invalid operands of types 'double' and 'long int' to binary 'operator%'
return round(getCurrentEpoch() + 3600 * myUtcOffset + 86400L) % 86400L;
exit status 1
invalid operands of types 'double' and 'long int' to binary 'operator%'
 
Сверху Снизу