• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ESP8266+ST7735S, как заставить работать корректно кириллические шрифты

Fill

New member
Решил тут поиграться с дисплеем ST7735S, ну какие-то навыки есть минимальные, интернет + GPT в помощь
Код:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <TimeLib.h>
#include <OneWire.h>
#include <DallasTemperature.h>


// Подключение дисплея
#define TFT_CS   D2
#define TFT_RST  D4
#define TFT_DC   D3

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

// Настройки Wi-Fi
const char *ssid = "Имя сети";
const char *password = "Пароль";

// Настройки NTP
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ru.pool.ntp.org", 10800, 60000); // Синхронизация каждую минуту (60000 мс)

// Подключение DS18B20
#define ONE_WIRE_BUS D1 // Пин, к которому подключен датчик
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Переменные для времени
unsigned long previousEpoch = 0;
int prevHour = -1;
int prevMinute = -1;
int prevSecond = -1;
bool colonVisible = true;

// Переменные для температуры
float currentTemp = 0.0;
float prevTemp = -100.0;
bool tempRequestInProgress = false; // Флаг состояния обновления температуры

// Переменные для таймера обновления температуры
unsigned long lastTempUpdate = 0; // Время последнего обновления температуры
const unsigned long tempUpdateInterval = 1000; // Интервал обновления температуры (мс)

void updateTemperature() {
  if (!tempRequestInProgress) {
    // Запрос температуры
    sensors.requestTemperatures();
    tempRequestInProgress = true;
    return;
  }

  // Считывание температуры
  currentTemp = sensors.getTempCByIndex(0);
  tempRequestInProgress = false;

  // Если температура изменилась, обновляем её отображение
  if (abs(currentTemp - prevTemp) >= 0.1) {
    prevTemp = currentTemp;

    tft.setTextSize(4);
    tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
    tft.setCursor(5, 60);
    tft.printf("%.1f C", currentTemp);

    // Рисуем символ градуса и "C"
    tft.setTextSize(1); // Уменьшаем размер шрифта для градуса и C
    tft.setCursor(110, 60); // Место для символа градуса
    tft.print("o");        // Символ "C"
  }
}

void setup() {
  Serial.begin(115200);

  // Инициализация дисплея
  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(ST7735_BLACK);
  tft.setRotation(1);

  // Установка яркости дисплея (по желанию)
  pinMode(TFT_LED, OUTPUT);
  analogWrite(TFT_LED, 64); // Уменьшаем яркость (от 0 до 255)

  // Подключение к Wi-Fi
  tft.setTextSize(1);
  tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
  tft.setCursor(10, 10);
  tft.print("Connecting...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(10, 10);
  tft.print("WiFi connected!");

  // Инициализация NTP и DS18B20
  timeClient.begin();
  timeClient.update();
  sensors.begin();

  // Установка времени
  setTime(timeClient.getEpochTime());
  previousEpoch = now();

  // Обновление температуры при старте
  updateTemperature();

  delay(2000);
  tft.fillScreen(ST7735_BLACK);
}

void loop() {
  // Обновление времени
  timeClient.update();
  unsigned long currentEpoch = timeClient.getEpochTime();
  if (currentEpoch != previousEpoch) {
    setTime(currentEpoch);
    previousEpoch = currentEpoch;
  }

  int currentHour = hour();
  int currentMinute = minute();
  int currentSecond = second();

  // Обновление времени на дисплее
  if (currentHour != prevHour || currentMinute != prevMinute) {
    prevHour = currentHour;
    prevMinute = currentMinute;

    tft.setTextSize(5);
    tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
    tft.setCursor(5, 10);
    tft.printf("%02d", currentHour);

    tft.setCursor(95, 10);
    tft.printf("%02d", currentMinute);
  }

  // Мигающее двоеточие
  if (currentSecond != prevSecond) {
    prevSecond = currentSecond;
    colonVisible = !colonVisible;

    tft.setTextSize(5);
    tft.setCursor(63, 10);
    if (colonVisible) {
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print(":");
    } else {
      tft.setTextColor(ST7735_BLACK, ST7735_BLACK);
      tft.print(":");
    }
  }

  // Таймер обновления температуры
  unsigned long currentMillis = millis();
  if (currentMillis - lastTempUpdate >= tempUpdateInterval) {
    lastTempUpdate = currentMillis;
    updateTemperature();
  }
}
Вышел вот такой рабочий код, попытки нарисовать символ "градуса" не привели к успеху, решил сразу копать сразу в сторону русификации, думаю там заодно и с символом "градуса" разберусь....
В общем насколько я понял, без подключения стороннего шрифта, дисплей кириллицу не поддерживает, всяческие перекодировки из utf8 в win1251 к успеху не привели - иероглифы.
Далее вот такой код с подключением шрифта
Код:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <TimeLib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "FontsRus/FreeMonoBold6.h"

// Подключение дисплея
#define TFT_CS   D2
#define TFT_RST  D4
#define TFT_DC   D3

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

// Настройки Wi-Fi
const char *ssid = "Имя сети";
const char *password = "Пароль";

// Настройки NTP
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ru.pool.ntp.org", 10800, 60000); // Синхронизация каждую минуту (60000 мс)

// Подключение DS18B20
#define ONE_WIRE_BUS D1 // Пин, к которому подключен датчик
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Переменные для времени
unsigned long previousEpoch = 0;
int prevHour = -1;
int prevMinute = -1;
int prevSecond = -1;
bool colonVisible = true;

// Переменные для температуры
float currentTemp = 0.0;
float prevTemp = -100.0;
bool tempRequestInProgress = false; // Флаг состояния обновления температуры

// Переменные для таймера обновления температуры
unsigned long lastTempUpdate = 0; // Время последнего обновления температуры
const unsigned long tempUpdateInterval = 1000; // Интервал обновления температуры (мс)

void updateTemperature() {
  if (!tempRequestInProgress) {
    // Запрос температуры
    sensors.requestTemperatures();
    tempRequestInProgress = true;
    return;
  }

  // Считывание температуры
  currentTemp = sensors.getTempCByIndex(0);
  tempRequestInProgress = false;

  // Если температура изменилась, обновляем её отображение
  if (abs(currentTemp - prevTemp) >= 0.1) {
    prevTemp = currentTemp;

    tft.setTextSize(3);
    tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
    tft.setCursor(5, 80);
    tft.fillRect(5, 80, 120, 30, ST7735_BLACK); // Очистка области перед выводом температуры
    tft.printf("%.1f C", currentTemp);
  }
}

void setup() {
  Serial.begin(115200);

  // Инициализация дисплея
  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(ST7735_BLACK);
  tft.setRotation(1);

  // Подключение к Wi-Fi
  tft.setTextSize(1);
  tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
  tft.setFont(&FreeMonoBold6pt8b);  // Установка кастомного шрифта
  tft.setCursor(10, 10);
  tft.print("Подключение...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(10, 10);
  tft.print("WiFi connected!");

  // Инициализация NTP и DS18B20
  timeClient.begin();
  timeClient.update();
  sensors.begin();

  // Установка времени
  setTime(timeClient.getEpochTime());
  previousEpoch = now();

  // Обновление температуры при старте
  updateTemperature();

  delay(2000);
  tft.fillScreen(ST7735_BLACK);
}

void loop() {
  // Обновление времени
  timeClient.update();
  unsigned long currentEpoch = timeClient.getEpochTime();
  if (currentEpoch != previousEpoch) {
    setTime(currentEpoch);
    previousEpoch = currentEpoch;
  }

  int currentHour = hour();
  int currentMinute = minute();
  int currentSecond = second();

  // Обновление времени на дисплее
  if (currentHour != prevHour || currentMinute != prevMinute) {
    prevHour = currentHour;
    prevMinute = currentMinute;

    // Очистка области перед обновлением часов
    tft.setTextSize(3);
    tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
    tft.fillRect(5, 35, 60, 30, ST7735_BLACK); // Очистка области для часов
    tft.setCursor(5, 35);
    tft.printf("%02d", currentHour);

    // Очистка области перед обновлением минут
    tft.fillRect(95, 35, 60, 30, ST7735_BLACK); // Очистка области для минут
    tft.setCursor(95, 35);
    tft.printf("%02d", currentMinute);
  }

  // Мигающее двоеточие
  if (currentSecond != prevSecond) {
    prevSecond = currentSecond;
    colonVisible = !colonVisible;

    tft.setTextSize(3);
    tft.setCursor(63, 35);
    tft.fillRect(63, 35, 20, 30, ST7735_BLACK); // Очистка области для двоеточия
    if (colonVisible) {
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print(":");
    } else {
      tft.setTextColor(ST7735_BLACK, ST7735_BLACK);
      tft.print(":");
    }
  }

  // Таймер обновления температуры
  unsigned long currentMillis = millis();
  if (currentMillis - lastTempUpdate >= tempUpdateInterval) {
    lastTempUpdate = currentMillis;
    updateTemperature();
  }
}
в итоге и так и сяк fillRect(), fillScreen() работает криво, выглядит не эстетично, через setTextColor(foreground, background) работает идеально, но только со стандартным шрифтом, а с костюмными происходит наслоение.
photo_2025-02-10_12-59-43.jpg
photo_2025-02-10_13-01-16.jpg
 

pvvx

Активный участник сообщества
1739278863612.png
Поиск Google, YouTube или DeepSeek: "squareline studio esp32" и т.д.
Бесплатной версии SquareLine вам хватит на создание любых меню и отображений для ESP.
 
Сверху Снизу