#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32Servo.h>
#define SERVO 16
#define LDR_R 34
#define LDR_L 35
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define BUZZER 5
#define LED 15
#define PB_CANCEL 4
#define PB_OK 33
#define PB_UP 32
#define PB_DOWN 2
#define DHTPIN 12
#define NTP_SERVER "pool.ntp.org"
// #define UTC_OFFSET 0
#define UTC_OFFSET_DST 0
Servo motor;
Adafruit_SSD1306 display(SCREEN_WIDTH ,SCREEN_HEIGHT , &Wire , OLED_RESET );
DHTesp dhtSensor;
WiFiClient espClient;
PubSubClient mqttClient(espClient);
//Global variables
int UTC_OFFSET = 3600 * 5 + 30 * 60;
int utc1 = 5;
int utc2 = 30;
int hours = 0;
int minutes = 0;
int seconds = 0;
int days = 0;
int months = 0;
int years = 0;
unsigned long timeNow = 0;
unsigned long timeLast = 0;
bool alarm_enabled = true;
int n_alarm = 3;
int alarm_hours[] = {0,1 , 2};
int alarm_minutes[] = {1 , 10 , 10};
int alarm_triggered[] = {false , false , false};
//for buzzer
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 l_light = 0;
int r_light = 0;
int current_mode = 0;
int max_modes = 5;
String modes[] = {
"1 - Set time" , "2 - Set Alarm 1" , "3 - Set Alarm 2" , "4 - Set Alarm 3" , "Disable alarms"
};
void print_line( String text , int text_size , int row , int column , bool displayok ){
display.setTextSize(text_size);
display.setTextColor(SSD1306_WHITE);
display.setCursor(column,row);
display.println(text);
if (displayok){
display.display();
}
}
void setupMqtt() {
mqttClient.setServer("test.mosquitto.org", 1883);
mqttClient.setCallback(receiveCallback);
Serial.println("Setup MQTT");
}
void receiveCallback (char* topic , byte* payload ,int length){
Serial.print("Message Arrived [");
Serial.print(topic);
Serial.print(" ]");
Serial.println();
char payloadCharAt[length];
for (int i = 0 ; i < length ; i ++){
Serial.print((char)payload[i]);
payloadCharAt[i] = (char) payload[i];
}
Serial.println();
if (strcmp(topic , "ENTC-ON-OFF" ) == 0){
if (payloadCharAt[0] == '1'){
digitalWrite(LED , HIGH);
}else{
digitalWrite(LED , LOW);
}
}
if (strcmp(topic , "SERVO-AN") == 0 ){
motor.write(50);
}
}
void print_time_now (void){
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
display.clearDisplay();
print_line (String(days), 2, 40 , 0 , false);
print_line(":", 2, 40 , 20 , false);
print_line (String(months), 2, 40 , 30 , false);
print_line(":", 2, 40 , 50 , false);
print_line (String(years), 2, 40 , 60 , false);
print_line (String(hours), 2, 0 , 30 , false);
print_line(":", 2, 0 , 50 , false);
print_line (String(minutes), 2, 0 , 60 , false);
print_line(":", 2, 0 , 80 , false);
print_line (String(seconds), 2, 0 , 90 , false);
display.display();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(BUZZER , OUTPUT);
pinMode(LED , OUTPUT);
pinMode(PB_CANCEL , INPUT);
pinMode(PB_OK , INPUT);
pinMode(PB_UP , INPUT);
pinMode(PB_DOWN , INPUT);
pinMode(DHTPIN , INPUT);
pinMode(LDR_R , INPUT);
pinMode(LDR_L , INPUT);
motor.attach(SERVO);
dhtSensor.setup(DHTPIN , DHTesp::DHT22 );
if (!display.begin(SSD1306_SWITCHCAPVCC ,SCREEN_ADDRESS )){
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.display();
display.clearDisplay();
delay(1000);
// print_line("Hii",1 , 0,0);
// delay(1000);
// print_time_now();
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
display.clearDisplay();
print_line("Connecting to the WIFI.......",0 , 0, 2 , true );
}
setupMqtt();
display.clearDisplay();
print_line("Connected to the WIFI",0 , 0, 2 , true );
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
display.clearDisplay();
print_line("Welcome to medibox", 1 , 20 , 2 , true);
delay(500);
display.clearDisplay();
}
void connectToBroker() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect("ESP32-123456")) {
Serial.println("Connected MQTT");
mqttClient.subscribe("ENTC-ON-OFF");
} else {
Serial.print("Failed MQTT, rc=");
Serial.println(mqttClient.state());
delay(500);
}
}
}
void update_time(void){
configTime((utc1 *3600 + utc2 * 60 ) , UTC_OFFSET_DST, NTP_SERVER);
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);
char timeMonth[3];
strftime(timeMonth, 3, "%m", &timeinfo);
months = atoi(timeMonth);
char timeYear[5]; // For the year, use 5 characters (including null terminator)
strftime(timeYear, 5, "%Y", &timeinfo);
years = atoi(timeYear);
}
void check_light(){
l_light = analogRead(LDR_L);
r_light = analogRead(LDR_R);
if (l_light >= r_light){
mqttClient.publish("LDR" , String(r_light-4000).c_str());
mqttClient.publish("LDR-LR" , "R");
}else{
mqttClient.publish("LDR" , String(l_light-4000).c_str());
mqttClient.publish("LDR-LR" , "L");
}
delay(20);
}
void loop() {
// put your main code here, to run repeatedly:
if (!mqttClient.connected()) {
connectToBroker();
}
mqttClient.loop();
update_time_with_check_alarm();
if (digitalRead(PB_OK) == LOW){
delay(200);
go_to_menu();
Serial.println("Came out from the fo_to_menue");
}
check_temp();
check_light();
mqttClient.publish("ENTC-TEMP", "25.12");
Serial.println("Published");
delay(500);
}
void update_time_with_check_alarm(void){
update_time();
print_time_now();
display.display();
if (alarm_enabled == true){
for (int i = 0 ; i < n_alarm ; i++){
if (alarm_triggered[i] == false && hours == alarm_hours[i] && minutes == alarm_minutes[i]){
ring_alarm();
alarm_triggered[i] = true;
}
}
}
}
void ring_alarm(){
display.clearDisplay();
print_line("Medicine Time", 2,0,0 , true);
//led light up
digitalWrite(LED , HIGH);
bool break_happened = false;
//ring buzzer
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 , LOW);
display.clearDisplay();
}
int wait_for_button(){
while(true){
if (digitalRead(PB_UP)== LOW){
delay(200);
Serial.println("UP");
return PB_UP;
}
if (digitalRead(PB_DOWN)== LOW){
delay(200);
Serial.println("DOWN");
return PB_DOWN;
}
if (digitalRead(PB_OK)== LOW){
delay(200);
Serial.println("OK");
return PB_OK;
}
if (digitalRead(PB_CANCEL)== LOW){
delay(200);
Serial.println("CANCEL");
return PB_CANCEL;
}
update_time();
}
}
void go_to_menu(){
while(digitalRead(PB_CANCEL) == HIGH){
display.clearDisplay();
int mapp[] = {0,10,20,30,40};
print_line(modes[0],0,0,8 , false);
print_line(modes[1],0,10,8 , false);
print_line(modes[2],0,20,8 , false);
print_line(modes[3],0,30,8 , false);
print_line(modes[4],0,40,8 , false);
print_line("o" , 0 , mapp[current_mode] , 0 , false);
display.display();
int pressed = wait_for_button();
if (pressed == PB_DOWN){
delay(200);
current_mode += 1;
current_mode = current_mode % max_modes;
}
else if (pressed == PB_UP){
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);
Serial.print("menu cancel button pressed");
break;
}
}
}
// void go_to_menu(){
// while(digitalRead(PB_CANCEL) == HIGH){
// display.clearDisplay();
// print_line(modes[current_mode],0,0,2 , true);
// int pressed = wait_for_button();
// 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);
// Serial.print("menu cancel button pressed");
// break;
// }
// }
// Serial.println("menu done");
// }
void set_time(){
display.clearDisplay();
while (true){
print_line("Timezone: " + String(utc1) + " : " + String(utc2),0 ,0,2 , true);
int pressed = wait_for_button();
if (pressed == PB_UP){
delay(200);
if (utc2 == 0){
utc2 = 30;
}
else{
utc2 = 0;
utc1 += 1;
}
if (utc1>12){
utc1 = -12;
}
display.clearDisplay();
print_line("Timezone: " + String(utc1) + " : " + String(utc2),0 ,0,2 , true );
Serial.println("Timezone: " + String(utc1) + " : " + String(utc2) );
}
else if (pressed == PB_DOWN){
delay(200);
if (utc2 == 0){
utc2 = 30;
utc1 -= 1;
}else{
utc2 = 0;
}
if (utc1 < -12){
utc1 = 12;
}
display.clearDisplay();
print_line("Timezone: " + String(utc1) + " : " + String(utc2),0 ,0,2 , true );
Serial.println("Timezone: " + String(utc1) + " : " + String(utc2) );
// Serial.println("Enter Hour: " + String(temp_hour));
}
else if(pressed = PB_OK ){
delay(200);
configTime((utc1 *3600 + utc2 * 60 ) , UTC_OFFSET_DST, NTP_SERVER);
print_line("Time set ", 0 ,0,2 , true);
delay(500);
break;
}
else if (pressed = PB_CANCEL){
delay(200);
Serial.println("Time set");
break;
}
}
}
void set_alarm(int alarm){
int temp_hour = alarm_hours[alarm];
while(true){
display.clearDisplay();
print_line("Enter alarm hour: " + String(temp_hour), 0, 0, 2 , true);
int pressed = wait_for_button();
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;
alarm_triggered[alarm] = false;
break;
}
else if (pressed == PB_CANCEL){
delay(200);
return;
}
}
int temp_minutes = alarm_minutes[alarm];
while(true){
display.clearDisplay();
print_line("Enter alarm minutes: " + String(temp_minutes), 0, 0, 2 , true);
int pressed = wait_for_button();
if (pressed == PB_UP){
delay(200);
temp_minutes += 1;
temp_minutes = temp_minutes % 60;
}
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;
}
}
display.clearDisplay();
print_line("Alarm is set", 0, 0, 2 , true);
delay(1000);
}
void run_mode(int mode){
if (mode == 0){
set_time();
}
if (mode == 1 || mode == 2 || mode == 3){
set_alarm(mode-1);
}
else if (mode == 4){
if (alarm_enabled){
alarm_enabled = false;
display.clearDisplay();
modes[4] = "Enable alarms";
print_line("Alarmas Disabled!!" , 0 , 0 , 2 , true);
delay(600);
display.clearDisplay();
}else{
alarm_enabled = true;
display.clearDisplay();
modes[4] = "Disable alarms";
print_line("Alarmas Enabled!!" , 0 , 0 , 2 , true);
delay(600);
display.clearDisplay();
}
}
}
void check_temp(){
TempAndHumidity data = dhtSensor.getTempAndHumidity();
if (data.temperature > 32){
display.clearDisplay();
print_line("TEMP HIGH", 0 , 40 , 1 , true);
digitalWrite(LED , HIGH);
}else{
digitalWrite(LED , LOW);
}
if (data.temperature < 26){
display.clearDisplay();
print_line("TEMP LOW", 0 , 40 , 1 , true);
digitalWrite(LED , HIGH);
}else{
digitalWrite(LED , LOW);
}
if (data.humidity > 80){
display.clearDisplay();
print_line("HUMIDITY HIGH", 0 , 50 , 1 , true);
digitalWrite(LED , HIGH);
}else{
digitalWrite(LED , LOW);
}
if (data.humidity < 60){
display.clearDisplay();
print_line("HUMIDITY LOW", 0 , 50 , 1 , true);
digitalWrite(LED , HIGH);
}else{
digitalWrite(LED , LOW);
}
}