#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <NTPClient.h>
#include <time.h>
#include <Wire.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#define SCREENWIDTH 128 // Width of Display
#define SCRRENHEIGHT 64. // Height of Display
#define OLEDRESET -1 // Reset
#define SCRRENADDRESS 0x3C // I2C Address
#define BUZZER 5
#define LED_1 25
#define LED_2 33
#define LED_3 32
#define PUSH_CANCEL 12
#define PUSH_UP 14
#define PUSH_DOWN 27
#define PUSH_OK 13
#define DHT_22 15
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET_DST 0
int UTC_OFFSET = 0;
WiFiUDP ntpUDP;
Adafruit_SSD1306 display(SCREENWIDTH, SCRRENHEIGHT, &Wire, OLEDRESET );
NTPClient timeClient(ntpUDP, NTP_SERVER, UTC_OFFSET);
DHTesp dhtSensor;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
unsigned long timeNow = 0;
unsigned long timeLast = 0;
bool alarm_enabled = true;
int n_alarms = 3;
int alarm_hours[] = {0, 1, 2};
int alarm_minutes[] = {1, 10, 15};
bool alarm_triggered [] = {false, false};
int n_notes = 8;
int C = 262;
int D = 294;
int E = 330;
int F = 349;
int G = 392;
int A = 440;
int B = 494;
int C_H = 523;
int notes[] = {C, D, E, F, G, A, B, C_H};
int current_mode = 0;
int max_modes = 5;
String modes[] = {"1-Set Time", "2-Set Alarm 1", "3-Set Alarm 2", "4-Set Alarm 3", "5-Disable Alarms"};
void setup() {
pinMode(BUZZER, OUTPUT);
pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(LED_3, OUTPUT);
pinMode(PUSH_CANCEL, INPUT);
pinMode(PUSH_UP, INPUT);
pinMode(PUSH_DOWN, INPUT);
pinMode(PUSH_OK, INPUT);
dhtSensor.setup(DHT_22, DHTesp::DHT22);
Serial.begin(9600);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCRRENADDRESS )) {
Serial.println(F("SSD1306 Allocation Failed"));
for (;;);
}
display.display();
delay(500);
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
display.clearDisplay();
print_line("Connecting to WiFi", 0, 0, 2);
}
display.clearDisplay();
print_line("Conneced to WiFi", 0, 0, 2);
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
display.clearDisplay();
print_line("Welcome", 10, 10, 2);
print_line("Medibox", 10, 30, 2);
delay(2000);
display.clearDisplay();
timeClient.begin();
}
void loop() {
//display.clearDisplay();
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
timeClient.update();
update_time_with_check_alarm();
if (digitalRead(PUSH_OK) == LOW) {
//delay(200);
go_to_menu();
}
check_temp();
}
void print_line(String text, int column, int row, int text_size) {
display.setTextColor(SSD1306_WHITE);
display.setTextSize(text_size);
display.setCursor(column, row);
display.println(text);
display.display();
}
void print_time_now(void) {
display.display();
//print_line(String(days), 0, 0, 2);
//print_line("-", 20, 0, 2);
print_line(String(hours), 20, 0, 2);
print_line(":", 40, 0, 2);
print_line(String(minutes), 50, 0, 2);
print_line(":", 70, 0, 2);
print_line(String(seconds), 80, 0, 2);
}
void update_time() {
hours = timeClient.getHours();
minutes = timeClient.getMinutes();
seconds = timeClient.getSeconds();
display.clearDisplay();
}
void setTimeZone() {
float new_UTC_OFFSET = 0;
while (true) {
display.clearDisplay();
print_line("Enter UTC offset", 0, 0, 1);
print_line(String(new_UTC_OFFSET), 0, 10, 1);
int pressed = wait_for_button_press();
if (pressed == PUSH_UP) {
delay(100);
new_UTC_OFFSET += 0.5; // Increase by half an hour
}
else if (pressed == PUSH_DOWN) {
delay(100);
new_UTC_OFFSET -= 0.5; // Decrease by half an hour
}
else if (pressed == PUSH_OK) {
delay(100);
UTC_OFFSET = new_UTC_OFFSET * 3600; // Convert to seconds
timeClient.setTimeOffset(UTC_OFFSET);
display.clearDisplay();
print_line("Time Zone Set", 0, 0, 2);
delay(1000);
break;
}
else if (pressed == PUSH_CANCEL) {
delay(100);
break;
}
}
}
void ring_alarm() {
display.clearDisplay();
print_line("TAKE", 10, 10, 2);
print_line("MEDICINE", 10, 30, 2);
digitalWrite(LED_1, HIGH);
bool break_happend = false;
//Buzzer Ring
while ( break_happend == false && digitalRead(PUSH_CANCEL) == HIGH) {
for (int i = 0; i < n_notes; i++) {
if (digitalRead(PUSH_CANCEL) == LOW) {
delay(200);
break_happend = true;
break;
}
tone(BUZZER, notes[i]);
delay(500);
noTone(BUZZER);
delay(2);
}
}
digitalWrite(LED_1, LOW);
display.clearDisplay();
}
void update_time_with_check_alarm(void) {
display.display();
update_time();
print_time_now();
if (alarm_enabled) {
for (int i = 0; i < n_alarms; i++) {
if (alarm_triggered[i] == false && hours == alarm_hours[i] && minutes == alarm_minutes[i]) {
ring_alarm();
alarm_triggered[i] = true;
}
}
}
}
int wait_for_button_press() {
while (true) {
if (digitalRead(PUSH_UP) == LOW) {
delay(200);
return PUSH_UP;
}
else if (digitalRead(PUSH_DOWN) == LOW) {
delay(200);
return PUSH_DOWN;
}
else if (digitalRead(PUSH_OK) == LOW) {
delay(200);
return PUSH_OK;
}
else if (digitalRead(PUSH_CANCEL) == LOW) {
delay(200);
return PUSH_CANCEL;
}
update_time();
}
}
void go_to_menu() {
while (digitalRead(PUSH_CANCEL) == HIGH) {
display.clearDisplay();
print_line(modes[current_mode], 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == PUSH_UP) {
delay(200);
current_mode += 1;
current_mode = current_mode % max_modes;
}
else if (pressed == PUSH_DOWN) {
delay(200);
current_mode -= 1;
if (current_mode < 0) {
current_mode = max_modes - 1;
}
}
else if (pressed == PUSH_OK) {
delay(200);
Serial.println(current_mode);
run_mode(current_mode);
}
else if (pressed == PUSH_CANCEL) {
delay(200);
break;
}
}
}
void set_time() {
int temp_hour = hours;
while (true) {
display.clearDisplay();
print_line("Enter hour:" + String(temp_hour), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == PUSH_UP) {
delay(200);
temp_hour += 1;
temp_hour = temp_hour % 24;
}
else if (pressed == PUSH_DOWN) {
delay(200);
temp_hour -= 1;
if (temp_hour < 0) {
temp_hour = 23;
}
}
else if (pressed == PUSH_OK) {
delay(200);
hours = temp_hour;
break;
}
else if (pressed == PUSH_CANCEL) {
delay(200);
break;
}
}
int temp_minute = minutes;
while (true) {
display.clearDisplay();
print_line("Enter minute:" + String(temp_minute), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == PUSH_UP) {
delay(200);
temp_minute += 1;
temp_minute = temp_minute % 60;
}
else if (pressed == PUSH_DOWN) {
delay(200);
temp_minute -= 1;
if (temp_minute < 0) {
temp_minute = 59;
}
}
else if (pressed == PUSH_OK) {
delay(200);
minutes = temp_minute;
break;
}
else if (pressed == PUSH_CANCEL) {
delay(200);
break;
}
}
display.clearDisplay();
print_line("Time is set", 0, 0, 2);
delay(1000);
}
void set_alarm(int alarm) {
int temp_hour = alarm_hours[alarm];
while (true) {
display.clearDisplay();
print_line("Enter hour:" + String(temp_hour), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == PUSH_UP) {
delay(200);
temp_hour += 1;
temp_hour = temp_hour % 24;
}
else if (pressed == PUSH_DOWN) {
delay(200);
temp_hour -= 1;
if (temp_hour < 0) {
temp_hour = 23;
}
}
else if (pressed == PUSH_OK) {
delay(200);
alarm_hours[alarm] = temp_hour;
break;
}
else if (pressed == PUSH_CANCEL) {
delay(200);
break;
}
}
int temp_minute = alarm_minutes[alarm];
while (true) {
display.clearDisplay();
print_line("Enter minute:" + String(temp_minute), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == PUSH_UP) {
delay(200);
temp_minute += 1;
temp_minute = temp_minute % 60;
}
else if (pressed == PUSH_DOWN) {
delay(200);
temp_minute -= 1;
if (temp_minute < 0) {
temp_minute = 59;
}
}
else if (pressed == PUSH_OK) {
delay(200);
alarm_minutes[alarm] = temp_minute;
break;
//Serial.println(current_mode);
//run_mode(current_mode);
}
else if (pressed == PUSH_CANCEL) {
delay(200);
break;
}
}
display.clearDisplay();
print_line("Alarm is Set", 0, 0, 2);
alarm_triggered[alarm] = false;
alarm_enabled = true;
delay(1000);
}
void run_mode(int mode) {
if (mode == 0){
setTimeZone();
update_time();
}
if (mode == 1 || mode == 2 || mode == 3) {
set_alarm(mode - 1);
}
else if (mode == 4) {
alarm_enabled = false;
}
}
void check_temp() {
TempAndHumidity data = dhtSensor.getTempAndHumidity();
display.clearDisplay();
print_line("Temp: " + String(data.temperature, 2) + "'C", 0, 20, 1);
print_line("Humidity: " + String(data.humidity, 1) + "%", 0, 30, 1);
if (data.temperature > 32) {
//display.clearDisplay();
print_line("TEMPERATURE IS HIGH", 0, 40, 1);
digitalWrite(LED_2, HIGH);
}
if (data.temperature < 26) {
//display.clearDisplay();
print_line("TEMPERATURE IS LOW", 0, 40, 1);
digitalWrite(LED_2, HIGH);
}
if (data.humidity > 80) {
//display.clearDisplay();
print_line("HUMIDITY IS HIGH", 0, 50, 1);
digitalWrite(LED_3, HIGH);
}
if (data.humidity < 60) {
//display.clearDisplay();
print_line("HUMIDITY IS LOW", 0, 50, 1);
digitalWrite(LED_3, HIGH);
}
}