#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <WiFi.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 //Reset pin number
#define SCREEN_ADDRESS 0x3c
#define Led_1 2
#define Buzzer 5
#define pb_cancel 19
#define pb_ok 32
#define pb_up 33
#define pb_down 35
#define Dhtpin 12
int offset_seconds = 0;
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET offset_seconds
#define UTC_OFFSET_DST 0
//Declare objects
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 = 3;
int alarm_hours[] = {0,1,2};
int alarm_minutes[] = {1,10,20};
bool alarm_triggered[] = {false,false,false};
int n_notes = 2;
int C = 282;
int D = 294;
int notes[] = {C,D};
int current_mode = 0;
int max_modes = 5;
String modes[] = {"1 - Set time Zone","2 - Set Alarm 1", "3 - Set Alarm 2", "4 - Set Alarm 3", "5 - Disable Alarms"};
void setup() {
// put your setup code here, to run once:
pinMode(Led_1, OUTPUT);
pinMode(Buzzer, OUTPUT);
pinMode(pb_cancel, INPUT);
pinMode(pb_ok, INPUT);
pinMode(pb_down, INPUT);
pinMode(pb_up, INPUT);
dhtSensor.setup(Dhtpin, DHTesp :: DHT22);
Serial.begin(9600);
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)){
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, Loop forever
}
// show initial display buffer contents on the screen
// the library initializes this width an adafruit splash screen
display.display();
delay(2000); // pause for 2 seconds
//WIFI initialization
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("Connected to Wifi", 0, 0, 2);
configTime(offset_seconds, UTC_OFFSET_DST, NTP_SERVER);
// Clear the buffer
display.clearDisplay();
print_line("Welcome to medibox",10,20,2);
delay(2000);
display.clearDisplay();
}
void loop() {
configTime(offset_seconds, UTC_OFFSET_DST, NTP_SERVER);
update_time_with_check_alarm();
if (digitalRead(pb_ok) == LOW){
delay(200);
go_to_menu();
}
check_temp();
display.display();
}
void print_line(String text, int column, int row, int text_size){
display.setTextSize(text_size); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); //Draw white text
display.setCursor(column,row); //Start from the top-left corner
display.println(text);
display.display();
}
void print_line_1(String text, int column, int row, int text_size){
display.setTextSize(text_size); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); //Draw white text
display.setCursor(column,row); //Start from the top-left corner
display.println(text);
}
void print_time_now(void){
display.clearDisplay();
print_line_1(String(days),0,0,2);
print_line_1(":",20,0,2);
print_line_1(String(hours),30,0,2);
print_line_1(":",50,0,2);
print_line_1(String(minutes),60,0,2);
print_line_1(":",80,0,2);
print_line_1(String(seconds),90,0,2);
}
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(timeHour,3, "%d", &timeinfo);
days = atoi(timeDay);
}
void ring_alarm(void){
display.clearDisplay();
print_line("Medicine time!", 0, 0, 2);
digitalWrite(Led_1, HIGH);
bool break_happened = false;
//Ring the alarm
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(){
print_time_now();
update_time();
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(){
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(){
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){
current_mode += 1;
current_mode = current_mode % max_modes;
delay(200);
}
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_time_zone(){
int offset_hours = 0;
while(true){
display.clearDisplay();
print_line("Enter offset hours: " + String(offset_hours), 0, 0, 2);
int pressed = wait_for_button_press();
if(pressed == pb_up){
offset_hours += 1;
offset_hours = offset_hours % 24;
}
else if(pressed == pb_down){
delay(200);
offset_hours -= 1;
if(offset_hours < 0){
offset_hours = 23;
}
}
else if(pressed == pb_ok){
delay(200);
break;
}
else if(pressed == pb_cancel){
delay(200);
break;
}
}
int offset_minutes = minutes;
while(true){
display.clearDisplay();
print_line("Enter offset minutes: " + String(offset_minutes), 0, 0, 2);
int pressed = wait_for_button_press();
if(pressed == pb_up){
offset_minutes += 1;
offset_minutes = offset_minutes % 60;
}
else if(pressed == pb_down){
delay(200);
offset_minutes -= 1;
if(offset_minutes < 0){
offset_minutes = 59;
}
}
else if(pressed == pb_ok){
delay(200);
minutes = offset_minutes;
break;
}
else if(pressed == pb_cancel){
delay(200);
break;
}
}
offset_seconds = 3600 * offset_hours + 60 * offset_minutes;
display.clearDisplay();
print_line("The time zone is set",0,0,2);
delay(1000);
}
void set_alarm(int alarm){
int temp_hours = alarm_hours[alarm];
while(true){
display.clearDisplay();
print_line("Enter alarm hour: " + String(temp_hours), 0, 0, 2);
int pressed = wait_for_button_press();
if(pressed == pb_up){
temp_hours += 1;
temp_hours = temp_hours % 24;
}
else if(pressed == pb_down){
delay(200);
temp_hours -= 1;
if(temp_hours < 0){
temp_hours = 23;
}
}
else if(pressed == pb_ok){
delay(200);
alarm_hours[alarm] = temp_hours;
break;
}
else if(pressed == pb_cancel){
delay(200);
break;
}
display.clearDisplay();
}
int temp_minutes = alarm_minutes[alarm];
while(true){
display.clearDisplay();
print_line("Enter alarm minute: " + String(temp_minutes), 0, 0, 2);
int pressed = wait_for_button_press();
if(pressed == pb_up){
temp_minutes += 1;\
temp_minutes = temp_minutes % 59;
}
else if(pressed == pb_down){
delay(200);
temp_minutes -= 1;
if(temp_minutes < 0){
temp_minutes = 59;
}
}
else if(pressed == pb_ok){
delay(200);
alarm_minutes[alarm] = temp_minutes;
break;
}
else if(pressed == pb_cancel){
delay(200);
break;
}
}
alarm_enabled = true;
display.clearDisplay();
print_line("The alarm is set",0,0,2);
delay(1000);
}
void run_mode(int mode){
if(mode == 0){
set_time_zone();
}
else if(mode == 1 || mode == 2 || mode == 3){
set_alarm(mode - 1);
}
else if(mode == 4){
alarm_enabled = false;
display.clearDisplay();
print_line("All alarms are disabled",0,0,2);
delay(1000);
}
}
void check_temp()
{
TempAndHumidity data = dhtSensor.getTempAndHumidity();
if(data.temperature > 35)
{
print_line_1("Temp High", 0, 40, 1);
}
else if(data.temperature < 25)
{
print_line_1("Temp Low", 0, 40, 1);
}
else if(data.humidity > 40)
{
print_line_1("Humidity High", 0, 50, 1);
}
if(data.humidity < 20)
{
print_line_1("Humidity Low", 0, 50, 1);
}
}