#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP32Servo.h> //for servo
// for wifi
#include <WiFi.h>
#include <PubSubClient.h>
//for time and time zone
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET 5 * 3600 + 30 * 60 // Sri Lanaka Indian Standard time
#define UTC_OFFSET_DST 0
//Ifor mqtt protacol and NTP
WiFiClient espClient;
PubSubClient mqttClient(espClient);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
//servo and LDR
Servo servo;
#define LDR_L 35
#define LDR_R 36
int t_off = 30;
float gamma_i = 0.75;
//Arrays for iot part
char temp_Ary[6];
char LDR_L_Ary[4];
char LDR_R_Ary[4];
#include "DHTesp.h" // for DHT22
const int DHT_PIN = 12;
DHTesp dhtSensor;
String Temp;
String Humidity;
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int hours=0;
int seconds=0;
int minutes=0;
int days=0;
unsigned long time_now=0;
unsigned long time_last=0;
// For Alarm
bool alarm_on =true;
int num_of_alarms=3;
int alarm_hours[]={0,1,2};
int alarm_minutes[]={1,10,20};
int alarm_triggerd[]={false,false,false};
// for buzzer
#define NOTE_C5 523
#define NOTE_E5 659
#define NOTE_G5 784
#define NOTE_REST 0
#define BUZZER_PIN 19
// Define the duration of each note (in milliseconds)
#define NOTE_DURATION 200
int alarmMelody[] = {
NOTE_C5, NOTE_E5, NOTE_G5, NOTE_REST,
NOTE_C5, NOTE_E5, NOTE_G5, NOTE_REST,
NOTE_C5, NOTE_E5, NOTE_G5, NOTE_REST,
NOTE_C5, NOTE_E5, NOTE_G5, NOTE_REST
};
// Define the note durations (in milliseconds)
int alarmNoteDurations[] = {
8, 8, 8, 4,
8, 8, 8, 4,
8, 8, 8, 4,
8, 8, 8, 4
};
// for LED1
#define LED1_PIN 21
// for push button
#define Cancel 18
// for other push buttons
#define up_pb 16
#define down_pb 14
#define ok_menu_pb 15
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","5 - Dissable Alarms"};
void setup() {
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT); // for buzzer
pinMode(LED1_PIN, OUTPUT); // for LED
pinMode(Cancel, INPUT);// for alarmstop button
//for other push buttons
pinMode(up_pb, INPUT);
pinMode(down_pb, INPUT);
pinMode(ok_menu_pb, INPUT); Serial.begin(9600);
pinMode(LDR_L, INPUT);
pinMode(LDR_R, INPUT);
// for dht22
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed !"));
for (;;);
}
// Turn on the display
display.display();
delay(2000);
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
// Clear OLED display
display.clearDisplay();
print_line("Welcome to Medibox !", 2, 15, 2);delay(2000);display.clearDisplay();
//Setup of WIFI and MQTT
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
display.clearDisplay();
print_line("Connecting to Wi-Fi", 0,0,2);
}
display.clearDisplay();
print_line(" Wi-Fi Connected..........", 0,0,2);
delay(500);
Serial.println("");
Serial.println("Wifi Connected");
Serial.println("IP Address");
Serial.println(WiFi.localIP());
//mqtt setting
mqttClient.setServer("test.mosquitto.org",1883);
mqttClient.setCallback(Receieve_Callback);
//Display Configuration
display.clearDisplay();
print_line("Connected to wifi.......", 0,0,2);
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
servo.attach(37);
}
/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
void loop() {
// Your main code here
// This speeds up the simulation
display.clearDisplay();
update_time_with_check_alarm();
Check_temp_humidity();
if(digitalRead(ok_menu_pb )== LOW)
{
go_to_menu();
}
Serial.println(alarm_hours[0]); //
Serial.println(alarm_minutes[0]);// for easy ness of debugging
//Setting up the client connection
if(!mqttClient.connected())
{
Connect_To_Broker();
}
mqttClient.loop();
//Reading the temperature
Serial.println(temp_Ary);
mqttClient.publish("MEDI_box-TEMP", temp_Ary);
delay(100);
//Reading the LDR analog values
Update_intensity();
Serial.println(LDR_L_Ary);
Serial.println(LDR_R_Ary);
mqttClient.publish("MEDI_box-INTEN-LEFT", LDR_L_Ary);
delay(100);
mqttClient.publish("MEDI_box-INTEN-RIGHT", LDR_R_Ary);
delay(100);
}
/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
////////////////////////////////////Print_line/////////////////////////////////////////////////////////
void print_line(String text,int column, int row, int text_size)
{
display.setTextSize(text_size);
display.setTextColor(SSD1306_WHITE);
display.setCursor(column, row);
display.println(text);
display.display();
}
////////////////////////////Print_Time////////////////////////////////////////////////////
void print_time(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);
}
/////////////////////////////Update_Time///////////////////////////////////////
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);
}
///////////////////////////////////////Ring_alarm////////////////////////////////////////////////
bool ISpushed = false;
void ring_alarm()
{
while(ISpushed==false && digitalRead(Cancel)==HIGH)
{
display.clearDisplay();
print_line("Medicine Time !", 2, 25, 2);
digitalWrite(LED1_PIN,HIGH);
music();
if(digitalRead(Cancel)==LOW)
{
delay(200);
ISpushed=true;
break;
}
digitalWrite(LED1_PIN,LOW);
display.clearDisplay();
}
digitalWrite(LED1_PIN,LOW);
}
//////////////////////////////////////////Update_time_with_check_alarm/////////////////////////////////////////////
void update_time_with_check_alarm(void)
{
update_time();
print_time();
if (alarm_on == true) {
for (int i = 0; i < num_of_alarms; i++) {
if (alarm_triggerd[i] == false && alarm_hours[i] == hours && alarm_minutes[i] == minutes)
{
Serial.println("ring");
ring_alarm();
alarm_triggerd[i] = true;
}
}
}
}
/////////////////////////////////////////Music library////////////////////////////////////////////////
void music()
{
for (int i = 0; i < sizeof(alarmMelody) / sizeof(int); i++) {
int noteDuration = NOTE_DURATION / alarmNoteDurations[i];
tone(BUZZER_PIN, alarmMelody[i], noteDuration);
delay(noteDuration * 1.3);
noTone(BUZZER_PIN);
delay(noteDuration / 4);
}
}
int wait_for_button_press()
{
while(true)
{
if(digitalRead(up_pb)==LOW)
{
delay(200);
return up_pb;
}
if(digitalRead(down_pb)==LOW)
{
delay(200);
return down_pb;
}
if(digitalRead(ok_menu_pb)==LOW)
{
delay(200);
return ok_menu_pb;
}
if(digitalRead(Cancel)==LOW)
{
delay(200);
return Cancel;
}
update_time();
}
}
///////////////////////////////////////Go To Menu////////////////////////////////////////////////
void go_to_menu()
{
delay(200);
while(digitalRead(Cancel)==HIGH)
{
display.clearDisplay();
print_line(modes[current_mode],0,0,2);
int pressed = wait_for_button_press();
if(pressed==up_pb)
{
delay(200);
current_mode+=1;
current_mode=current_mode % max_modes;
}
else if(pressed==down_pb)
{
delay(200);
current_mode-=1;
if(current_mode<0)
{
current_mode=max_modes-1;
}
}
else if(pressed==ok_menu_pb)
{
delay(200);
run_mode(current_mode);
}
else if(pressed==Cancel)
{
delay(200);
break;
}
}
}
////////////////////////////////////////Set_Time///////////////////////////////////////////////
void set_time()
{
display.clearDisplay();
int temp_hours=hours;
while(true)
{
display.clearDisplay();
print_line("Enter hour: " + String(temp_hours),0,0,2);
int pressed=wait_for_button_press();
if(pressed==up_pb)
{
delay(200);
temp_hours+=1;
temp_hours%=24;
}
else if(pressed==down_pb)
{
delay(200);
temp_hours+=-1;
if(temp_hours<0)
{
temp_hours = 23;
}
}
else if(pressed==ok_menu_pb)
{
delay(200);
hours=temp_hours;
break;
}
else if(pressed==Cancel)
{
delay(200);
break;
}
}
int temp_minutes=minutes;
while(true)
{
display.clearDisplay();
print_line("Enter minutes: " + String(temp_minutes),0,0,2);
int pressed=wait_for_button_press();
if(pressed==up_pb)
{
delay(200);
temp_minutes+=1;
temp_minutes%=60;
}
else if(pressed==down_pb)
{
delay(200);
temp_minutes+=-1;
if(temp_minutes<0)
{
temp_minutes = 59;
}
}
else if(pressed==ok_menu_pb)
{
delay(200);
minutes=temp_minutes;
break;
}
else if(pressed==Cancel)
{
delay(200);
break;
}
}
display.clearDisplay();
print_line("Time is set",0,0,2);
delay(1000);
}
////////////////////////////////////Set_Alarm/////////////////////////////////////////////////////
void set_alarm(int alarm)
{
display.clearDisplay();
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==up_pb)
{
delay(200);
temp_hours+=1;
temp_hours%=24;
}
else if(pressed==down_pb)
{
delay(200);
temp_hours+=-1;
if(temp_hours<0)
{
temp_hours = 23;
}
}
else if(pressed==ok_menu_pb)
{
delay(200);
alarm_hours[alarm]=temp_hours;
break;
}
else if(pressed==Cancel)
{
delay(200);
break;
}
}
int temp_minutes =alarm_minutes[alarm];
while(true)
{
display.clearDisplay();
print_line("Enter minutes: " + String(temp_minutes),0,0,2);
int pressed=wait_for_button_press();
if(pressed==up_pb)
{
delay(200);
temp_minutes+=1;
temp_minutes%=60;
}
else if(pressed==down_pb)
{
delay(200);
temp_minutes+=-1;
if(temp_minutes < 0)
{
temp_minutes = 59;
}
}
else if(pressed==ok_menu_pb)
{
delay(200);
alarm_minutes[alarm]=temp_minutes;
break;
}
else if(pressed==Cancel)
{
delay(200);
break;
}
}
display.clearDisplay();
print_line("Alarm is set ! ",0,0,2);
delay(1000);
}
////////////////////////////////////////////Run_mode//////////////////////////////////////////////
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_on=false;
}
}
////////////////////////////////////Check_temp_humidity///////////////////////////////////////////////////////////
void Check_temp_humidity()
{
TempAndHumidity data = dhtSensor.getTempAndHumidity();
if(data.temperature>35)
{
display.clearDisplay();
print_line("HIGH Temp",0,40,1);
delay(1000);
}
if(data.temperature<25)
{
display.clearDisplay();
print_line("LOW Temp",0,40,1);
delay(1000);
}
if(data.humidity>40)
{
display.clearDisplay();
print_line("HIGH Humidity",0,50,1);
delay(1000);
}
if(data.humidity<20)
{
display.clearDisplay();
print_line("LOW Humdity",0,50,1);
delay(1000);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Newly added iot part
//////////////////////
//////////////////////
//////////////////////
void Connect_To_Broker() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection......");
if (mqttClient.connect("ESP32-000789543243")) {
Serial.println("connected");
mqttClient.subscribe("SERVO-ANGLE");
mqttClient.subscribe("SERVO-CONTROL-FACTOR");
} else {
Serial.print("failed");
Serial.print(mqttClient.state());
delay(5000);
}
}
}
void Receieve_Callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived - "); Serial.print(topic);Serial.print("- ");
char payloadCharAr[length];
Serial.print("Message Recieved: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
payloadCharAr[i] = (char)payload[i];
}
Serial.println();
if (strcmp(topic, "SERVO-ANGLE") == 0) {
t_off = String(payloadCharAr).toInt();
} else if (strcmp(topic, "SERVO-CONTROL-FACTOR") == 0) {
gamma_i = String(payloadCharAr).toFloat();
}
}
void Update_intensity() {
float left_LDR_Val = analogRead(LDR_L) * 1.00;
float right_LDR_Val = analogRead(LDR_R) * 1.00;
float left_LDR_Val_cha = (float)((left_LDR_Val - 4063.00) / (32.00 - 4063.00));
float right_LDR_Val_cha = (float)((right_LDR_Val - 4063.00) / (32.00 - 4063.00));
updateAngle(left_LDR_Val_cha, right_LDR_Val_cha);
String(left_LDR_Val_cha).toCharArray(LDR_L_Ary, 4);
String(right_LDR_Val_cha).toCharArray(LDR_R_Ary, 4);
}
void updateAngle(float left_LDR_Val, float right_LDR_Val) {
float max_intensity = left_LDR_Val;
float D = 1.5;
if (right_LDR_Val > max_intensity) {
max_intensity = right_LDR_Val;
D = 0.5;
}
else{}
int theeta = t_off * D + (180 - t_off) * max_intensity * gamma_i;
theeta = min(theeta, 180);
servo.write(theeta);
}