Va salut !
Si inca un montaj cu Wemos D1 mini (sper ca nu v-am plictisit !). Un ceas cu termometru (DS18B20), cu display LCD 2x16, conectare la WiFi. Functioneaza perfect, de multa vreme.
//ceas cu termometru, ora iarna/vara
#ifdef ESP8266
#include
#else
#include
#endif
#include <Arduino.h> #include <OneWire.h> #include <DallasTemperature.h> #include <time.h> #include <LiquidCrystal_I2C.h>
// Constants
#define ONE_WIRE_BUS 0
#define WIFI_RETRY_LIMIT 15
#define WIFI_RETRY_DELAY 1000
#define BACKLIGHT_PIN D5
//#define NTP_REFRESH_INTERVAL 86400000 // 24 hours in milliseconds
#define NTP_REFRESH_INTERVAL 3600000 // 1 hour in milliseconds
unsigned long lastNTPsync = 0;
// Network credentials
const char* ssid = "your_ssid";
const char* password = "your_psw";
// NTP settings
const char* NTP_SERVER = "ro.pool.ntp.org";
const char* TZ_INFO = "EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00";
// Custom degree symbol for LCD
byte customChar[] = {
0x08, 0x14, 0x08, 0x07,
0x08, 0x08, 0x07, 0x00
};
// Global objects
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 columns, 2 rows
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Global variables
tm timeinfo;
time_t now;
long unsigned lastNTPtime;
unsigned long lastEntryTime;
String StrTempC;
// Add these variables to store previous values for comparison
int prevHour = -1;
int prevMin = -1;
int prevSec = -1;
int prevDay = -1;
int prevMonth = -1;
int prevWDay = -1;
String prevTemp = "";
String readDSTemperatureC() {
sensors.requestTemperatures();
float tempC = sensors.getTempCByIndex(0);
float fTempAfis = tempC;
String sTempToStr = "";
if (tempC == -127.00) {
Serial.println("Failed to read from DS18B20 sensor");
return "--";
} else {
Serial.print("Temperature Celsius: ");
Serial.println(tempC, 1);
}
// Format temperature string with sign and padding
if (tempC < 0.0) {
sTempToStr = "-";
fTempAfis *= -1;
} else {
sTempToStr = " ";
}
if (fTempAfis < 9.9) {
sTempToStr += " ";
}
return (sTempToStr + String(fTempAfis, 1));
}
bool connectToWiFi() {
WiFi.begin(ssid, password);
int incercari = 0;
while (WiFi.status() != WL_CONNECTED && incercari < WIFI_RETRY_LIMIT) {
delay(WIFI_RETRY_DELAY);
Serial.print(".");
lcd.setCursor(0, 1);
lcd.print(incercari + 1);
lcd.print(" / ");
lcd.print(WIFI_RETRY_LIMIT);
lcd.print(" ");
incercari++;
}
if (WiFi.status() == WL_CONNECTED) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi conectat !");
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP());
delay(2000);
return true;
}
return false;
}
bool getTimeReducedTraffic(int ms) {
uint32_t start = millis();
do {
time(&now);
localtime_r(&now, &timeinfo);
delay(10);
} while (((millis() - start) <= ms) && (timeinfo.tm_year < (2016 - 1900)));
if (timeinfo.tm_year <= (2016 - 1900))
return false;
Serial.print("Time Now: ");
Serial.println(now);
StrTempC = readDSTemperatureC();
return true;
}
void showTime(tm *localTime) {
char time_output[40];
bool timeChanged = false;
bool dateChanged = false;
bool tempChanged = false;
if (localTime->tm_hour >= 8 && localTime->tm_hour < 20) {
analogWrite(BACKLIGHT_PIN, 800); // Luminozitate mare
} else {
analogWrite(BACKLIGHT_PIN, 150); // Luminozitate redusă
}
// Only update time if it has changed
if (localTime->tm_hour != prevHour || localTime->tm_min != prevMin || localTime->tm_sec != prevSec) {
lcd.setCursor(0, 0);
sprintf(time_output, "%02d:%02d:%02d", localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
lcd.print(time_output);
prevHour = localTime->tm_hour;
prevMin = localTime->tm_min;
prevSec = localTime->tm_sec;
timeChanged = true;
// Clear day of week at midnight
if (localTime->tm_hour == 0 && localTime->tm_min == 0 && localTime->tm_sec == 0) {
lcd.setCursor(9, 1);
lcd.print(" ");
}
}
// Only update date if it has changed
if (localTime->tm_mday != prevDay || localTime->tm_mon != prevMonth) {
lcd.setCursor(0, 1);
sprintf(time_output, "%02d/%02d", localTime->tm_mday, localTime->tm_mon + 1);
lcd.print(time_output);
prevDay = localTime->tm_mday;
prevMonth = localTime->tm_mon;
dateChanged = true;
}
// Only update day of week if it has changed
if (localTime->tm_wday != prevWDay) {
char* dow = getDOW(localTime->tm_wday);
lcd.setCursor(8 + (8 - strlen(dow)), 1);
lcd.print(dow);
prevWDay = localTime->tm_wday;
}
// Only update temperature if it has changed
if (StrTempC != prevTemp) {
lcd.setCursor(10, 0);
lcd.print(StrTempC);
// Display degree symbol (only if temperature changed)
lcd.setCursor(15, 0);
lcd.write(0);
prevTemp = StrTempC;
tempChanged = true;
}
}
char * getDOW(uint8_t tm_wday) {
switch (tm_wday) {
case 1: return " Luni";
case 2: return " Marti";
case 3: return "Miercuri";
case 4: return " Joi";
case 5: return " Vineri";
case 6: return " Sambata";
case 0: return "Duminica";
default: return " Error ";
}
}
// Loop function to update temperature
unsigned long lastTempUpdate = 0;
const unsigned long TEMP_UPDATE_INTERVAL = 10000; // Update temperature every 10 seconds
void setup() {
// Initialize sensors and communication
sensors.begin();
Serial.begin(115200);
pinMode(BACKLIGHT_PIN, OUTPUT);
analogWriteRange(1023); // gamă PWM
// Initialize LCD
lcd.begin(4, 5); // SDA = D2, SCL = D1
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Conectare WiFi..");
// Connect to WiFi
if (!connectToWiFi()) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Eroare WiFi!");
lcd.setCursor(0, 1);
lcd.print(" Reconectare...");
delay(2000);
ESP.restart();
}
// Configure time
configTime(0, 0, NTP_SERVER);
setenv("TZ", TZ_INFO, 1);
// Get initial time
if (!getTimeReducedTraffic(30000)) { // Wait up to 30 seconds for initial time sync
Serial.println("Time not set");
ESP.restart();
}
// Display initial time
showTime(&timeinfo);
// Store time reference
lastNTPtime = time(&now);
lastEntryTime = millis();
// Create custom character for degree symbol
lcd.createChar(0, customChar);
// Initialize previous values
prevHour = -1;
prevMin = -1;
prevSec = -1;
prevDay = -1;
prevMonth = -1;
prevWDay = -1;
prevTemp = "";
lcd.home();
lcd.write(0);
lcd.clear();
}
void loop() {
unsigned long currentMillis = millis();
// 1. Re-sincronizare NTP (o dată pe oră)
if (currentMillis - lastNTPsync >= NTP_REFRESH_INTERVAL) {
Serial.println("[NTP] Re-sincronizare...");
configTime(0, 0, NTP_SERVER);
setenv("TZ", TZ_INFO, 1);
tzset();
// Nu folosim delay mare aici, getTime va rula în background
getTimeReducedTraffic(5000);
lastNTPsync = currentMillis;
}
// 2. Actualizare structură timp (fără contact NTP)
// Această funcție trebuie să ruleze des pentru a menține timeinfo actualizat
time(&now);
localtime_r(&now, &timeinfo);
// 3. Actualizare temperatură la intervalul definit (10 secunde)
if (currentMillis - lastTempUpdate >= TEMP_UPDATE_INTERVAL) {
StrTempC = readDSTemperatureC();
lastTempUpdate = currentMillis;
}
// 4. Actualizare afișaj DOAR când se schimbă secunda
// Aceasta elimină flicker-ul cauzat de scrierea repetată pe LCD
if (timeinfo.tm_sec != prevSec) {
showTime(&timeinfo);
// prevSec este actualizat deja în interiorul funcției showTime din PDF-ul tău
}
}
Niciun comentariu:
Trimiteți un comentariu