#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHTesp.h>
#include <WiFi.h>
#include <ESP32Servo.h>
#include <PubSubClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0X3C
#define BUZZER 13
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET 0
#define UTC_OFFSET_DST 0
#define CANCEL 27
#define OK 14
#define UP 26
#define DOWN 25
#define MENU 5
#define LED_1 4
#define LED_2 2
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGT, &Wire, OLED_RESET);
const int DHT_PIN = 15;
DHTesp dhtSensor;
const float GAMMA = 0.7;
const float RL10 = 50;
const int servoPin = 18;
Servo servo;
int motorAngle = 0;
int motorAngleOffset = 30;
float controllingFactor = 0.75;
char intAr[6];
char tempAr[6];
char humAr[6];
WiFiClient espClient;
PubSubClient mqttClient(espClient);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
bool isScheduleON = false;
unsigned long scheduleOnTime;
float minimumAngle;
bool isControlFactor = false;
unsigned long controlFactor;
void setup() {
Serial.begin(9900);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.display();
delay(2000);
display.clearDisplay();
print_line("Welcome to MediBox", 8, 20, 2);
delay(2000);
display.clearDisplay();
delay(1000);
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);
timeClient.begin();
timeClient.setTimeOffset(5.5 * 3600);
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
pinMode(BUZZER, OUTPUT);
servo.attach(servoPin, 500, 2400);
setupMqtt();
}
void loop() {
slidingWindow();
Serial.println("---");
delay(1000);
check_temp();
if (!mqttClient.connected()) {
connectToBroker();
}
mqttClient.loop();
mqttClient.publish("ENTSAS1", intAr);
mqttClient.publish("ENTSAS2", tempAr);
mqttClient.publish("ENTSAS3", humAr);
checkSchedule();
}
unsigned long getTime() {
timeClient.update();
return timeClient.getEpochTime();
}
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();
}
void print_temp_and_humid (void) {
TempAndHumidity data = dhtSensor.getTempAndHumidity();
//Serial.println("Temp:" + String(data.temperature,2) + "°C");
//Serial.println ("Humidity:" + String(data.humidity,1) + "%");print_line("Temp:",0,40,1.5);
print_line(String(data.temperature, 2), 30, 40, 1.5);
print_line("C", 60, 40, 1.5);
delay(1000);
print_line("Humidity:", 0, 50, 1.5);
print_line(String(data.humidity, 1), 60, 50, 1.5);
print_line( "%", 90, 50, 1.5);
delay(1000);
}
void check_temp(void) {
TempAndHumidity data = dhtSensor.getTempAndHumidity();
bool all_good = true;
if (data.temperature > 32) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("TEMP HIGH", 0, 40, 1.5);
delay(1000);
}
else if (data.temperature < 26) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("TEMP LOW", 0, 40, 1.5);
delay(1000);
}
if (data.humidity > 80) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("HUMIDITY HIGH", 0, 50, 1.5);
delay(1000);
}
else if (data.humidity < 60) {
all_good = false;
digitalWrite(LED_2, HIGH);
print_line("HUMIDITY LOW", 0, 50, 1.5);
delay(1000);
}
if (all_good) {
digitalWrite(LED_2, LOW);
print_temp_and_humid();
}
String(data.temperature, 2).toCharArray(tempAr, 6);
String(data.humidity, 1).toCharArray(humAr, 6);
}
void slidingWindow() {
int analogValue = analogRead(34);
float voltage = analogValue / 4095. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
float intensity = (lux - 0.1) / 100881.02;
String(intensity, 2).toCharArray(intAr, 6);
Serial.println(intensity);
motorAngleOffset = minimumAngle + 30;
motorAngle = motorAngleOffset + (180 - motorAngleOffset) * intensity * controllingFactor ;
servo.write(motorAngle);
delay(15);
}
void setupMqtt() {
mqttClient.setServer("test.mosquitto.org", 1883);
mqttClient.setCallback(callback);
}
void connectToBroker() {
while (!mqttClient.connected()) {
Serial.println("Attempting to connect MQTT..");
if (mqttClient.connect("ESP32-960507")) {
Serial.println("Connected");
mqttClient.subscribe("ENTSAS-OUT1");
mqttClient.subscribe("ENTSAS-OUT2");
mqttClient.subscribe("MAM");
}
else {
Serial.println("Failed");
Serial.println(mqttClient.state());
delay(500);
}
}
}
void buzzerOn(bool on) {
if (on) {
tone(BUZZER, 256);
} else {
noTone(BUZZER);
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
char payloadCharAr[length];
for (int i = 0; i < length; i++) {
payloadCharAr[i] = (char)payload[i];
}
if (strcmp(topic, "ENTSAS-OUT1") == 0) {
buzzerOn(payloadCharAr[0] == '1');
}
else if (strcmp(topic, "ENTSAS-OUT2") == 0) {
if (payloadCharAr[0] == 'N') {
isScheduleON = false;
} else {
isScheduleON = true;
scheduleOnTime = atol(payloadCharAr);
}
}
String stMessage;
if (strcmp(topic, "MAM") == 0) {
for (int i = 0; i < length; i++) {
stMessage += (char)payload[i];
minimumAngle = stMessage.toFloat();
Serial.print(stMessage);
Serial.print(minimumAngle);
}
}
}
void checkSchedule() {
if (isScheduleON) {
unsigned long currentTime = getTime();
if (currentTime > scheduleOnTime) {
buzzerOn(true);
isScheduleON = false;
mqttClient.publish("ENTSAS-ON-OFF", "1");
mqttClient.publish("ENTSAS-SCH-ON", "0");
}
}
}