-
Notifications
You must be signed in to change notification settings - Fork 0
/
esp32-arduino.ino
682 lines (609 loc) · 24.5 KB
/
esp32-arduino.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
// Author: M. S. S. Weerasinghe
// Title: Smart Medicine Box
// Include the required libraries
#include <Wire.h> // For I2C communication
#include <Adafruit_GFX.h> // For the OLED display
#include <Adafruit_SSD1306.h> // For the OLED display
#include <DHTesp.h> // For the DHT sensor
#include <WiFi.h> // For the WiFi communication
#include <PubSubClient.h> // For the MQTT communication
#include <ESP32Servo.h> // For the servo motor
// Define constants for the OLED display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // shares reset pin of ESP32
#define SCREEN_ADDRESS 0x3C // I2C address
// Define constants for the hardware pins
#define DHT_PIN 12
#define LED 18
#define BUZZER 19
#define UP_BUTTON 26
#define DOWN_BUTTON 25
#define OK_BUTTON 27
#define CANCEL_BUTTON 33
#define SERVO_PIN 32
#define LDR_RIGHT 34
#define LDR_LEFT 35
// Define MQTT topics
#define TEMPERATURE_TOPIC "medibox-210690B-temperature"
#define HUMIDITY_TOPIC "medibox-210690B-humidity"
#define ALARM_ON_TOPIC "medibox-210690B-alarm-on"
#define ALARM_ON_GET_TOPIC "medibox-210690B-alarm-on-get"
#define ALARM_1_TIME_TOPIC "medibox-210690B-alarm-1-time"
#define ALARM_2_TIME_TOPIC "medibox-210690B-alarm-2-time"
#define ALARM_3_TIME_TOPIC "medibox-210690B-alarm-3-time"
#define ALARM_1_TIME_GET_TOPIC "medibox-210690B-alarm-1-time-get"
#define ALARM_2_TIME_GET_TOPIC "medibox-210690B-alarm-2-time-get"
#define ALARM_3_TIME_GET_TOPIC "medibox-210690B-alarm-3-time-get"
#define LIGHT_LEFT_TOPIC "medibox-210690B-light-left"
#define LIGHT_RIGHT_TOPIC "medibox-210690B-light-right"
#define MOTOR_ANGLE_TOPIC "medibox-210690B-motor-angle"
// Create an instances of the required libraries
DHTesp dht; // DHT sensor
Servo servo; // Servo motor
WiFiClient espClient; // WiFi client
PubSubClient mqttClient(espClient); // MQTT client
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // OLED display
// Define global variables
int utcOffset = 0; // UTC offset
int dstOffset = 0; // Daylight saving time offset
int milliTimenow = 0; // Milliseconds since the program started
int initmilliseconds = 0; // Time, the program started in milliseconds
int timenow[3] = {0, 0, 0}; // Current time in hours, minutes, and seconds
const int buzzerToneCount = 6; // Number of buzzer tones
int buzzerTones[buzzerToneCount] = {262, 294, 330, 349, 392, 440}; // Buzzer tones
float humidity, newHumidity, temperature, newTemperature; // For the DHT sensor
int leftLight, rightLight, newLeftLight, newRightLight; // For the LDR sensors
// Strings to store the values for the MQTT communication
char temperatureStr[6], humidityStr[6], timeInMillisStr[10], lightLeftStr[6], lightRightStr[6];
// Variables to configure the alarms
bool alarmsEnabled = true;
const int alarmCount = 3; // Number of alarms that can be set
int alarmTimes[alarmCount][2] = {{0, 1}, {1, 0}, {2, 0}}; // Alarm times in hours and minutes
int currentAlarmOption = 0; // Current selected alarm option
bool alarmRingingFinished[alarmCount] = {false, false, false}; // Alarm ringing status
// Variables to configure the menu
const int menuOptionCount = 3; // Number of menu options
String menuOptions[menuOptionCount] = {"Set Time Zone", "Set Alarm", "Enable/Disable Alarms"}; // Menu options
int currentMenuOption = 0; // Current selected menu option
void setup() {
// Start the serial communication
Serial.begin(115200);
// Initialize the OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
// If the display cannot be initialized, print an error message
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Loop indefinitely
}
// Initialize the hardware pins
pinMode(LED, OUTPUT);
pinMode(BUZZER, OUTPUT);
pinMode(UP_BUTTON, INPUT);
pinMode(DOWN_BUTTON, INPUT);
pinMode(OK_BUTTON, INPUT);
pinMode(CANCEL_BUTTON, INPUT);
pinMode(LDR_LEFT, INPUT);
pinMode(LDR_RIGHT, INPUT);
pinMode(SERVO_PIN, OUTPUT);
servo.attach(SERVO_PIN); // Initialize the servo motor
dht.setup(DHT_PIN, DHTesp::DHT22); // Initialize the DHT sensor
display.display();
delay(2000);
// Connect to the WiFi network
WiFi.begin("Wokwi-GUEST", "", 6); // Change the SSID and password to your WiFi network
// Loop and display waiting message until the WiFi network is connected
while (WiFi.status() != WL_CONNECTED) {
delay(250);
display.clearDisplay();
display.println("Connecting to WiFi...");
display.display();
}
// Successfully connected to the WiFi network
display.clearDisplay();
display.println("Connected to the WiFi network");
setupMqtt(); // Setup the MQTT communication
updateTime(); // Update initial time (program start time) from the NTP server
display.display();
delay(2000);
display.clearDisplay();
// Display the welcome message
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Welcome to Medibox");
display.display();
delay(2000);
}
// Main loop
void loop() {
if (!mqttClient.connected()) connectToBroker();
updateTimeAndTemp();
updateLightIntensity();
// Check if the alarm time has been reached and ring the alarm
if (alarmsEnabled) {
checkAlarmReached();
}
// Check if the user wants to go to the menu
if (digitalRead(OK_BUTTON) == LOW) {
goToMenu();
}
mqttClient.loop();
delay(500);
}
// Function to setup the MQTT communication
void setupMqtt() {
mqttClient.setServer("test.mosquitto.org", 1883); // Set the MQTT broker (host, port)
mqttClient.setCallback(receiveCallback); // Set the callback function for receiving messages
}
// Function to connect to the MQTT broker
void connectToBroker() {
// Loop until connected to the MQTT broker
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection....");
if (mqttClient.connect("ESP-6783-876345267")) { // "ESP-6783-876345267" is the client ID
// Successfully connected to the MQTT broker
Serial.println("connected to MQTT broker");
// Subscribe to the MQTT topics
mqttClient.subscribe(ALARM_ON_GET_TOPIC);
mqttClient.subscribe(ALARM_1_TIME_GET_TOPIC);
mqttClient.subscribe(ALARM_2_TIME_GET_TOPIC);
mqttClient.subscribe(ALARM_3_TIME_GET_TOPIC);
mqttClient.subscribe(MOTOR_ANGLE_TOPIC);
// Publish initial configuration to the MQTT broker
// Alarms enabled/disabled
if (alarmsEnabled)
mqttClient.publish(ALARM_ON_TOPIC, "true");
else
mqttClient.publish(ALARM_ON_TOPIC, "false");
// Alarm times - convert hours and minutes to a milliseconds string before publishing
sprintf(timeInMillisStr, "%d", alarmTimeToMillis(alarmTimes[0][0], alarmTimes[0][1]));
mqttClient.publish(ALARM_1_TIME_TOPIC, timeInMillisStr);
sprintf(timeInMillisStr, "%d", alarmTimeToMillis(alarmTimes[1][0], alarmTimes[1][1]));
mqttClient.publish(ALARM_2_TIME_TOPIC, timeInMillisStr);
sprintf(timeInMillisStr, "%d", alarmTimeToMillis(alarmTimes[2][0], alarmTimes[2][1]));
mqttClient.publish(ALARM_3_TIME_TOPIC, timeInMillisStr);
}
else {
// Failed to connect to the MQTT broker
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// Function to convert hours and minutes to milliseconds
int alarmTimeToMillis(int hour, int minute) {
return hour * 60 * 60 * 1000 + minute * 60 * 1000;
}
// Function to convert milliseconds to hours and minutes
void millisToAlarmTime(int millis, int alarmIndex) {
// updates global alarm times array
alarmTimes[alarmIndex][0] = (millis / 1000 / 60 / 60) % 24; // hours
alarmTimes[alarmIndex][1] = (millis / 1000 / 60) % 60; // minutes
}
// Function to receive and handle messages from the MQTT broker
void receiveCallback(char* topic, byte* payload, unsigned int length) {
// Print the received message on the serial monitor
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++)
Serial.print((char)payload[i]);
Serial.println();
// Check if the received message is to enable/disable the alarms
if (strcmp(topic, ALARM_ON_GET_TOPIC) == 0) {
// Update the alarm status based on the received message
if (strcmp((char*)payload, "true") == 0)
alarmsEnabled = true;
else
alarmsEnabled = false;
}
// Check if the received message is to update the alarm times
else if (strcmp(topic, ALARM_1_TIME_GET_TOPIC) == 0) // If the message is to update alarm 1 time
millisToAlarmTime(atoi((char*)payload), 0); // Update the alarm 1 time
else if (strcmp(topic, ALARM_2_TIME_GET_TOPIC) == 0) // If the message is to update alarm 2 time
millisToAlarmTime(atoi((char*)payload), 1); // Update the alarm 2 time
else if (strcmp(topic, ALARM_3_TIME_GET_TOPIC) == 0) // If the message is to update alarm 3 time
millisToAlarmTime(atoi((char*)payload), 2); // Update the alarm 3 time
// Check if the received message is to update the motor angle
else if (strcmp(topic, MOTOR_ANGLE_TOPIC) == 0)
servo.write(atoi((char*)payload)); // Update the motor angle
}
// Function to print a given text on the OLED display
void printTextLine(String text, int row = 0, int column = 0, int textSize = 1) {
display.setTextSize(textSize);
display.setCursor(column, row); // Set the cursor position
display.println(text);
display.display();
}
// Function to display the menu
void showMenu() {
display.clearDisplay();
printTextLine("Menu", 0, 0, 2);
for (int i = 0; i < menuOptionCount; i++) {
if (i == currentMenuOption)
printTextLine("-> " + menuOptions[i], 20 + i * 10, 0); // Highlight the current menu option
else
printTextLine(menuOptions[i], 20 + i * 10, 0);
}
}
// Function to change the time using the NTP server
void updateTime() {
// Connect to the WiFi network
configTime(utcOffset * 3600, dstOffset * 3600, "pool.ntp.org"); // (UTC offset, daylight saving time offset, NTP host)
struct tm timeinfo; // struct to store the time information
// Get the current time from the NTP server
if (!getLocalTime(&timeinfo)) {
// If the time cannot be obtained, print an error message
Serial.println("Failed to obtain time from NTP server");
return;
}
// Get the current time in hours, minutes, and seconds from the timeinfo struct
char timeSecond[3], timeMinute[3], timeHour[3];
strftime(timeSecond, 3, "%S", &timeinfo);
strftime(timeMinute, 3, "%M", &timeinfo);
strftime(timeHour, 3, "%H", &timeinfo);
// Calculate started time in milliseconds, corresponding to the current timezone
initmilliseconds = atoi(timeSecond) * 1000 + atoi(timeMinute) * 60 * 1000 + atoi(timeHour) * 60 * 60 * 1000 - millis();
display.clearDisplay();
}
// Function to display the current time zone
void displayTimeZone(int utcOffset) {
display.clearDisplay();
if (utcOffset >= 0)
printTextLine("Current Time Zone: \nUTC+" + String(utcOffset), 0, 0); // Add + sign for positive UTC offset
else
printTextLine("Current Time Zone: \nUTC" + String(utcOffset), 0, 0);
}
// Function to set the time zone
void setTimeZone() {
// Display the current time zone at the start
int tempUtcOffset = utcOffset;
displayTimeZone(tempUtcOffset);
delay(200);
// Loop until the user sets the time zone
while (true) {
if (digitalRead(UP_BUTTON) == LOW) {
// Increase the UTC offset
tempUtcOffset++;
if (tempUtcOffset > 14) // Maximum UTC offset is 14; set offset to -12
tempUtcOffset = -12;
displayTimeZone(tempUtcOffset);
}
else if (digitalRead(DOWN_BUTTON) == LOW) {
// Decrease the UTC offset
tempUtcOffset--;
if (tempUtcOffset < -12) // Minimum UTC offset is -12; set offset to 14
tempUtcOffset = 14;
displayTimeZone(tempUtcOffset);
}
else if (digitalRead(OK_BUTTON) == LOW) {
// Set the selected UTC offset
utcOffset = tempUtcOffset;
display.clearDisplay();
if (utcOffset >= 0) // Add + sign for positive UTC offset
printTextLine("Time Zone set to \nUTC+" + String(utcOffset), 0, 0);
else
printTextLine("Time Zone set to \nUTC" + String(utcOffset), 0, 0);
delay(2000);
updateTime(); // Update the time based on the new time zone
break;
}
else if (digitalRead(CANCEL_BUTTON) == LOW) {
break; // Cancel the time zone setting
}
delay(200);
}
display.clearDisplay();
showMenu(); // Display the main menu after setting/not setting the time zone
delay(200);
}
// Function to display the alarm menu
void displayAlarmMenu() {
display.clearDisplay();
printTextLine("Select alarm to set", 0, 0);
// Display the alarm options
for (int i = 0; i < alarmCount; i++) {
if (i == currentAlarmOption)
printTextLine("-> Alarm " + String(i + 1) + ": " + String(alarmTimes[i][0]) + ":" + String(alarmTimes[i][1]), 10 + i * 10, 0); // Highlight the current alarm option
else
printTextLine("Alarm " + String(i + 1) + ": " + String(alarmTimes[i][0]) + ":" + String(alarmTimes[i][1]), 10 + i * 10, 0);
}
}
// Function to display selected alarm time in hours or minutes
void displayAlarmUnit(int timeIndex, int value) {
display.clearDisplay();
if (timeIndex == 0) {
printTextLine("Set hour ", 0, 0);
printTextLine("-> " + String(value), 10, 0); // Display the selected hour
} else if (timeIndex == 1) {
printTextLine("Set minute ", 0, 0);
printTextLine("-> " + String(value), 10, 0); // Display the selected minute
}
}
// Function to set the alarm time in hours or minutes
bool setAlarmTimeUnit(int alarmIndex, int timeIndex) {
int value = alarmTimes[alarmIndex][timeIndex]; // Get the current alarm time (hour or minute) of the selected alarm
display.clearDisplay();
// Set the alarm time in hours
if (timeIndex == 0) {
displayAlarmUnit(timeIndex, value); // Display the selected hour
while (true) {
if (digitalRead(UP_BUTTON) == LOW) { // Increase the hour
value = (value + 1) % 24;
displayAlarmUnit(timeIndex, value);
} else if (digitalRead(DOWN_BUTTON) == LOW) { // Decrease the hour
value = (value - 1) % 24;
if (value == -1) { value = 23; }
displayAlarmUnit(timeIndex, value);
} else if (digitalRead(OK_BUTTON) == LOW) { // Set the selected hour
alarmTimes[alarmIndex][timeIndex] = value;
return true;
} else if (digitalRead(CANCEL_BUTTON) == LOW) { // Cancel the alarm time setting
return false;
}
delay(200);
}
}
// Set the alarm time in minutes
else if (timeIndex == 1) {
displayAlarmUnit(timeIndex, value); // Display the selected minute
while (true) {
if (digitalRead(UP_BUTTON) == LOW) { // Increase the minute
value = (value + 1) % 60;
displayAlarmUnit(timeIndex, value);
} else if (digitalRead(DOWN_BUTTON) == LOW) { // Decrease the minute
value = (value - 1) % 60;
if (value == -1) { value = 59; }
displayAlarmUnit(timeIndex, value);
} else if (digitalRead(OK_BUTTON) == LOW) { // Set the selected minute
alarmTimes[alarmIndex][timeIndex] = value;
return true;
} else if (digitalRead(CANCEL_BUTTON) == LOW) { // Cancel the alarm time setting
return false;
}
delay(200);
}
}
return false;
}
// Function to set the alarm time
void setAlarmTime(int alarmIndex) {
display.clearDisplay();
printTextLine("Set alarm " + String(alarmIndex + 1) + " time", 0, 0); // Display the selected alarm
int prev_hour = alarmTimes[alarmIndex][0];
// Update alarm time only if setting both hours and minutes is successful
// Set the alarm time in hours
if (setAlarmTimeUnit(alarmIndex, 0)) {
// Set the alarm time in minutes
if (setAlarmTimeUnit(alarmIndex, 1)) {
// Alarm time set successfully
display.clearDisplay();
printTextLine("Alarm " + String(alarmIndex + 1) + " time set to " + String(alarmTimes[alarmIndex][0]) + ":" + String(alarmTimes[alarmIndex][1]), 0, 0);
// publish the new alarm time to the MQTT broker
if (!mqttClient.connected()) // Connect to the MQTT broker if not connected
connectToBroker();
// Convert the alarm time to milliseconds string before publishing
sprintf(timeInMillisStr, "%d", alarmTimeToMillis(alarmTimes[alarmIndex][0], alarmTimes[alarmIndex][1]));
// Check the alarm index and publish the alarm time to the relevant topic
if (alarmIndex == 0)
mqttClient.publish(ALARM_1_TIME_TOPIC, timeInMillisStr);
else if (alarmIndex == 1)
mqttClient.publish(ALARM_2_TIME_TOPIC, timeInMillisStr);
else if (alarmIndex == 2)
mqttClient.publish(ALARM_3_TIME_TOPIC, timeInMillisStr);
delay(2000);
}
// If setting the alarm time in minutes is not successful, set the alarm time in hours to the previous value
else {
alarmTimes[alarmIndex][0] = prev_hour;
}
}
delay(1000);
}
// Function to select alarm option for updating the alarm time
void setAlarm() {
while (true) {
if (digitalRead(UP_BUTTON) == LOW) {
// Decrement the alarm option
currentAlarmOption = (currentAlarmOption - 1) % alarmCount;
if (currentAlarmOption == -1) { currentAlarmOption = alarmCount - 1; }
displayAlarmMenu(); // Display the alarm menu
} else if (digitalRead(DOWN_BUTTON) == LOW) {
// Increment the alarm option
currentAlarmOption = (currentAlarmOption + 1) % alarmCount;
displayAlarmMenu(); // Display the alarm menu
} else if (digitalRead(OK_BUTTON) == LOW) {
// Set the alarm time for the selected alarm option
setAlarmTime(currentAlarmOption);
displayAlarmMenu(); // Display the alarm menu after setting the alarm time
} else if (digitalRead(CANCEL_BUTTON) == LOW) {
// Return to the main screen
display.clearDisplay();
break;
}
delay(200);
}
}
// Function to navigate to main menu
void goToMenu() {
showMenu(); // Display the main menu
while (true) {
// Check if the user wants to navigate the menu
if (digitalRead(UP_BUTTON) == LOW) {
currentMenuOption = (currentMenuOption - 1) % menuOptionCount; // Decrement the menu option
if (currentMenuOption == -1) { currentMenuOption = menuOptionCount - 1; }
showMenu(); // Display updated menu
}
else if (digitalRead(DOWN_BUTTON) == LOW) {
currentMenuOption = (currentMenuOption + 1) % menuOptionCount; // Increment the menu option
showMenu(); // Display updated menu
}
// Navigate to relevant menu option based on user input
else if (digitalRead(OK_BUTTON) == LOW) {
if (currentMenuOption == 0) {
setTimeZone(); // Navigate to the set time zone menu
} else if (currentMenuOption == 1) {
setAlarm(); // Navigate to the set alarms menu
} else if (currentMenuOption == 2) {
// Enable/disable the alarms
display.clearDisplay();
if (!mqttClient.connected()) // Connect to the MQTT broker if not connected
connectToBroker();
// If the alarms are disabled, enable them
if (!alarmsEnabled) {
// Publish new alarm status to the MQTT broker
mqttClient.publish(ALARM_ON_TOPIC, "true");
printTextLine("Alarms enabled", 0, 0);
alarmsEnabled = true; // Enable the alarms
}
// If the alarms are enabled, disable them
else {
// Publish new alarm status to the MQTT broker
mqttClient.publish(ALARM_ON_TOPIC, "false");
printTextLine("Alarms disabled", 0, 0);
alarmsEnabled = false; // Disable the alarms
}
delay(2000);
showMenu(); // Display the main menu after enabling/disabling the alarms
}
}
else if (digitalRead(CANCEL_BUTTON) == LOW) {
// Return to the main screen
display.clearDisplay();
return;
}
}
}
// Function to check if the temperature has changed
bool temperatureChanged() {
if (newTemperature != temperature) {
temperature = newTemperature; // Update the temperature
return true;
}
return false;
}
// Function to check if the humidity has changed
bool humidityChanged() {
if (newHumidity != humidity) {
humidity = newHumidity; // Update the humidity
return true;
}
return false;
}
// Function to check if the intensityof left LDR sensor has changed
bool leftLightChanged() {
if (newLeftLight != leftLight) {
leftLight = newLeftLight; // Update the left light intensity
return true;
}
return false;
}
// Function to check if the intensity of right LDR sensor has changed
bool rightLightChanged() {
if (newRightLight != rightLight) {
rightLight = newRightLight; // Update the right light intensity
return true;
}
return false;
}
// Function to publish updated light intensity
void updateLightIntensity() {
// Read the light intensity from the LDR sensors
newLeftLight = analogRead(LDR_LEFT);
newRightLight = analogRead(LDR_RIGHT);
// Check if the light intensity has changed
if (leftLightChanged()) {
// Publish the light intensity to the MQTT broker
String(leftLight).toCharArray(lightLeftStr, 6);
mqttClient.publish(LIGHT_LEFT_TOPIC, lightLeftStr);
}
if (rightLightChanged()) {
// Publish the light intensity to the MQTT broker
String(rightLight).toCharArray(lightRightStr, 6);
mqttClient.publish(LIGHT_RIGHT_TOPIC, lightRightStr);
}
}
// Function to update temperature, humidity, and time on the OLED display
void updateTimeAndTemp() {
// Read the temperature and humidity from the DHT sensor
newHumidity = dht.getHumidity();
newTemperature = dht.getTemperature();
// Check if the humidity has changed
if (humidityChanged()) {
String(humidity).toCharArray(humidityStr, 6);
// Publish the humidity to the MQTT broker
mqttClient.publish(HUMIDITY_TOPIC, humidityStr);
}
// Check if the temperature has changed
if (temperatureChanged()) {
String(temperature).toCharArray(temperatureStr, 6);
// Publish the temperature to the MQTT broker
mqttClient.publish(TEMPERATURE_TOPIC, temperatureStr);
}
// Calculate the current time (= program start time + milliseconds since the program started)
milliTimenow = initmilliseconds + millis();
// Calculate the current time in hours, minutes, and seconds
timenow[0] = (milliTimenow / 1000 / 60 / 60) % 24; // Hours
timenow[1] = (milliTimenow / 1000 / 60) % 60; // Minutes
timenow[2] = (milliTimenow / 1000) % 60; // Seconds
display.clearDisplay();
// Display updated time, temperature, and humidity on the OLED display
printTextLine("Time: " + String(timenow[0]) + ":" + String(timenow[1]) + ":" + String(timenow[2]), 0, 0);
printTextLine("Temperature: " + String(temperature) + "C", 10, 0);
printTextLine("Humidity: " + String(humidity) + "%", 20, 0);
// Check if the temperature and humidity are within the acceptable range
// If not, display a warning message and turn on the LED
if ((temperature > 32 || temperature < 26) && (humidity > 80 || humidity < 60)) {
printTextLine("Temperature and humidity out of range!", 30, 0);
display.display();
digitalWrite(LED, HIGH);
} else if (temperature > 32 || temperature < 26) {
printTextLine("Temperature out of range!", 30, 0);
display.display();
digitalWrite(LED, HIGH);
} else if (humidity > 80 || humidity < 60) {
printTextLine("Humidity out of range!", 30, 0);
display.display();
digitalWrite(LED, HIGH);
} else { // Temperature and humidity are within the acceptable range
digitalWrite(LED, LOW);
display.display();
delay(500);
}
}
// Function to ring the alarm
void ringAlarm(int alarmIndex) {
digitalWrite(LED, HIGH);
// Keep ringing the alarm until the user stops it
while (!alarmRingingFinished[alarmIndex]) {
for (int j = 0; j < buzzerToneCount; j++) {
// Check if the user has stopped the alarm
if (digitalRead(CANCEL_BUTTON) == LOW) {
alarmRingingFinished[alarmIndex] = true; // Update ringing status to exit the loop
digitalWrite(LED, LOW);
break;
}
// Ring the buzzer with different tones
tone(BUZZER, buzzerTones[j]); delay(400);
noTone(BUZZER); delay(2);
}
}
}
// Function to check if the alarm time has been reached
void checkAlarmReached() {
// For each alarm, check if the alarm time has reached (hours and minutes match the current time)
for (int i = 0; i < alarmCount; i++) {
if (alarmTimes[i][0] == timenow[0] && alarmTimes[i][1] == timenow[1]) {
if (!alarmRingingFinished[i]) {
display.clearDisplay();
printTextLine("Medicine time!", 0, 0, 2);
ringAlarm(i);
}
} else {
// After Exit from the loop in ringAlarm function, reset the alarm ringing status
alarmRingingFinished[i] = false;
}
}
}