Фоторамка с нейросетью

Коллеги, у Алекса есть проект "Фоторамка с нейросетью" на ESP8266. Купил дисплей на контроллере ILI9488. Не могу приживить, при запуске белый экран. WEB интерфейс работает. Хотелось решить эту проблему.

 

Комментарии

vadim352627

★✩✩✩✩✩✩
25 Янв 2025
24
28
@SoftFelix,
Спасибо! Давно хотел такое сделать, но не получалось. Буду пробовать с фоторезистором 5539.

Да, по идее после каждого изменения настройки должно выполняться db.update();, точно скажу позже

@SoftFelix, Работает, но единственная проблема как я понимаю в частоте ШИМ, во время понижения яркости на экране заметны полосы, и они зависимо от частоты или медленные или быстрые. У вас есть такое?
 
  • Лойс +1
Реакции: SoftFelix

SoftFelix

★✩✩✩✩✩✩
16 Фев 2020
65
20
во время понижения яркости на экране заметны полосы, и они зависимо от частоты или медленные или быстрые. У вас есть такое?
Нет, у меня никаких полос. Яркость меняется плавно в оба направления. Какая частота микроконтроллера выбрана при компиляции? У меня 160МГц. Текстовые конфиги в main.cpp менялись? В настройках веб-итерфейса, какие числовые настройки получились для включения режима "ночь" и яркости экрана для этого режима?
 

vadim352627

★✩✩✩✩✩✩
25 Янв 2025
24
28
@SoftFelix, Поставил 160МГц, особо ничего не поменялось. Пробовал поменять "
частота ШИМ в Гц", но там эти линии или становились шире и медленнее, или быстрее но больше. А в браузере как то так примерно1748622996945.png
 

SoftFelix

★✩✩✩✩✩✩
16 Фев 2020
65
20
@vadim352627, дисплей какой? Как у меня в мессаге, или другой?
ШИМ я выбрал с минимальной частотой, т.к. на бОльшей появлялись какие-то тормоза, а 100Гц показали себя отлично. Изначально по умолчанию, насколько я помню, там было 1000 Гц.

Я ещё такую доработку сделал для дисплея 1.8' и там тоже всё плавно без полос. А полосы только в момент регулировки яркости? Когда в min установиться полос нет?

Попробуй поиграться с:

#define BRIGHT_CHANGE_STEP 20 // шаг изменения яркости (в отсчётах)

...в main.cpp.

Я бы видео заснял, но авто ИСО в телефоне не даёт нормально показать регулировку яркости.

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

Можно ещё покрутить:

unsigned long brightTimer = 20; // проверка и установка яркости каждые 20мс.

...но не делать меньше 20, а то начнёт Wi-Fi отваливаться.
 
Изменено:
  • Лойс +1
Реакции: vadim352627

Пьеро

✩✩✩✩✩✩✩
30 Апр 2025
9
1
@SoftFelix, Проверил на дисплее ILI9488, прошивку брал эту, плата LOLIN(WEMOS) D1 R2 & mini, частота 160МГц, Шим поставил 1000 Гц, на темных картинках, типа ночной город, при регулировке и на средней яркости видны небольшие полосы, на светлых все нормамльно
 
  • Лойс +1
Реакции: SoftFelix

vadim352627

★✩✩✩✩✩✩
25 Янв 2025
24
28
В общем я исправил и убрал линии данным способом:
  • Пин D1 идёт к одному концу резистора 100 Ом.
  • Из другой стороны резистора:
    • Идёт провод на LED пин дисплея
    • И туда же припаиваешь + ножку конденсатора
  • – ножку конденсатора припаиваешь к GND (рядом на дисплее или ESP).

И поставил PWM_FREQ 1000. И линии пропали полностью!
 
  • Лойс +1
Реакции: Пьеро и SoftFelix

SoftFelix

★✩✩✩✩✩✩
16 Фев 2020
65
20
@vadim352627, импульсы ШИМ пропустил через интегрирующую цепочку. Хотел так же сделать изначально, но и без ней у меня всё отлично заработало. И минимальная яркость сейчас выставляется? А какая ёмкость конденсатора?
 

vadim352627

★✩✩✩✩✩✩
25 Янв 2025
24
28
@SoftFelix, Вот с регулировкой минимальной яркостью не очень, заметил что на яркости в 50% уже экран практически тухнет. 100 мкФ 25V конденсатор.
 
Изменено:

SoftFelix

★✩✩✩✩✩✩
16 Фев 2020
65
20
100 мкФ 25V конденсатор.
Конденсатор ОЧЕНЬ большого номинала. Надо начать с 0.1мкФ.

заметил что на яркости в 50% уже экран практически тухнет
Потому что ШИМ сигнал не может зарядить цепь с такой дикой постоянной времени.
 
  • Лойс +1
Реакции: vadim352627

vadim352627

★✩✩✩✩✩✩
25 Янв 2025
24
28
@SoftFelix, Вот для себя выбрал или 4.7мкФ или два таких конденсатора, и результат тогда приемлемый, на фото не сильно будет видно я думаю. И экран тогда тухнет уже на 30%, а не 50%
 

vadim352627

★✩✩✩✩✩✩
25 Янв 2025
24
28
В общем при помощи чатгпт я оптимизировал код яркости экрана от @SoftFelix и изменил функционал, добавив два режима: Авто и ручной. В режиме "АВТО" экран меняет яркость в зависимости от света, автояркость работает как в телефоне. В ручном режиме можно самому ставить яркость, от 0% до 100%. У меня была проблема с линиями на экране при изменении яркости, и я их исправил этим способом:
  • Пин D1 идёт к одному концу резистора 100 Ом.
  • Из другой стороны резистора:
    • Идёт провод на LED пин дисплея
    • И туда же припаривается + ножку конденсатора 4.7мкФ (я использовал две штуки)
  • – ножку конденсатора припаиваешь к GND (рядом на дисплее или ESP).

Еще раз спасибо @SoftFelix за его код и работу.

brightness.h:
#pragma once
#include <Arduino.h>
#include "config.h"
#include "db.h"

#define LCD_BRIGHT_MAX 1023        // макс яркость подсветки дисплея (0...1023)
#define BRIGHT_THRESHOLD_HYSTER 50 // гистерезис (в отсчётах)
#define BRIGHT_CHANGE_STEP 10      // шаг изменения яркости (в отсчётах)

#define PWM_FREQ 1000    // частота ШИМ в Гц (100...40000)
#define PWM_RES 10       // разрядность ШИМ (4...16)
#define BACKLIGHT_PIN D1 // вывод ШИМ на подсветку TFT, Разрядность ШИМ 10 бит (0...1023), D1(ESP8266)-------->LED(TFT 4.0), отключить LED от +5В!!!
#define PHOTO_PIN A0     // вывод для подключения фоторезистора, 10 бит, (0...1023), 3.3V<---[PHOTO 5518]---A0---[10K]--->GND

extern byte LCD_BRIGHT;
extern int16_t LCD_BRIGHT_LEVEL;

void brightness_init()
{
    pinMode(BACKLIGHT_PIN, OUTPUT);
    analogWriteFreq(PWM_FREQ);
    analogWriteResolution(PWM_RES);
    analogWrite(BACKLIGHT_PIN, LCD_BRIGHT_MAX);

    LCD_BRIGHT = db[kk::bright_manual_auto];
}

void checkBrightness() {
  static int targetBright = 1023;

  // Обновляем время
  time_t nowSecs = time(nullptr) + AppState::timezoneOffset;
  localtime_r(&nowSecs, &AppState::timeinfo);
  int hour = AppState::timeinfo.tm_hour;

  // === Режимы
  int mode = db[kk::brightness_mode].toInt();

  if (mode == 0) {
    // Ручной
    LCD_BRIGHT = db[kk::bright_manual_auto];
    targetBright = map(LCD_BRIGHT, 0, 100, 100, 1023);  // фикс
  } else if (mode == 1) {
    // Авто
    int adc = analogRead(PHOTO_PIN);
    targetBright = map(adc, 0, 200, 150, 1023);
    targetBright = constrain(targetBright, 100, 1023);
  }

  // === Плавная коррекция
  if (abs(LCD_BRIGHT_LEVEL - targetBright) > BRIGHT_CHANGE_STEP) {
    if (LCD_BRIGHT_LEVEL < targetBright)
      LCD_BRIGHT_LEVEL += BRIGHT_CHANGE_STEP;
    else
      LCD_BRIGHT_LEVEL -= BRIGHT_CHANGE_STEP;
  } else {
    LCD_BRIGHT_LEVEL = targetBright;
  }

  analogWrite(BACKLIGHT_PIN, LCD_BRIGHT_LEVEL);
}


inline bool testTimer(unsigned long &dataTimer, unsigned long setTimer)
{
    if (millis() - dataTimer >= setTimer)
    {
        dataTimer = millis();
        return true;
    }
    return false;
}
db.h:
#pragma once
#include <GyverDBFile.h>
#include <LittleFS.h>
GyverDBFile db(&LittleFS, "settings.db");

enum kk : size_t {
    wifi_ssid,
    wifi_pass,
    kand_token,
    kand_secret,
    gen_query,
    gen_negative,
    gen_style,
    auto_gen,
    auto_prd,
    brightness_mode,
    bright_manual_auto
};

void db_init() {
    LittleFS.begin();
    db.begin();
    db.init(kk::wifi_ssid, "");
    db.init(kk::wifi_pass, "");
    db.init(kk::kand_token, "");
    db.init(kk::kand_secret, "");

    db.init(kk::gen_query, "");
    db.init(kk::gen_negative, "");
    db.init(kk::gen_style, 0);

    db.init(kk::auto_gen, 0);
    db.init(kk::auto_prd, 60);
    db.init(kk::brightness_mode, 1);     // авто по умолчанию
    db.init(kk::bright_manual_auto, 100); // макс яркость
}
settings.h:
#pragma once
#include <AutoOTA.h>
#include <SettingsGyver.h>

#include "config.h"
#include "db.h"
#include "gen.h"
#include "timer.h"
#include "brightness.h"
SettingsGyver sett("AI Фоторамка v" F_VERSION, &db);
sets::Timer gentmr;

AutoOTA ota(F_VERSION, "AlexGyver/AiFrame/main/project.json");

void init_tmr()
{
  int prd = db[kk::auto_prd];
  gentmr.setTime(0, max(prd, 60));
  if (db[kk::auto_gen].toBool())
    gentmr.startInterval();
  else
    gentmr.stop();
}

void build(sets::Builder &b)
{
  {
    sets::Group g(b, "Генерация");
    b.Select(kk::gen_style, "Стиль", gen.styles);
    b.Input(kk::gen_query, "Промт");
    b.Input(kk::gen_negative, "Исключить");
    b.Label(SH("status"), "Статус", gen.status);
    b.Button(SH("generate"), "Генерировать");
  }
  {
    sets::Group g(b, "Автогенерация");
    b.Switch(kk::auto_gen, "Включить");
    b.Time(kk::auto_prd, "Период");
  }
  {
    sets::Group g(b, "Настройки");
    {
      sets::Menu m(b, "WiFi");
      sets::Group g(b);
      b.Input(kk::wifi_ssid, "SSID");
      b.Pass(kk::wifi_pass, "Pass");
      b.Button(SH("wifi_save"), "Подключить");
    }
    {
      sets::Menu m(b, "API");
      sets::Group g(b);
      b.Input(kk::kand_token, "Token");
      b.Pass(kk::kand_secret, "Secret");
      b.Button(SH("api_save"), "Применить");
    }
    int mode = db[kk::brightness_mode].toInt();
    // === Режим ===
    b.Select(kk::brightness_mode, "Режим яркости", "Ручной;Авто;");

    // === Ручной режим ===
    if (mode == 0)
    {
      b.Slider(kk::bright_manual_auto, "Яркость", 0, 100, 1, "");
    }
  }

  if (b.Confirm("update"_h))
    ota.update();

  // actions
  if (b.build.isAction())
  {
    switch (b.build.id)
    {
    case SH("generate"):
      generate();
      init_tmr();
      break;
    case SH("wifi_save"):
      db.update();
      ESP.reset();
      break;
    case SH("api_save"):
      gen.setKey(db[kk::kand_token], db[kk::kand_secret]);
      db.update();
      break;
    case kk::auto_gen:
    case kk::auto_prd:
      init_tmr();
      break;
    case kk::brightness_mode:
      db.update();
      sett.reload();
      break;
    case kk::bright_manual_auto:
      LCD_BRIGHT = db[kk::bright_manual_auto];
      db.update();
      break;
    }
  }
}

void update(sets::Updater &u)
{
  u.update(SH("status"), gen.status);
  if (ota.hasUpdate())
    u.update("update"_h, "Доступно обновление. Обновить прошивку?");
}

void sett_init()
{
  sett.begin();
  sett.onBuild(build);
  sett.onUpdate(update);
  init_tmr();
}

void sett_tick()
{
  ota.tick();
  sett.tick();
  if (gentmr)
    generate();
}
и в main.cpp добавил в самом начале:

byte LCD_BRIGHT; // ручная яркость 0…100
int16_t LCD_BRIGHT_LEVEL = LCD_BRIGHT_MAX; // текущая фактическая яркость
unsigned long brightTimer = 30; // интервал проверки яркости
unsigned long brightTimerD = 0;


в setup() :

brightness_init();

и в loop() :

if (testTimer(brightTimerD, brightTimer)) checkBrightness();
 
  • Лойс +1
Реакции: Alex_48 и SoftFelix