#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <WiFi.h>
#define SCREEN_WIDTH 128 // OLED width, in pixels
#define SCREEN_HEIGHT 64 // OLED height, in pixels
#define SCREEN_ADDRESS 0x3C
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET 0
#define UTC_OFFSET_DST 0
#define BUZZER 5
#define LED_1 15
#define PB_CANCEL 34
#define PB_OK 32
#define PB_UP 33
#define PB_DOWN 35
#define DHTPIN 12
// create an OLED display object connected to I2C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
DHTesp dhtSensor;
// Global variables
int days=0;
int hours=0;
int minutes=0;
int seconds=0;
unsigned long timeNow=0;
unsigned long timeLast=0;
bool alarms_enabled[]={false,false};
int n_alarms=2;
int alarm_hours[]={0,1};
int alarm_minutes[]={1,10};
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 Zone","2 - Set Alarm 1","3 - Set Alarm 2","4 - View Actice Alarms","5 - Delete a alarm"};
void setup() {
pinMode(BUZZER, OUTPUT);
pinMode(LED_1, OUTPUT);
pinMode(PB_CANCEL, INPUT);
pinMode(PB_OK, INPUT);
pinMode(PB_UP, INPUT);
pinMode(PB_DOWN, INPUT);
dhtSensor.setup(DHTPIN,DHTesp::DHT22);
Serial.begin(9600);
// initialize OLED display with I2C address 0x3C
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("failed to start SSD1306 OLED"));
for (;;);
}
display.display();
delay(2000); // wait two seconds for initializing
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
display.clearDisplay();
print_line("Connecting to WIFI",0,0,2);
}
display.clearDisplay(); // clear display
print_line("Connected to WIFI",0,0,2);
display.clearDisplay();
print_line("Welcome to Medibox!",10,20,2);
delay(2000);
display.clearDisplay();
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
}
void loop()
{
update_time_with_check_alarm();
if(digitalRead(PB_OK) == LOW)
{
delay(50);
go_to_menu();
}
check_temp();
}
void print_line(String text,int column,int row,int text_size)
{
display.setTextSize(text_size); // set text size
display.setTextColor(SSD1306_WHITE); // set text color
display.setCursor(column, row); // set position to display (x,y)
display.println(text); // set text
display.display();
}
void print_time_now()
{
display.clearDisplay();
print_line(String(days),0,0,2);
print_line(":",20,0,2);
print_line(String(hours),30,0,2);
print_line(":",50,0,2);
print_line(String(minutes),60,0,2);
print_line(":",80,0,2);
print_line(String(seconds),90,0,2);
print_line("Press ok to go to menu",0,30,1);
}
void update_time()
{
struct tm timeinfo;
getLocalTime(&timeinfo);
char timeHour[3];
strftime(timeHour,3, "%H", &timeinfo);
hours=atoi(timeHour);
char timeMinute[3];
strftime(timeMinute,3, "%M", &timeinfo);
minutes=atoi(timeMinute);
char timeSecond[3];
strftime(timeSecond,3, "%S", &timeinfo);
seconds=atoi(timeSecond);
char timeDay[3];
strftime(timeDay,3, "%H", &timeinfo);
days=atoi(timeDay);
}
void ring_alarm()
{
display.clearDisplay();
print_line("MEDICINE TIME!",0,0,2);
digitalWrite(LED_1, HIGH);
bool break_happened = false;
while(break_happened == false && digitalRead(PB_CANCEL)==HIGH){
for (int i=0;i<n_notes;i++){
if (digitalRead(PB_CANCEL)==LOW)
{
delay(200);
break_happened=true;
break;
}
tone(BUZZER,notes[i]);
delay(500);
noTone(BUZZER);
delay(2);
}
}
digitalWrite(LED_1, LOW);
display.clearDisplay();
}
void update_time_with_check_alarm()
{
update_time();
print_time_now();
for(int i=0;i<n_alarms;i++)
{
if (alarms_enabled[i] == true && alarm_triggered[i] == false && alarm_hours[i]==hours && alarm_minutes[i]==minutes)
{
ring_alarm();
alarm_triggered[i]=true;
}
}
}
int wait_for_button_press()
{
while(true)
{
if(digitalRead(PB_UP) == LOW)
{
delay(200);
return PB_UP;
}
else if(digitalRead(PB_DOWN) == LOW)
{
delay(200);
return PB_DOWN;
}
else if(digitalRead(PB_OK) == LOW)
{
delay(200);
return PB_OK;
}
else if(digitalRead(PB_CANCEL) == LOW)
{
delay(200);
return PB_CANCEL;
}
update_time();
}
}
void go_to_menu()
{
while(digitalRead(PB_CANCEL) == HIGH)
{
display.clearDisplay();
print_line("Displaying current mode...",0,0,2);
print_line(modes[current_mode],0,30,2);
int pressed=wait_for_button_press();
if(pressed == PB_UP)
{
delay(200);
current_mode+=1;
current_mode=current_mode % max_modes;
}
else if(pressed == PB_DOWN)
{
delay(200);
current_mode-=1;
if(current_mode<0)
{
current_mode=max_modes-1;
}
}
else if(pressed == PB_OK)
{
delay(200);
run_mode(current_mode);
}
else if(pressed == PB_CANCEL)
{
delay(200);
break;
}
}
}
void set_offset_time()
{
int temp_hour=0;
while(true)
{
display.clearDisplay();
print_line("Enter offset hours: "+String(temp_hour),0,0,2);
int pressed=wait_for_button_press();
if(pressed == PB_UP)
{
delay(200);
temp_hour+=1;
temp_hour=temp_hour % 24;
}
else if(pressed == PB_DOWN)
{
delay(200);
temp_hour-=1;
if(temp_hour<0)
{
temp_hour=23;
}
}
else if(pressed == PB_OK)
{
delay(200);
hours=hours+temp_hour;
break;
}
else if(pressed == PB_CANCEL)
{
delay(200);
break;
}
}
int temp_minute=0;
while(true)
{
display.clearDisplay();
print_line("Enter offset minutes: "+String(temp_minute),0,0,2);
int pressed=wait_for_button_press();
if(pressed == PB_UP)
{
delay(200);
temp_minute+=1;
temp_minute=temp_minute % 60;
}
else if(pressed == PB_DOWN)
{
delay(200);
temp_minute-=1;
if(temp_minute<0)
{
temp_minute=59;
}
}
else if(pressed == PB_OK)
{
delay(200);
minutes=minutes+temp_minute;
break;
}
else if(pressed == PB_CANCEL)
{
delay(200);
break;
}
}
display.clearDisplay();
print_line("Offset 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 == PB_UP)
{
delay(200);
temp_hour+=1;
temp_hour=temp_hour % 24;
}
else if(pressed == PB_DOWN)
{
delay(200);
temp_hour-=1;
if(temp_hour<0)
{
temp_hour=23;
}
}
else if(pressed == PB_OK)
{
delay(200);
alarm_hours[alarm]=temp_hour;
break;
}
else if(pressed == PB_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 == PB_UP)
{
delay(200);
temp_minute+=1;
temp_minute=temp_minute % 60;
}
else if(pressed == PB_DOWN)
{
delay(200);
temp_minute-=1;
if(temp_minute<0)
{
temp_minute=59;
}
}
else if(pressed == PB_OK)
{
delay(200);
alarm_minutes[alarm]=temp_minute;
break;
}
else if(pressed == PB_CANCEL)
{
delay(200);
break;
}
}
display.clearDisplay();
print_line("Alarm is set",0,0,2);
delay(1000);
}
void view_active_alarms()
{
int row=0;
display.clearDisplay();
for(int i=0;i<n_alarms;i++)
{
if(alarms_enabled[i]==true)
{
print_line("Alarm "+String(i)+" enabled",0,row,2);
row++;
}
}
int pressed=wait_for_button_press();
if(pressed==PB_CANCEL)
{
go_to_menu();
}
}
void delete_alarm()
{
int alarm=1;
display.clearDisplay();
for(int i=0;i<n_alarms;i++)
{
print_line("Delete alarm"+String(alarm),0,0,2);
int pressed=wait_for_button_press();
if(pressed == PB_CANCEL)
{
alarm++;
continue;
}
else if(pressed==PB_OK)
{
// for (int i = alarm; i < size - 1; i++)
// {
// arr[i] = arr[i + 1];
// }
continue;
}
}
go_to_menu();
}
void run_mode(int mode)
{
if(mode==0)
{
set_offset_time();
}
else if(mode ==1 || mode ==2)
{
set_alarm(mode-1);
}
else if(mode==3)
{
view_active_alarms();
}
else if(mode==4)
{
delete_alarm();
}
}
void check_temp()
{
TempAndHumidity data = dhtSensor.getTempAndHumidity();
if(data.temperature>35)
{
display.clearDisplay();
print_line("TEMP HIGH",0,40,1);
}
else if(data.temperature<25)
{
display.clearDisplay();
print_line("TEMP LOW",0,40,1);
}
if(data.humidity>40)
{
display.clearDisplay();
print_line("HUMIDITY HIGH",0,50,1);
}
else if(data.humidity<20)
{
display.clearDisplay();
print_line("HUMIDITY LOW",0,50,1);
}
}