// Libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
// Definitions
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
#define BUZZER 4
#define LED_1 15
#define LED_2 2
#define CANCEL 34 //Cancel push button.cancel alarm,do to menu
#define OK 35 //Select ok push button
#define DOWN 32 //Navigate down push button
#define UP 33 //Navigate up push button
#define DHT 12
// Object Declarations
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
DHTesp dhtSensor;
// 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[] = {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 = 4;
String options[] = {"1 - Set Time", "2 - Set Alarm 1", "3 - Set Alarm 2", "4 - Disable Alarm"};
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(BUZZER, OUTPUT);
pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(CANCEL, INPUT);
pinMode(OK, INPUT);
pinMode(DOWN, INPUT);
pinMode(UP, INPUT);
dhtSensor.setup(DHT, DHTesp::DHT22);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
// Show the display buffer on the screen. You MUST call display() after
// drawing commands to make them visible on screen!
display.display();
delay(2000);
display.clearDisplay();
print_line("Welcome to Medibox", 25, 20, 2);
delay(3000);
display.clearDisplay();
}
void loop() {
update_time_with_check_alarm();
if (digitalRead(CANCEL) == LOW) {
delay(1000); //for switch debouncing standard 200ms
go_to_menu();
Serial.println("MENU");
}
check_temp();
}
void print_line(String text, int column, int row, int text_size ) {
//display.clearDisplay();
display.setTextSize(text_size);
display.setTextColor(SSD1306_WHITE);
display.setCursor(column, row);
display.println(text);
display.display();
}
void print_time_now(void) {
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(void) {
timeNow = millis() / 1000; //the number of seconds after bootup
seconds = timeNow - timeLast; //number of seconds passed after the last function call of update_time
if (seconds >= 60) {
minutes += 1; //minutes = minutes +1
timeLast += 60;
}
if (minutes == 60) {
minutes = 0;
hours += 1;
}
if (hours == 24) {
hours = 0;
days += 1;
}
}
void ring_alarm(void) {
//Display on LED
display.clearDisplay();
print_line("MEDICINE TIME", 0, 0, 2);
//Light an LED
digitalWrite(LED_1, HIGH);
bool break_ = false;
//Ring the BUZZER
while (break_ == false && digitalRead(CANCEL) == HIGH) {
for (int i = 0; i < n_notes; i++) {
if (digitalRead(CANCEL) == LOW) {
delay(200); //for switch debouncing standard 200ms
break_ = true;
break;
}
tone(BUZZER, notes[i]);
delay(500);
noTone(BUZZER);
delay(2);
}
}
delay(200); //for switch debouncing standard 200ms
digitalWrite(LED_1, LOW);
display.clearDisplay();
}
void update_time_with_check_alarm(void) {
update_time();
display.clearDisplay();
print_time_now();
// check for alarms
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(UP) == LOW) {
delay(200);
return UP;
}
else if (digitalRead(DOWN) == LOW) {
delay(200);
return DOWN;
}
else if (digitalRead(OK) == LOW) {
delay(200);
return OK;
}
else if (digitalRead(CANCEL) == LOW) {
delay(200);
return CANCEL;
}
}
update_time();
}
void go_to_menu(void) {
while (digitalRead(CANCEL) == HIGH) {
display.clearDisplay();
print_line(options[current_mode], 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == UP) {
current_mode += 1;
current_mode = current_mode % max_modes;
delay(200);
}
else if (pressed == DOWN) {
current_mode -= 1;
if (current_mode < 0) {
current_mode = max_modes - 1;
}
delay(200);
}
else if (pressed == OK) {
//Serial.println(current_mode);
run_mode(current_mode);
delay(200);
}
}
}
void run_mode(int mode) {
int temp_hour = 0;
int temp_min = 0;
if (mode == 0) {
while (digitalRead(CANCEL) == HIGH) {
//Set Time
//set hour
display.clearDisplay();
print_line("Enter Hour" + String(temp_hour), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == UP) {
temp_hour += 1;
temp_hour = temp_hour % 24;
delay(200);
}
else if (pressed == DOWN) {
temp_hour -= 1;
if (temp_hour < 0) {
temp_hour = 23;
}
delay(200);
}
else if (pressed == OK) {
hours = temp_hour;
delay(200);
break;
}
}
while (digitalRead(CANCEL) == HIGH) {
//set minutes
display.clearDisplay();
print_line("Enter Mins" + String(temp_min), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == UP) {
temp_min += 1;
temp_min = temp_min % 60;
delay(200);
}
else if (pressed == DOWN) {
temp_min -= 1;
if (temp_min < 0) {
temp_min = 59;
}
delay(200);
}
else if (pressed == OK) {
minutes = temp_min;
delay(200);
break;
}
}
display.clearDisplay();
print_line("Time Set", 0, 0, 2);
delay(1000);
}
else if (mode == 1 || mode == 2) {
while (digitalRead(CANCEL) == HIGH) {
//set hour
display.clearDisplay();
print_line("Enter Hour" + String(alarm_hours[mode - 1]), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == UP) {
temp_hour += 1;
temp_hour = temp_hour % 24;
delay(200);
}
else if (pressed == DOWN) {
temp_hour -= 1;
if (temp_hour < 0) {
temp_hour = 23;
}
delay(200);
}
else if (pressed == OK) {
alarm_hours[mode - 1] = temp_hour;
delay(200);
}
}
while (digitalRead(CANCEL) == HIGH) {
//set min
display.clearDisplay();
print_line("Enter Hour" + String(alarm_minutes[mode - 1]), 0, 0, 2);
int pressed = wait_for_button_press();
if (pressed == UP) {
temp_min += 1;
temp_min = temp_min % 60;
delay(200);
}
else if (pressed == DOWN) {
temp_min -= 1;
if (temp_min < 0) {
temp_min = 59;
}
delay(200);
}
else if (pressed == OK) {
alarm_minutes[mode - 1] = temp_min;
delay(200);
}
}
display.clearDisplay();
print_line("Alarm Set", 0, 0, 2);
delay(2000);
}
else if (mode == 3) {
alarm_enabled = false;
display.clearDisplay();
print_line("Alarm Disabled", 0, 0, 2);
delay(2000);
}
}
void check_temp(void) {
TempAndHumidity data = dhtSensor.getTempAndHumidity();
bool all_good = true;
if (data.temperature > 35) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("TEMP HIGH", 1, 40, 0);
}
else if (data.temperature < 25) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("TEMP LOW", 1, 40, 0);
}
if (data.humidity > 85) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("HUMID HIGH", 1, 50, 0);
}
else if (data.humidity < 35) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("HUMID LOW", 1, 50, 0);
}
if (all_good) {
digitalWrite(LED_2, LOW);
}
}