// include libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <WiFi.h>
//define oled display parameters
#define screen_width 128 // OLED DISPLAY WIDTH IN PIXELS
#define screen_height 64 // OLED DISPLAY HEIGHT IN PIXELS
#define oled_reset -1 // REST PIN
#define screen_address 0x3C // SEE DATA SHEET FOR ADDRESS
#define BUZZER 5
#define LED_1 15
#define PB_CANCEL 34
#define PB_OK 32
#define PB_UP 35
#define PB_DOWN 33
#define DHTPIN 12
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET 19800
#define UTC_OFFSET_DST 0
long utc_offset_sec=0;
// declare objects
Adafruit_SSD1306 display(screen_width, screen_height, &Wire, oled_reset);
DHTesp dhtSensor;
//declare 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 = 2;
int alarm_hours[] = {0, 0};
int alarm_minutes[] = {0, 1};
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 = 4;
String modes[] = {"1-Set Time", "2-Set Alarm 1", "3-Set Alarm 2", "4-Disable Alarms"};
void setup() {
// put your setup code here, to run once:
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);
if (!display.begin(SSD1306_SWITCHCAPVCC, screen_address)) {
Serial.println(F("SSD1306 allocation failed "));
for (;;);
}
// turn on OLED DISPLAY
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("connected to WIFI",0,0,2);
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
// clear OLED DISPLAY
display.clearDisplay();
print_line("Welcome to Medibox!", 10, 20, 2);
delay(500);
display.clearDisplay();
}
void loop() {
// put your main code here, to run repeatedly:
update_time_with_check_alarm();
if (digitalRead(PB_OK) == LOW) {
delay(200);
go_to_menu();
}
check_temp();
}
void print_line(String text, int column, int row, int text_size ) {
//display a custom message
display.setTextSize (text_size);
display.setTextColor(SSD1306_WHITE);
display.setCursor(column, row) ; // COLUMN , ROW
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() {
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;
while (break_happened == false && digitalRead(PB_CANCEL) == HIGH) {
for (int i = 0 ; i < n_notes ; i = i + 1) {
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(void) {
update_time();
print_time_now();
if (alarm_enabled == true) {
for ( int i = 0 ; i < n_alarms ; i = i + 1) {
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;
}
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(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);
run_mode(current_mode);
}
else if (pressed == PB_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 == 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;
}
}
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){
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 run_mode(int mode) {
if ( mode == 0) {
set_time();
}
else if(mode==1|| mode==2){
set_alarm(mode-1);
}
else if (mode==3){
alarm_enabled=false;
}
}
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);
}
}
void set_timezone() {
int current_offset_hours = utc_offset_sec / 3600;
int current_offset_minutes = (utc_offset_sec % 3600) / 60;
int offset_hours = read_value("Enter offset hours: ", current_offset_hours, 14, -12);
int offset_minutes = read_value("Enter offset minutes: ", current_offset_minutes, 59, 0);
utc_offset_sec = offset_hours * 3600 + offset_minutes * 60;
configTime(utc_offset_sec, UTC_OFFSET_DST, NTP_SERVER);
print_line("Timezone set to " + String(offset_hours) + ":" + String(offset_minutes), 0, 0, 2);
delay(250);
}
int read_value(String text, int init_value, int max_value, int min_value) {
int temp_value = init_value;
while (true) {
print_line(text + String(temp_value), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == PB_UP) {
delay(200);
temp_value += 1;
if (temp_value > max_value) {
temp_value = min_value;
}
}
else if (pressed == PB_DOWN) {
delay(200);
temp_value -= 1;
if (temp_value < min_value) {
temp_value = max_value;
}
}
else if (pressed == PB_OK) {
delay(200);
return temp_value;
}
else if (pressed == PB_CANCEL) {
delay(200);
break;
}
}
return init_value;
}