1
- // Weather icon credits: https://github.com/SeBassTian23/ESP32-WeatherDisplay/tree/master
1
+ // =============== HEADER SECTION ===============
2
2
3
- // base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
4
- // enable or disable GxEPD2_GFX base class
3
+ // E-paper weather clock v1 - Main code
4
+ // Uses GxEPD2 library for e-paper display control
5
+
6
+ // =============== CONFIGURATION ===============
7
+ // Enable/disable GxEPD2_GFX base class - uses ~1.2k more code
5
8
#define ENABLE_GxEPD2_GFX 0
6
9
7
10
#include < GxEPD2_3C.h>
@@ -197,23 +200,29 @@ BH1750 lightMeter(0x23); // Initalize light sensor
197
200
GxEPD2_3C<GxEPD2_420c_Z21, GxEPD2_420c_Z21::HEIGHT> display (GxEPD2_420c_Z21(/* CS=5*/ /* SS*/ D7, /* DC=*/ D1, /* RST=*/ D2, /* BUSY=*/ D3)); // 400x300, UC8276
198
201
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;
199
202
200
- // #define SEALEVELPRESSURE_HPA (1013.25)
201
- #define BATPIN A0 // battery voltage divider connection pin (1M Ohm with 104 Capacitor)
202
- #define DEBUG_PIN D6
203
- #define BATTERY_LEVEL_SAMPLING 4
204
- #define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
205
- int TIME_TO_SLEEP = 900 ;
206
-
207
- // battery related settings
208
- #define battType 3.6 // for ICR 4.2, for LFR 3.6
209
- #define battChangeThreshold 0.15
210
- #define battUpperLim 3.3 // for ICR or LiPo battery 4.19
211
- #define battHigh 3.4 // for ICR or LiPo battery 4.2
212
- #define battLow 2.9
213
-
214
- int nightFlag = 0 ; // preserves data in rtc memory from deep sleep loss
215
- float battLevel;
216
- bool DEBUG_MODE = false , BATTERY_CRITICAL = false ;
203
+ // =============== GLOBAL CONSTANTS ===============
204
+ // Hardware pins
205
+ #define BATPIN A0 // Battery voltage divider pin (1M Ohm with 104 Capacitor)
206
+ #define DEBUG_PIN D6 // Debug mode toggle pin
207
+
208
+ // Battery monitoring settings
209
+ #define BATTERY_LEVEL_SAMPLING 4 // Number of samples to average
210
+ #define battType 3.6 // Battery type voltage (ICR: 4.2, LFR: 3.6)
211
+ #define battChangeThreshold 0.15 // Threshold for battery level changes
212
+ #define battUpperLim 3.3 // Upper voltage limit
213
+ #define battHigh 3.4 // Ideal battery voltage threshold (ICR: 4.1, LFR: 3.4)
214
+ #define battLow 2.9 // Low battery threshold
215
+
216
+ // Sleep settings
217
+ #define uS_TO_S_FACTOR 1000000 // Micro seconds to seconds conversion
218
+ int TIME_TO_SLEEP = 900 ; // Default sleep time in seconds (15 mins)
219
+
220
+ // =============== GLOBAL VARIABLES ===============
221
+ // State variables
222
+ int nightFlag = 0 ; // Night mode state preserved across sleep
223
+ float battLevel; // Current battery level
224
+ bool DEBUG_MODE = false ; // Debug mode state
225
+ bool BATTERY_CRITICAL = false ; // Critical battery state
217
226
218
227
String jsonBuffer;
219
228
@@ -225,7 +234,8 @@ char monthName[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
225
234
226
235
int httpResponseCode;
227
236
228
- // takes samples based on BATTERY_LEVEL_SAMPLING, averages them and returns actual battery voltage
237
+ // =============== HELPER FUNCTIONS ===============
238
+ // Measures and returns the averaged battery voltage
229
239
float batteryLevel ()
230
240
{
231
241
uint32_t Vbatt = 0 ;
@@ -239,11 +249,23 @@ float batteryLevel()
239
249
return (Vbattf);
240
250
}
241
251
252
+ // Disables WiFi and reduces CPU frequency to save power
253
+ void turnOffWifi ()
254
+ {
255
+ WiFi.disconnect (true ); // Disconnect from the network
256
+ WiFi.mode (WIFI_OFF); // Switch WiFi off
257
+ setCpuFrequencyMhz (40 ); // Set CPU to 40MHz
258
+ delay (1 );
259
+ Serial.println (" WIFI OFF" );
260
+ }
261
+
242
262
// forward declaration
243
263
void tempPrint (byte offset = 0 );
244
264
265
+ // =============== MAIN SETUP AND LOOP ===============
245
266
void setup ()
246
267
{
268
+ setCpuFrequencyMhz (80 );
247
269
Serial.begin (115200 );
248
270
Serial.println (" Setup" );
249
271
pinMode (BATPIN, INPUT);
@@ -271,7 +293,28 @@ void setup()
271
293
}
272
294
nightFlag = pref.getBool (" nightFlag" , false );
273
295
274
- if (!BATTERY_CRITICAL)
296
+ if (lightMeter.begin (BH1750::ONE_TIME_HIGH_RES_MODE))
297
+ {
298
+ Serial.println (F (" BH1750 Advanced begin" ));
299
+ }
300
+ else
301
+ {
302
+ Serial.println (F (" Error initialising BH1750" ));
303
+ errMsg (" Error BH1750" );
304
+ while (1 )
305
+ ; // Runs forever
306
+ }
307
+ float lux = 0 ;
308
+ while (!lightMeter.measurementReady (true ))
309
+ {
310
+ yield ();
311
+ }
312
+ lux = lightMeter.readLightLevel (); // Get Lux value
313
+ Serial.print (" Light: " );
314
+ Serial.print (lux);
315
+ Serial.println (" lx" );
316
+
317
+ if (!BATTERY_CRITICAL && lux != 0 )
275
318
{
276
319
bool wifiConfigExist = pref.isKey (" ssid" );
277
320
if (!wifiConfigExist)
@@ -334,49 +377,31 @@ void setup()
334
377
;
335
378
}
336
379
}
337
- if (lightMeter.begin (BH1750::ONE_TIME_HIGH_RES_MODE))
338
- {
339
- Serial.println (F (" BH1750 Advanced begin" ));
340
- }
341
- else
342
- {
343
- Serial.println (F (" Error initialising BH1750" ));
344
- errMsg (" Error BH1750" );
345
- while (1 )
346
- ; // Runs forever
347
- }
348
- float lux = 0 ;
349
- while (!lightMeter.measurementReady (true ))
350
- {
351
- yield ();
352
- }
353
- lux = lightMeter.readLightLevel ();
354
- Serial.print (" Light: " );
355
- Serial.print (lux);
356
- Serial.println (" lx" );
357
380
358
- if (!rtc.begin ())
381
+ float hTempHold, lTempHold, tempBattLevel;
382
+
383
+ if (lux != 0 || DEBUG_MODE == true )
359
384
{
360
- Serial.println (" Couldn't find RTC" );
361
- errMsg (" Error RTC" );
362
- while (1 )
363
- ; // Runs forever
364
- }
365
- Serial.println (" RTC Ready" );
385
+ if (!rtc.begin ())
386
+ {
387
+ Serial.println (" Couldn't find RTC" );
388
+ errMsg (" Error RTC" );
389
+ while (1 )
390
+ ; // Runs forever
391
+ }
392
+ Serial.println (" RTC Ready" );
366
393
367
- DateTime now = rtc.now ();
394
+ DateTime now = rtc.now ();
368
395
369
- if ((now.hour () == 0 ) && (now.minute () >= 0 && now.minute () < 15 ))
370
- { // reset high low at midnight
371
- pref.putFloat (" hTemp" , 0.0 );
372
- pref.putFloat (" lTemp" , 60.0 );
373
- }
396
+ if ((now.hour () == 0 ) && (now.minute () >= 0 && now.minute () < 15 ))
397
+ { // reset high low at midnight
398
+ pref.putFloat (" hTemp" , 0.0 );
399
+ pref.putFloat (" lTemp" , 60.0 );
400
+ }
374
401
375
- if (lux != 0 || DEBUG_MODE == true )
376
- {
377
402
if (sensor.begin () == true ) // Function to check if the sensor will correctly self-identify with the proper Device ID/Address
378
403
{
379
- Serial.println (" Lux Begin" );
404
+ Serial.println (" TMP117 Begin" );
380
405
}
381
406
else
382
407
{
@@ -429,12 +454,7 @@ void setup()
429
454
customApiKey = pref.getString (" apiCustom" , " " );
430
455
}
431
456
else
432
- {
433
- // wifioff cpu speed reduced
434
- WiFi.disconnect (true ); // Disconnect from the network
435
- WiFi.mode (WIFI_OFF); // Switch WiFi off
436
- setCpuFrequencyMhz (40 );
437
- }
457
+ turnOffWifi (); // wifioff cpu speed reduced
438
458
439
459
hTemp = pref.getFloat (" hTemp" , -1.0 );
440
460
lTemp = pref.getFloat (" lTemp" , -1.0 );
@@ -446,8 +466,9 @@ void setup()
446
466
pref.putFloat (" lTemp" , 60.0 );
447
467
pref.putFloat (" battLevel" , battType);
448
468
}
469
+
470
+ hTempHold = hTemp, lTempHold = lTemp, tempBattLevel = battLevel;
449
471
}
450
- float hTempHold = hTemp, lTempHold = lTemp, tempBattLevel = battLevel;
451
472
bool tempNightFlag = nightFlag;
452
473
453
474
Serial.println (" Setup done" );
@@ -494,7 +515,8 @@ void setup()
494
515
}
495
516
else
496
517
{
497
- Serial.println (" Time" );
518
+ turnOffWifi (); // turn off wifi if not connected
519
+ Serial.println (" Time Only" );
498
520
display.drawBitmap (270 , 0 , wifiOff, 12 , 12 , GxEPD_BLACK);
499
521
tempPrint (40 );
500
522
Serial.println (" Time Done" );
@@ -522,19 +544,24 @@ void setup()
522
544
523
545
Serial.println (" Data Write Done" );
524
546
pref.end ();
525
- esp_sleep_enable_timer_wakeup (TIME_TO_SLEEP * uS_TO_S_FACTOR);
526
547
Serial.println (" Setup ESP32 to sleep for every " + String (TIME_TO_SLEEP / 60 ) + " Mins" );
548
+
549
+ // Disable peripherals
550
+ Wire.end ();
551
+ esp_sleep_enable_timer_wakeup (TIME_TO_SLEEP * uS_TO_S_FACTOR);
527
552
// Go to sleep now
528
553
Serial.println (" Going to sleep now" );
529
554
Serial.flush ();
530
- delay (100 );
555
+ delay (10 );
556
+ // Enter deep sleep
531
557
esp_deep_sleep_start ();
532
558
}
533
559
}
534
560
535
561
void loop () {}
536
562
537
- // Handles the httpresponse and returns the data as json payload
563
+ // =============== WEATHER AND DISPLAY FUNCTIONS ===============
564
+ // Fetches weather data from API and returns JSON response
538
565
String weatherDataAPI (const char *serverName)
539
566
{
540
567
WiFiClient client;
@@ -920,6 +947,9 @@ void weatherPrint()
920
947
u8g2Fonts.print (s);
921
948
}
922
949
}
950
+
951
+ // Turn off WiFi as soon as possible after data fetch
952
+ turnOffWifi ();
923
953
}
924
954
925
955
// UNCOMMENT BELOW FUNCTION IF YOU WISH TO USE ONLY oPENwEATHERmAP API
@@ -1104,8 +1134,11 @@ void weatherPrint()
1104
1134
u8g2Fonts.print(s);
1105
1135
}
1106
1136
}
1137
+ // Turn off WiFi as soon as possible after data fetch
1138
+ turnOffWifi();
1107
1139
}*/
1108
1140
1141
+ // =============== UI HELPER FUNCTIONS ===============
1109
1142
// In case of api failure, it displays network info for debugging
1110
1143
void networkInfo ()
1111
1144
{
0 commit comments