Ретро часы на ESP32

Ретро часы на ESP32 содержать четыре индикатора тлеющего разряда ИН-14 и два индикатора ИН-16. Индикаторы ИН-14 используются для индикации часов и минут, а ИН-16 для секунд. Возможно использование других индикаторов тлеющего разряда. Часы помимо индикаторов содержат стабилизатор 5 В (7805), повышающий преобразователь на 180 В (IRF840), шесть транзисторных оптопар (TLP627), дешифратор (К155ИД1) и плату ESP32. Сами часы работают от напряжения 12 В (можно от 9 В), стабилизатор на 5 В необходим для питания платы ESP32 и дешифратора.

Повышающий преобразователь работает на частоте 25 кГц и управляется микроконтроллером ESP32. С выхода D15 микроконтроллера сигнал ШИМ уровня 3,3 В подается на базу транзистора BC547 который работает в ключевом режиме. Далее с коллектора ШИМ (уровень сигнала 12 В) сигнал подается на затвор MOSFET транзистора IRF840.

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

На выходе повышающего преобразователя установлен индикатор ИН-3, который сигнализирует о наличии высокого напряжения. Выходное напряжение преобразователя настраивается программно, путем изменения длительности импульса сигнала ШИМ.

Индикация часов динамическая, в ее состав входит К155ИД1, который представляет собой двоично-десятичный дешифpатоp с высоковольтным выходом. Выходы дешифратора напрямую управляют работой всех катодов индикаторных ламп. Управление анодами индикаторов осуществляется при помощи шести транзисторных оптопар.

Плата управления ESP32 DevKit v1 Wi-Fi Bluetooth ESP32-WROOM-32 поддерживает динамическую индикацию и управление ШИМ сигналом. Дополнительно ESP32 используется для получения точного времени NTP.

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

Так как часам для подключения к NTP-серверу необходим Интернет, то плата ESP32 при авторизации в Wi-Fi сети будет работать как точка доступа, а в режиме синхронизации времени как Веб-сервер.

Для авторизации в сети Wi-Fi переводится в режим точки доступа с фиксированным IP адресом — 192.168.4.1 , для перевода ESP32 в режим точки доступа необходимо на пин D23 подать GND (нажать фиксированную кнопку AT/STA) и нажать кнопку RESET (или отключить и снова включить питание).

Далее необходимо подключится к точке доступа ESPap, ввести пароль — 12345678.

Далее в браузере в адресной строке указать адрес дочки доступа http://192.168.4.1

После как указали имя и пароль Вашей Wi-Fi сети, нажмите на кнопку «Сохранить настройки» , в энергонезависимую память будут сохранены параметры Вашей Wi-Fi сети, после чего появится сообщение:

Удалите перемычку с D23 (отжать кнопку AT/STA), отключитесь от сети ESPap, перезагрузите ESP32, подключитесь к Вашей сети Wi-Fi.

В браузере в адресной строке укажите IP адрес 192.168.1.33 (пример)

Часы содержат следующие функциональные возможности:

  • Изменение временного сдвига от UTC (Москва находится в часовом поясе UTC+3)
  • Установка яркости свечения индикаторов в дневное время
  • Установка яркости свечения индикаторов в ночное время
  • Установка интервала ночного времени работы часов
  • Антиотравление катодов индикаторов тлеющего разряда (ровно в 30 минут каждого часа происходит перебор всех цифр)

Перед загрузкой скетча рекомендую ознакомится со статьей  — ESP32 DevKit v1 Wi-Fi Bluetooth ESP32-WROOM-32 (Arduino IDE).

#define ID1 2
#define ID2 4
#define ID4 16
#define ID8 17
 
#define IN1 25
#define IN2 26
#define IN3 27
#define IN4 14
#define IN5 12
#define IN6 13
 
#include <WiFi.h>
#include <NTPClient.h>         // http://rcl-radio.ru/wp-content/uploads/2019/11/ntpclientmaster.zip
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <EEPROM.h>
#include "esp_system.h"
 
#ifndef APSSID
#define APSSID "ESPap"
#define APPSK  "12345678"
#endif
 
  const char *ssid = APSSID;
  const char *password = APPSK;
  WebServer server(80);
  WiFiUDP ntpUDP;
  /////////////////  https://www.ntppool.org/zone/@ - другие сервера  /////////////////////////////
  ///////////////// для России - ru.pool.ntp.org //////////////////////////////////////////////////
  NTPClient timeClient(ntpUDP, "pool.ntp.org", 21600,3600123);// 21600 - временной сдвиг в секундах от UTC 
 
  int ss,mm,hh,i,an,segm,brignes,brignes_low, end_night,start_night;
  long a[6];
  unsigned long times, sum, times1;
  byte len_ssid, len_pass;
  int w,ip1,ip2,ip3,ip4,utc;
  hw_timer_t * timer = NULL;
  volatile SemaphoreHandle_t timerSemaphore;
  portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
 
 
void IRAM_ATTR onTimer() {
      portENTER_CRITICAL_ISR(&timerMux);
  switch(i){
     case 0: an=10;anod();delayMicroseconds(2000);segm=a[0]; an=0; segment();anod();break;
     case 1: an=10;anod();delayMicroseconds(2000);segm=a[1]; an=1; segment();anod();break;
     case 2: an=10;anod();delayMicroseconds(2000);segm=a[2]; an=2; segment();anod();break;
     case 3: an=10;anod();delayMicroseconds(2000);segm=a[3]; an=3; segment();anod();break;
     case 4: an=10;anod();delayMicroseconds(2000);segm=a[4]; an=4; segment();anod();break;
     case 5: an=10;anod();delayMicroseconds(2000);segm=a[5]; an=5; segment();anod();break;
}
    i++;if(i>5){i=0;}
    portEXIT_CRITICAL_ISR(&timerMux);
    xSemaphoreGiveFromISR(timerSemaphore, NULL);
}
 
 
 
void setup(){ 
  timerSemaphore = xSemaphoreCreateBinary();
//////// GPIO ///////////////  
  pinMode(15,OUTPUT); 
  pinMode(23,INPUT_PULLUP);// D23 
  digitalWrite(15,HIGH);
  Serial.begin(9600);
//////// AP /////////////////
  if(digitalRead(23)==LOW){
  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.on("/", handleRoot);
  server.on("/ok", handleOk);
  server.begin();
  Serial.println("HTTP server started");  
}
  else{
//////// STA ///////////////
  WiFi.mode( WIFI_STA);
  EEPROM.begin(512);
  len_ssid = EEPROM.read(96);
  len_pass = EEPROM.read(97);
  utc = EEPROM.read(201);
  brignes = EEPROM.read(200);
  brignes_low = EEPROM.read(202);
  start_night = EEPROM.read(203);
  end_night = EEPROM.read(204);
  if(brignes > 150){brignes=150;} 
  if(brignes_low > 150){brignes_low=150;} 
  if(len_pass > 64) len_pass = 0;
/////// READ EEPROM
  unsigned char* buf_ssid = new unsigned char[32];
  unsigned char* buf_pass = new unsigned char[64];
 for(byte i = 0; i < len_ssid; i++) buf_ssid[i] = char(EEPROM.read(i));
  buf_ssid[len_ssid] = '\x0';
  const char *ssid  = (const char*)buf_ssid;
 for(byte i = 0; i < len_pass; i++) buf_pass[i] = char(EEPROM.read(i + 32));
  const char *pass  = (const char*)buf_pass;
  buf_pass[len_pass] = '\x0';
  delay(2000);
  Serial.print("SSID: ");Serial.print(ssid);Serial.print("   ");Serial.print("Password: ");Serial.println(pass);
/////// connection       
  WiFi.begin(ssid, pass);
 while (WiFi.status() != WL_CONNECTED){delay (10);Serial.print (".");digitalWrite(15,HIGH);}
  Serial.println();Serial.print("Connected to ");Serial.println(ssid);Serial.print("IP address: ");Serial.println(WiFi.localIP());
   ip1 = WiFi.localIP()[0];
   ip2 = WiFi.localIP()[1];
   ip3 = WiFi.localIP()[2];
   ip4 = WiFi.localIP()[3];
  server.begin();
  server.on("/", web);
  server.on("/reset", web0);    
}
 
///////// PWM /////////////////////////  
  ledcSetup(2, 25000, 8); // 25000 kHz / 8 bit / cannel 1
  ledcAttachPin(15, 2);   // D15 / cannel 1
  ledcWrite(2, 255-brignes);  
///////// TIMER 3 /////////////////////
  timer = timerBegin(3, 8000, true);
  timerAttachInterrupt(timer, &onTimer, false);
  timerAlarmWrite(timer, 35, true);
  timerAlarmEnable(timer);    
///////////////////////////////////////  
  pinMode(IN1,OUTPUT);pinMode(IN2,OUTPUT);pinMode(IN3,OUTPUT); pinMode(IN4,OUTPUT); pinMode(IN5,OUTPUT); 
  pinMode(IN6,OUTPUT); pinMode(ID1,OUTPUT); pinMode(ID2,OUTPUT); pinMode(ID4,OUTPUT); pinMode(ID8,OUTPUT); 
  timeClient.setTimeOffset(utc*1800);     
}
 
 
void loop(){
  delay(1000);
  server.handleClient();
 if(digitalRead(23)==HIGH){
/////////////// times ////////////////////////////
  if(millis()-times>=1000){times=millis();
   while(!timeClient.update()){timeClient.forceUpdate();}
   hh = timeClient.getHours();
   mm = timeClient.getMinutes();
   ss = timeClient.getSeconds();
   Serial.print(hh/10);Serial.print(hh%10);Serial.print(":");Serial.print(mm/10);Serial.print(mm%10);Serial.print(":");Serial.print(ss/10);Serial.println(ss%10);
///// brightness  
 
   if(hh>=0&&hh<=end_night||hh>=start_night){ledcWrite(2, 255-brignes_low); }else {ledcWrite(2, 255-brignes);}
}
  sum = hh*10000+mm*100+ss;
///////// ///////////////  
 if(mm==30&&ss<10){
  switch(ss){
    case 0: sum=000000;break;
    case 1: sum=111111;break;
    case 2: sum=222222;break;
    case 3: sum=333333;break;
    case 4: sum=444444;break;
    case 5: sum=555555;break;
    case 6: sum=666666;break;
    case 7: sum=777777;break;
    case 8: sum=888888;break;
    case 9: sum=999999;break;}}
 
  a[0]=sum/100000;
  a[1]=sum/10000%10;
  a[2]=sum/1000%10;
  a[3]=sum/100%10;
  a[4]=sum/10%10;
  a[5]=sum%10;
 
   }
 
}// loop
 
void segment(){
  switch(segm){                                                                 
    case 0: digitalWrite(ID8,LOW);digitalWrite(ID4,LOW);digitalWrite(ID2,LOW);digitalWrite(ID1,LOW);break;     // DEC 0 = 0b0000
    case 1: digitalWrite(ID8,LOW);digitalWrite(ID4,LOW);digitalWrite(ID2,LOW);digitalWrite(ID1,HIGH);break;    // DEC 1 = 0b0001
    case 2: digitalWrite(ID8,LOW);digitalWrite(ID4,LOW);digitalWrite(ID2,HIGH);digitalWrite(ID1,LOW);break;    // DEC 2 = 0b0010
    case 3: digitalWrite(ID8,LOW);digitalWrite(ID4,LOW);digitalWrite(ID2,HIGH);digitalWrite(ID1,HIGH);break;   // DEC 3 = 0b0011
    case 4: digitalWrite(ID8,LOW);digitalWrite(ID4,HIGH);digitalWrite(ID2,LOW);digitalWrite(ID1,LOW);break;    // DEC 4 = 0b0100
    case 5: digitalWrite(ID8,LOW);digitalWrite(ID4,HIGH);digitalWrite(ID2,LOW);digitalWrite(ID1,HIGH);break;   // DEC 5 = 0b0101
    case 6: digitalWrite(ID8,LOW);digitalWrite(ID4,HIGH);digitalWrite(ID2,HIGH);digitalWrite(ID1,LOW);break;   // DEC 6 = 0b0110
    case 7: digitalWrite(ID8,LOW);digitalWrite(ID4,HIGH);digitalWrite(ID2,HIGH);digitalWrite(ID1,HIGH);break;  // DEC 7 = 0b0111
    case 8: digitalWrite(ID8,HIGH);digitalWrite(ID4,LOW);digitalWrite(ID2,LOW);digitalWrite(ID1,LOW);break;    // DEC 8 = 0b1000
    case 9: digitalWrite(ID8,HIGH);digitalWrite(ID4,LOW);digitalWrite(ID2,LOW);digitalWrite(ID1,HIGH);break;   // DEC 9 = 0b1001
    case 10:digitalWrite(ID8,HIGH);digitalWrite(ID4,HIGH);digitalWrite(ID2,HIGH);digitalWrite(ID1,HIGH);break; // Пусто = 0b1111
 
  }}
 
 
void anod(){
  switch(an){                                                             
    case 0: digitalWrite(IN1,HIGH);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,LOW);digitalWrite(IN5,LOW);digitalWrite(IN6,LOW);break;    
    case 1: digitalWrite(IN1,LOW);digitalWrite(IN2,HIGH);digitalWrite(IN3,LOW);digitalWrite(IN4,LOW);digitalWrite(IN5,LOW);digitalWrite(IN6,LOW);break;   
    case 2: digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,HIGH);digitalWrite(IN4,LOW);digitalWrite(IN5,LOW);digitalWrite(IN6,LOW);break;   
    case 3: digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,HIGH);digitalWrite(IN5,LOW);digitalWrite(IN6,LOW);break;
    case 4: digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,LOW);digitalWrite(IN5,HIGH);digitalWrite(IN6,LOW);break;   
    case 5: digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,LOW);digitalWrite(IN5,LOW);digitalWrite(IN6,HIGH);break;
    case 10:digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,LOW);digitalWrite(IN5,LOW);digitalWrite(IN6,LOW);break;   
  }}
 
void web(){ 
          timerAlarmWrite(timer, 35, false);
          delay(300);
   String webPage = "<meta charset='utf-8'><meta name='viewport' content='width=480, user-scalable=no' />";
   //style
          webPage += "<head><style>.tab1 {background-color:#F5F5F5;border-radius: 5px;margin: auto;}";
          webPage += "#menu1{list-style:none; width:100%; padding:0 0 0 0 ; margin: 0 0 0 0;background: #999;}";
          webPage += "#menu1 li{float:left; font:bold 14px Arial;text-shadow: 1px 1px 0px #000;}";
          webPage += "#menu1 a{color:#fff; display:block; height:36px; line-height:36px; padding:10px 10px 10px 10px; background:#4682B4; text-decoration:none;}";
          webPage += "#menu1 a:hover{color:#fff; background:#555;}";
          webPage += "#menu1 b{color:#fff; display:block; height:25px; line-height:36px; padding:10px 10px 10px 10px; background:#4682B4; text-decoration:none;}";
          webPage += "</style></head>";
    /////////////   
          webPage += "<TABLE class='tab1' align='center' width='470' BORDER='1' cellspacing='0' cellpadding='5'>";
          webPage +="<td colspan='2'><h1><center>ESP32<br>Страница настройки Интернет часов</h1>";
          webPage +="<tr><td colspan='2'><center><big>Текущее время: ";         
          webPage += hh/10;webPage += hh%10; webPage +=":";webPage +=mm/10;
          webPage += mm%10; webPage +=":";webPage +=ss/10;webPage += ss%10;
          webPage += "</center>";
          webPage += "<form method='POST' action='reset' >";
          webPage += "<tr><td colspan='2'><input name='time_utc'  autocomplete='off' maxlength='3' size='1'> Временной сдвиг UTC (30 мин)";
          webPage += "<br><small>Установлено: ";EEPROM.begin(512);webPage += EEPROM.read(201);
          webPage += " (";webPage += utc*0.5;webPage += " ч.)";
          webPage += "<tr><td><input name='brignes'  autocomplete='off' maxlength='3' size='1'> Яркость день 0-150";
          webPage += "<br><small>Установлено: ";EEPROM.begin(512);webPage += EEPROM.read(200);
          webPage += "<td><input name='brignes_low'  autocomplete='off' maxlength='3' size='1'> Яркость ночь 0-150";
          webPage += "<br><small>Установлено: ";EEPROM.begin(512);webPage += EEPROM.read(202);
          webPage += "<tr><td colspan='2'><center> Время работы ночного режима подсветки <tr>";
          webPage += "<tr><td> Начало (18-23 ч) <input name='start_night'  autocomplete='off' maxlength='3' size='1'>";
          webPage += "<br><small>Установлено: ";EEPROM.begin(512);webPage += EEPROM.read(203);
          webPage += "<td> Конец: (1-12 ч) <input name='end_night'  autocomplete='off' maxlength='3' size='1'>";
          webPage += "<br><small>Установлено: ";EEPROM.begin(512);webPage += EEPROM.read(204);
 
 
          webPage += "<tr><td colspan='2'><center><br><input type=SUBMIT value='Сохранить настройки'>";
          webPage += "</form>";
          webPage += "<center><br>Заполните все ячейки формы, незаполненная ячейка формы не изменит ранее установленный параметр";
 
          server.send(200, "text/html", webPage);
          timerAlarmWrite(timer, 35, true);
          timerAlarmEnable(timer); 
 
}
 
void sumbit(){ 
     if (server.args() > 0 ) {
   for ( uint8_t i = 0; i < server.args(); i++ ) {
     if (server.argName(i) == "brignes"){brignes = server.arg(i).toInt();}
     if (server.argName(i) == "time_utc"){utc = server.arg(i).toInt();}
     if (server.argName(i) == "brignes_low"){brignes_low = server.arg(i).toInt();}
     if (server.argName(i) == "start_night"){start_night = server.arg(i).toInt();}
     if (server.argName(i) == "end_night"){end_night = server.arg(i).toInt();}
 
  }
    Serial.println("Save");
    if(brignes > 150){brignes=150;} if(brignes < 0){brignes=0;}
    if(brignes_low > 150){brignes_low=150;} if(brignes_low < 0){brignes_low=0;}
 
    if(brignes==NULL){}else{EEPROM.write(200,brignes);}
    if(utc==NULL){}else{EEPROM.write(201,utc);}
    if(brignes_low==NULL){}else{EEPROM.write(202,brignes_low);}
    if(start_night==NULL){}else{EEPROM.write(203,start_night);}
    if(end_night==NULL){}else{EEPROM.write(204,end_night);}
 
    EEPROM.commit();
    EEPROM.end(); 
    EEPROM.begin(512);
    brignes = EEPROM.read(200); 
    utc = EEPROM.read(201);
    brignes_low = EEPROM.read(202);
    start_night = EEPROM.read(203);
    end_night = EEPROM.read(204); 
    timeClient.setTimeOffset(utc*1800);
    if(hh>=0&&hh<=6||hh>=23){ledcWrite(2, 255-brignes_low);}else {ledcWrite(2, 255-brignes);}
}}  
 
void handleRoot() { 
   timerAlarmWrite(timer, 35, false);
   delay(300);
   String str = "<meta charset='utf-8'><meta name='viewport' content='width=480, user-scalable=no' />";
   //style
          str += "<head><style>.tab1 {background-color:#F5F5F5;border-radius: 5px;margin: auto;}";
          str += "#menu1{list-style:none; width:100%; padding:0 0 0 0 ; margin: 0 0 0 0;background: #999;}";
          str += "#menu1 li{float:left; font:bold 14px Arial;text-shadow: 1px 1px 0px #000;}";
          str += "#menu1 a{color:#fff; display:block; height:36px; line-height:36px; padding:10px 10px 10px 10px; background:#4682B4; text-decoration:none;}";
          str += "#menu1 a:hover{color:#fff; background:#555;}";
          str += "#menu1 b{color:#fff; display:block; height:25px; line-height:36px; padding:10px 10px 10px 10px; background:#4682B4; text-decoration:none;}";
          str += "</style></head>";
   ////////////       
          str += "<TABLE class='tab1' align='center' width='470' BORDER='1' cellspacing='0' cellpadding='10'>";
          str +="<td><h1><center>ESP32<br>Авторизация</h1>";
          str += "<form method='POST' action='ok'>";
          str += "<tr><td><input name='ssid'  autocomplete='off'><big> Имя Wi-Fi сети";
          str += "<tr><td><input name='pswd'  autocomplete='off'><big> Пароль";
          str += "<tr><td><center><input type=SUBMIT value='Сохранить настройки'>";
          str += "</form>";
          server.send ( 200, "text/html", str );
          timerAlarmWrite(timer, 35, true);
          timerAlarmEnable(timer); 
}      
 
void handleOk(){
  timerAlarmWrite(timer, 35, false);
  delay(300);
  String ssid_ap;
  String pass_ap;
  unsigned char* buf = new unsigned char[64];
 
  String str = "<meta charset='utf-8'><meta name='viewport' content='width=480, user-scalable=no' />";;
  str += "<body>";
 
  EEPROM.begin(512);
 
  ssid_ap = server.arg(0);
  pass_ap = server.arg(1);
 
  if(ssid_ap != ""){
    EEPROM.write(96,ssid_ap.length());
    EEPROM.write(97,pass_ap.length());
    ssid_ap.getBytes(buf, ssid_ap.length() + 1);
    for(byte i = 0; i < ssid_ap.length(); i++)
    EEPROM.write(i, buf[i]); 
    pass_ap.getBytes(buf, pass_ap.length() + 1);
    for(byte i = 0; i < pass_ap.length(); i++)
    EEPROM.write(i + 32, buf[i]);
    EEPROM.commit();
    EEPROM.end(); 
 
  const char *ast_ssid_ap = ssid_ap.c_str();
  const char *ast_pass_ap = pass_ap.c_str();
    /////////////////////////
    WiFi.begin(ast_ssid_ap, ast_pass_ap);
      // Wait for connection
    while (WiFi.status() != WL_CONNECTED){delay (10);Serial.print (".");}
 ///////////////////////////////////////////////////////////////////////////  
    str +="<big><center>Конфигурация сохранена в память<br>";
    str +="<big><center>Уберите перемычку с D23 и перезагрузите ESP32</p><br>";
    str +="<big><b><center>";
    str += WiFi.localIP().toString();
    str +="</b><hr>";
    str +="<a href=\"/\">Return</a> to settings page</br>";
  }
  else {
    str += "<big><center>No WIFI Net</br>\
   <a href=\"/\">Return</a> to settings page</br>";
  }
  str += "</body></html>";
  server.send ( 200, "text/html", str );
  timerAlarmWrite(timer, 35, true);
  timerAlarmEnable(timer); 
}
 
 
void web0() { 
   timerAlarmWrite(timer, 35, false);
   delay(300);
   String str0 = "<meta charset='utf-8'><meta name='viewport' content='width=480, user-scalable=no' />";
          str0 += "<center><b><big>Настройки сохранены.<br> Для возврата на предыдущую страницу перейдите по <a href='./'>ссылке</a>";
   server.send (200, "text/html", str0);
   sumbit();
   timerAlarmWrite(timer, 35, true);
   timerAlarmEnable(timer); 
}

При прошивке ESP32 необходимо отключать питание 12 В


Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=3367#p3367

Доработка № 1

Добавление в меню режима антиотравления катодов, перебор цифр 1-4 раза в час, отключение.

Скетч — http://forum.rcl-radio.ru/viewtopic.php?pid=3370#p3370

Доработка № 2

Вывод на индикаторы даты и месяца (в течении 4 секунд каждую минуту в 30 секунд), активация режима в меню.

Скетч — http://forum.rcl-radio.ru/viewtopic.php?pid=3371#p3371

Доработка № 3

Добавлено два будильника, будильник работает в нескольких режимах: по будням, по выходным, каждый день, выключено. Добавлена кнопка отключения сигнала будильника.

Скетч — http://forum.rcl-radio.ru/viewtopic.php?pid=3373#p3373

Добавить комментарий

Войти с помощью: