// Required Libraries
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Servo.h>
// Servo Setup
Servo servoTop1;
Servo servoBottom1;
Servo servoTop2;
Servo servoBottom2;
// Define Servo Angles
#define closeBottomAngle 0
#define openBottomAngle 90
#define closeTopAngle 90
#define openTopAngle 0
// Pill Settings
int pillAmount1 = 0;
int pillAmount2 = 0;
int wantedHour = 0;
int wantedMinute = 0;
#define takeWindow 10
// WiFi and MQTT Settings
const char* ssid = "oliphone";
const char* password = "123456789";
const char* mqtt_server = "192.168.137.1";
WiFiClient espClient;
PubSubClient client(espClient);
// RTC and LCD
RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Pins
#define trayPin 14 // D5 - IR Sensor
#define ledPin 12 // D6 - LED
#define buzzerPin 13 // D7 - Buzzer
// Setup WiFi
void setup_wifi() {
delay(10);
Serial.begin(9600);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected - ESP IP address: ");
Serial.println(WiFi.localIP());
}
// MQTT Reconnection
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP8266Client")) {
Serial.println("connected");
client.subscribe("dispenser/#");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// Setup
void setup() {
Serial.begin(9600);
pinMode(trayPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
servoTop1.attach(4); // D2
servoBottom1.attach(2); // D4
servoTop2.attach(0); // D3
servoBottom2.attach(5); // D1
servoTop1.write(closeTopAngle);
servoBottom1.write(closeBottomAngle);
servoTop2.write(closeTopAngle);
servoBottom2.write(closeBottomAngle);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Dispenser Ready");
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
lcd.setCursor(0, 1);
lcd.print("RTC not found!");
while (1);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
// Main loop
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
dispenserCheck();
}
void dispenserCheck() {
DateTime now = rtc.now();
int currentHour = now.hour();
int currentMinute = now.minute();
int currentSecond = now.second();
if ((wantedHour == currentHour) && (wantedMinute == currentMinute) && (currentSecond == 0)) {
for (int i = 0; i < pillAmount1; i++) {
servoTop1.write(openTopAngle); delay(1000);
servoTop1.write(closeTopAngle); delay(1000);
servoBottom1.write(openBottomAngle); delay(500);
servoBottom1.write(closeBottomAngle); delay(500);
}
for (int i = 0; i < pillAmount2; i++) {
servoTop2.write(openTopAngle); delay(2000);
servoTop2.write(closeTopAngle); delay(2000);
servoBottom2.write(openBottomAngle); delay(500);
servoBottom2.write(closeBottomAngle); delay(500);
}
trayCheck();
}
}
void trayCheck() {
int count = 0;
bool taken = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Waiting for user...");
while (count < takeWindow) {
int irValue = digitalRead(trayPin);
Serial.print("IR Value: ");
Serial.println(irValue);
if (irValue == LOW) {
taken = true;
break;
}
delay(1000);
count++;
}
if (!client.connected()) reconnect();
if (taken) {
digitalWrite(ledPin, HIGH);
digitalWrite(buzzerPin, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Pills Taken");
client.publish("dispenser/tray", "taken");
} else {
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Pills Not Taken");
client.publish("dispenser/tray", "inform");
}
delay(5000);
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
}
// MQTT callback
void callback(char* topic, byte* payload, unsigned int length) {
String messageTemp;
for (int i = 0; i < length; i++) {
messageTemp += (char)payload[i];
}
if (String(topic) == "dispenser/pill1") pillAmount1 = messageTemp.toInt();
if (String(topic) == "dispenser/pill2") pillAmount2 = messageTemp.toInt();
if (String(topic) == "dispenser/timer/hour") wantedHour = messageTemp.toInt();
if (String(topic) == "dispenser/timer/minutes") wantedMinute = messageTemp.toInt();
}
give me diagram on each of the connection pin