#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <WiFi.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0X3C
#define BUZZER 5
#define LED_1 15
#define PB_CANCEL 33
#define PB_DOWN 32
#define PB_OK 35
#define PB_UP 34
#define DHTPIN 12
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET 19800
#define UTC_OFFSET_DST 0
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
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 alarm_enabled= true;
int n_alarms = 4;
int alarm_hours[]={8,13,20,0};
int alarm_minutes[]={0,0,30,0};
bool alarm_triggered[] ={false,false,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","3-Set Alarm","4-Set Alarm","5-Disable Alarms"};
// defines pins numbers for ultrasonic
const int trigPin = 26;
const int echoPin = 25;
// defines variables
long duration;
int distance;
void setup() {
// put your setup code here, to run once:
pinMode(BUZZER, OUTPUT);
pinMode(LED_1, OUTPUT);
pinMode(PB_CANCEL, INPUT);
pinMode(PB_DOWN, INPUT);
pinMode(PB_OK, INPUT);
pinMode(PB_UP, INPUT);
dhtSensor.setup(DHTPIN,DHTesp::DHT22);
//Ultrasonic sensor pins
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600);
Serial.println("Hello, I'm your medibox!");
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)){
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.display();
delay(500);
WiFi.begin("Wokwi-GUEST","",6);
while(WiFi.status() != WL_CONNECTED){
delay(250);
display.clearDisplay();
print_line("Connecting to WIFI.",0,0,2);
}
display.clearDisplay();
print_line("WIFI Connected.",0,0,2);
configTime(UTC_OFFSET,UTC_OFFSET_DST,NTP_SERVER);
display.clearDisplay();
print_line("Welcome to Medibox!",0,0,2);
}
void loop() {
// put your main code here, to run repeatedly:
update_time_with_check_alarm();
if(digitalRead(PB_OK)==LOW){
delay(100);
go_to_menu();
}
check_temp();
check_box();
}
void print_line(String text,int column, int row, int txt_size){
display.setTextSize(txt_size);
display.setCursor(column,row);
display.setTextColor(SSD1306_WHITE);
display.println(text);
display.display();
}
void print_time_now(void){
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);
}
void update_time_0(void){
timeNow = millis()/1000;
seconds = timeNow - timeLast;
if(seconds == 60){
minutes+=1;
timeLast+=60;
}
if(minutes == 60){
hours+=1;
minutes = 0;
}
if(hours == 24){
days +=1;
hours =0;
}
}
void update_time(void){
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,"%d",&timeinfo);
days = atoi(timeDay);
}
void ring_alarm(){
display.clearDisplay();
print_line("MEDICINE TIME",0,0,2);
digitalWrite(LED_1,HIGH);
bool break_happened = false;
//ring the buzzer
while(break_happened == false && digitalRead(PB_CANCEL)==HIGH){
for(int i=0; i<n_notes; i++){
tone(BUZZER,notes[i]);
delay(500);
noTone(BUZZER);
delay(2);
if(digitalRead(PB_CANCEL)==LOW){
delay(200); //prevent bounsing
break_happened = true;
reminder();
}
else if(digitalRead(PB_OK)==LOW){
delay(200); //prevent bounsing
break_happened = true;
break;
}
}
}
digitalWrite(LED_1,LOW);
display.clearDisplay();
}
void update_time_with_check_alarm(void){
update_time();
print_time_now();
if(alarm_enabled == true){
for(int i=0; i<n_alarms;i++){
if(alarm_triggered[i]==false && alarm_hours[i]==hours && alarm_minutes[i] == minutes){
ring_alarm();
alarm_triggered[i]=true;
}
}
}
}
int wait_for_button_press(void){
while(true){
if(digitalRead(PB_UP)==LOW){
delay(200);
return PB_UP;
}
if(digitalRead(PB_DOWN)==LOW){
delay(200);
return PB_DOWN;
}
if(digitalRead(PB_OK)==LOW){
delay(200);
return PB_OK;
}
if(digitalRead(PB_CANCEL)==LOW){
delay(200);
return PB_CANCEL;
}
update_time();
}
}
void go_to_menu(void){
while(digitalRead(PB_CANCEL)==HIGH){
display.clearDisplay();
print_line(modes[current_mode],0,0,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);
Serial.println(current_mode);
run_mode(current_mode);
}
else if(pressed == PB_CANCEL){
delay(200);
break;
}
}
}
void set_time(void){
//update hours************************************
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 == 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=temp_hour;
break;
}
else if(pressed == PB_CANCEL){
delay(200);
break;
}
}
//update minutes************************************
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 == 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=temp_minute;
break;
}
else if(pressed == PB_CANCEL){
delay(200);
break;
}
}
display.clearDisplay();
print_line("Time is set",0,0,2);
delay(1000);
}
//****************************************************************************
void set_alarm(int alarm){
//update hours************************************
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;
}
}
//update minutes************************************
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 run_mode(int mode){
if (mode==0){
set_time();
}
else 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();
delay(100);
if(data.temperature >35){
print_line("TEMP HIGH",0,40,1);
}
else if(data.temperature <25){
print_line("TEMP LOW",0,40,1);
}
if(data.humidity >40){
print_line("HUMIDITY HIGH",0,50,1);
}
else if(data.humidity <20){
print_line("HUMIDITY LOW",0,50,1);
}
}
//Check medicine in the medibox
void check_box(){
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
// Prints the distance on the Serial Monitor
if(distance>50){
print_line("Empty",0,20,2);
}
}
//set reminder
void reminder(){
//update minutes************************************
bool set;
int temp_hour;
int temp_minute=0;
while(true){
display.clearDisplay();
print_line("Reminder 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(current_mode<0){
temp_minute=59;
}
}
else if(pressed == PB_OK){
delay(200);
int final_minute=minutes+temp_minute;
if(final_minute<60){
alarm_hours[3]=hours;
alarm_minutes[3]=final_minute;
}
else{
alarm_hours[3]=hours+1;
alarm_minutes[3]=final_minute-60;
}
set=1;
break;
}
else if(pressed == PB_CANCEL){
delay(200);
break;
}
}
if(set){
display.clearDisplay();
print_line("Reminder is set",0,0,2);
delay(1000);
}
else{
display.clearDisplay();
print_line("Reminder not set",0,0,2);
delay(1000);
}
}