#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include "pitches.h"
#include <NewPing.h>
#include "thingProperties.h"
#include <HardwareSerial.h>
#define SCREEN_WIDTH 20
#define SCREEN_HEIGHT 4
#define DHT_PIN 18
#define TRIG_PIN 15
#define ECHO_PIN 13
#define BUZZER_PIN 12
#define GREEN_LED_PIN 33
#define RED_LED_PIN 32
#define RELAY_PIN 4
#define BUZZER_CHANNEL 0
#define BUZZER_RESOLUTION 8
#define BUZZER_FREQUENCY 1000
const int maxDistance = 600; // maxDistance=h*2,h=300mm
const int minIVLevel = 200;
const int maxIVLevel = 500;
const float minTemperature = 32.0;
const float maxTemperature = 38.0;
const float minHumidity = 40.0;
const float maxHumidity = 60.0;
bool isBuzzerActivated = false; // Global variable to track buzzer
unsigned long previousMillisLCD = 0;
const unsigned long lcdInterval = 1000;
const long smsInterval = 1000;
const unsigned long smsDelay = 100;
unsigned long previousMillisSMS = 0;
const unsigned long loopDelay = 1000;
unsigned long previousMillisLoop = 0;
int messageCountSent = 0;
int messageCountReceived = 0;
int totalDeletedMessages = 0;
DHT dht(DHT_PIN, DHT22);
NewPing sonar(TRIG_PIN, ECHO_PIN, maxDistance);
HardwareSerial sim800l(2);
LiquidCrystal_I2C lcd(0x27, SCREEN_WIDTH, SCREEN_HEIGHT); // I2C address may vary
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4};
int noteDurations[] = {
4, 8, 8, 4, 4, 4, 4, 4};
unsigned long previousMillisMelody = 0;
const long melodyInterval = 1000;
//float IV_levelMm;
void setup()
{
lcd.init(); // Initialize LCD
lcd.backlight(); // Turn on backlight
displayInstrument("Eng Joel Odero", "INCUBATOR MONITORING", "BASED ON ESP32 IOT", "WELCOME!!!", 2000);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
Serial.begin(115200);
sim800l.begin(9600, SERIAL_8N1, 16, 17);
sim800l.begin(9600);
dht.begin();
// Initialize Arduino Cloud
initProperties();
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
ledcSetup(BUZZER_CHANNEL, BUZZER_FREQUENCY, BUZZER_RESOLUTION);
ledcAttachPin(BUZZER_PIN, BUZZER_CHANNEL);
}
void loop()
{
unsigned long currentMillis = millis();
ArduinoCloud.update();
temperature = dht.readTemperature();
humidity = dht.readHumidity();
// Get Ultrasonic Distance and update IV_levelMm
IV_levelMm = getUltrasonicDistance();
checkSMSCommands();
updateIVPumpStatus();
sendSensorDataSMS();
deleteAllSMS();
// Check sensor limits and perform actions
checkSensorLimits(temperature, humidity, IV_levelMm);
activateBuzzer(temperature, humidity, IV_levelMm);
bool buzzerActivated = isBuzzerOn(temperature, humidity, IV_levelMm);
controlLEDs(buzzerActivated, temperature, humidity, IV_levelMm);
// Delete all SMS messages and print the number of deleted messages
int deletedMessages = deleteAllSMS();
totalDeletedMessages += deletedMessages;
//Serial.print("Deleted Messages: ");
//Serial.print(deletedMessages);
// Automatic control based on IV level
if (!isSwitchOnCloud) { // Check if the switch on cloud is OFF
// Control IV pump based on IV level
if (IV_levelMm < minIVLevel && !isIVPumpOn) {
turnOnPump();
Serial.println("Switched to Automatic Control");
} else if (IV_levelMm >= maxIVLevel && isIVPumpOn) {
turnOffPump();
Serial.println("Switched to Manual Control");
} else if (IV_levelMm > minIVLevel && IV_levelMm < maxIVLevel && isIVPumpOn) {
turnOffPump();
}
}
controlPump(IV_levelMm); // Control IV pump based on IV_level
displayOnLCD(temperature, humidity, IV_levelMm, digitalRead(RELAY_PIN));
printSensorValues(temperature, humidity, IV_levelMm, digitalRead(RELAY_PIN), isBuzzerOn(temperature, humidity, IV_levelMm));
if (currentMillis - previousMillisMelody >= melodyInterval)
{
previousMillisMelody = currentMillis;
playMelody(temperature, humidity, IV_levelMm); // Play melody at regular intervals
}
if (currentMillis - previousMillisLCD >= lcdInterval)
{
previousMillisLCD = currentMillis;
lcd.clear();
}
// Add a delay of 2000ms (2 seconds) using millis
if (currentMillis - previousMillisLoop >= loopDelay)
{
previousMillisLoop = currentMillis;
// Your existing loop code goes here
}
}
void activateBuzzer(float temperature, float humidity, float IV_levelMm)
{
if (temperature > maxTemperature || temperature < minTemperature ||
humidity > maxHumidity || humidity < minHumidity ||
IV_levelMm < minIVLevel || IV_levelMm > maxIVLevel)
{
Serial.println("Buzzer ON!");
ledcWrite(BUZZER_CHANNEL, 255); // Activate buzzer when conditions are met
}
else
{
Serial.println("Buzzer OFF!");
ledcWrite(BUZZER_CHANNEL, 0); // Deactivate buzzer otherwise
}
}
void controlLEDs(bool isBuzzerActivated, float temperature, float humidity, float IV_levelMm)
{
if (isBuzzerActivated)
{
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(GREEN_LED_PIN, LOW);
}
else
{
if (temperature > maxTemperature || temperature < minTemperature ||
humidity > maxHumidity || humidity < minHumidity ||
IV_levelMm < minIVLevel || IV_levelMm > maxIVLevel)
{
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(GREEN_LED_PIN, LOW);
}
else
{
digitalWrite(GREEN_LED_PIN, HIGH);
digitalWrite(RED_LED_PIN, LOW);
}
}
}
void controlPump(float IV_levelMm)
{
if (IV_levelMm < minIVLevel)
{
digitalWrite(RELAY_PIN, HIGH); // Turn on pump when IV_level < 100mm
}
else if (IV_levelMm > maxIVLevel)
{
digitalWrite(RELAY_PIN, LOW); // Turn off pump when IV_level > 350mm
}
else
{
digitalWrite(RELAY_PIN, LOW); // Ensure pump is off when IV_level is between 500mm and 1000mm
}
}
void displayOnLCD(float temperature, float humidity, float IV_levelMm, bool isIVPumpOn)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temperature: ");
lcd.print(temperature);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.print(humidity);
lcd.print(" %");
lcd.setCursor(0, 2);
lcd.print("IV_level: ");
lcd.print(IV_levelMm);
lcd.print(" mm");
lcd.setCursor(0, 3);
lcd.print("IV PUMP: ");
lcd.print(isIVPumpOn ? "ON" : "OFF");
// Add a delay of 10ms (0.01 second)
unsigned long currentMillis = millis();
unsigned long delayMillis = 10;
while (millis() - currentMillis < delayMillis) {
// Waiting for the specified delay
// You can add additional tasks here if needed
}
}
void displayInstrument(String instrument, String name, String basis, String welcome, int duration)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(instrument);
lcd.setCursor(0, 1);
lcd.print(name);
lcd.setCursor(0, 2);
lcd.print(basis);
lcd.setCursor(0, 3);
lcd.print(welcome);
unsigned long startMillis = millis();
unsigned long currentMillis = startMillis;
// Add a delay using millis
while (currentMillis - startMillis < duration) {
// You can add additional tasks here if needed
currentMillis = millis();
}
lcd.clear();
}
void printSensorValues(float temperature, float humidity, float IV_levelMm, bool isIVPumpOn, bool isBuzzerOn) {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print("°C, Humidity: ");
Serial.print(humidity);
Serial.print("%, IV_level: ");
Serial.print(IV_levelMm);
Serial.print("mm, IV PUMP: ");
Serial.print(isIVPumpOn ? "ON" : "OFF");
Serial.print(", BUZZER: ");
Serial.println(isBuzzerOn ? "ON" : "OFF");
unsigned long currentMillis = millis();
unsigned long delayMillis = 1000;
while (millis() - currentMillis < delayMillis) {
// Waiting for the specified delay
// You can add additional tasks here if needed
}
}
float getUltrasonicDistance()
{
static unsigned long previousMillis = 0;
const unsigned long measurementInterval = 100; // Set your desired interval in milliseconds
unsigned long currentMillis = millis();
// Initialize IV_levelMm
float IV_levelMm = 0;
// Check if it's time to perform the ultrasonic measurement
if (currentMillis - previousMillis >= measurementInterval)
{
// Trigger the ultrasonic sensor
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Perform the measurement and return the distance in centimeters
float distanceCm = sonar.ping_cm();
// Convert distance to millimeters
float distanceMm = distanceCm * 10;
// Calculate IV_levelMm
IV_levelMm = maxDistance - distanceMm;
// Update the previousMillis for the next measurement
previousMillis = currentMillis;
}
return IV_levelMm;
}
bool isBuzzerOn(float temperature, float humidity, float IV_levelMm)
{
bool buzzerStatus = false; // Initialize buzzer status
if (temperature > maxTemperature || temperature < minTemperature ||
humidity > maxHumidity || humidity < minHumidity ||
IV_levelMm < minIVLevel || IV_levelMm > maxIVLevel)
{
buzzerStatus = true; // Activate buzzer when conditions are met
}
return buzzerStatus;
}
void playMelody(float temperature, float humidity, float IV_levelMm)
{
if (temperature > maxTemperature || temperature < minTemperature ||
humidity > maxHumidity || humidity < minHumidity ||
IV_levelMm < minIVLevel || IV_levelMm > maxIVLevel)
{
int noteDuration;
int pauseBetweenNotes;
for (int thisNote = 0; thisNote < 8; thisNote++)
{
noteDuration = 1000 / noteDurations[thisNote];
tone(BUZZER_PIN, melody[thisNote], noteDuration);
pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(BUZZER_PIN);
}
}
}
void checkSensorLimits(float temperature, float humidity, float IV_levelMm)
{
if (temperature > maxTemperature)
{
displayWarning("High Temperature Warning!");
}
else if (temperature < minTemperature)
{
displayWarning("Low Temperature Warning!");
}
if (humidity > maxHumidity)
{
displayWarning("High Humidity Warning!");
}
else if (humidity < minHumidity)
{
displayWarning("Low Humidity Warning!");
}
if (IV_levelMm > maxIVLevel)
{
displayWarning("High IV Level Warning!");
}
else if (IV_levelMm < minIVLevel)
{
displayWarning("Low IV Level Warning!");
}
isBuzzerActivated = isBuzzerOn(temperature, humidity, IV_levelMm);
if (isBuzzerActivated)
{
activateBuzzer(temperature, humidity, IV_levelMm);
}
}
void displayWarning(String warning)
{
Serial.println("Warning: " + warning);
}
void onIsSwitchOnCloudChange() {
if (isSwitchOnCloud) {
turnOnPump();
Serial.println("Switched to Manual Control");
} else {
turnOffPump();
Serial.println("Switched to Automatic Control");
}
}
void turnOnPump() {
digitalWrite(RELAY_PIN, HIGH);
}
void turnOffPump() {
digitalWrite(RELAY_PIN, LOW);
}
void updateIVPumpStatus() {
isIVPumpOn = (digitalRead(RELAY_PIN) == HIGH);
}
void sendSensorDataSMS() {
sendSMS("Temperature: " + String(temperature) + " °C");
sendSMS("Humidity: " + String(humidity) + " %");
sendSMS("IV Level: " + String(IV_levelMm) + " mm");
sendSMS("Pump Status: " + String(isIVPumpOn ? "ON" : "OFF"));
sendSMS("Buzzer Status: " + String(digitalRead(BUZZER_PIN) == HIGH ? "Activated" : "Not Activated"));
}
void checkSMSCommands() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillisSMS >= smsInterval) {
previousMillisSMS = currentMillis;
while (sim800l.available()) {
String sms = sim800l.readStringUntil('\n');
processSMSCommand(sms);
messageCountReceived++;
}
deleteAllSMS();
}
}
void processSMSCommand(String command) {
command.trim();
if (command.startsWith("T")) {
sendTemperatureSMS();
} else if (command.startsWith("H")) {
sendHumiditySMS();
} else if (command.startsWith("I")) {
sendIVLevelSMS();
} else if (command.startsWith("P")) {
sendIVPumpStatusSMS();
} else if (command.startsWith("B")) {
sendBuzzerStatusSMS();
} else if (command.startsWith("C")) {
sendConditionsSMS();
} else if (command.startsWith("ON")) {
turnOnPump();
sendSMS("Pump turned ON");
} else if (command.startsWith("OFF")) {
turnOffPump();
sendSMS("Pump turned OFF");
}
}
void sendTemperatureSMS() {
String message = "Temperature: " + String(temperature) + " °C";
sendSMS(message);
}
void sendHumiditySMS() {
String message = "Humidity: " + String(humidity) + " %";
sendSMS(message);
}
void sendIVLevelSMS() {
String message = "IV Level: " + String(IV_levelMm) + " mm";
sendSMS(message);
}
void sendIVPumpStatusSMS() {
String message = "IV Pump Status: " + String(isIVPumpOn ? "ON" : "OFF");
sendSMS(message);
}
void sendBuzzerStatusSMS() {
String message = "Buzzer Status: " + String(digitalRead(BUZZER_PIN) == HIGH ? "Activated" : "Not Activated");
sendSMS(message);
}
void sendConditionsSMS() {
String conditions = "Normal conditions. Incubator is okay. Infant is fine.";
if (isBuzzerActivated) {
conditions = "Abnormal conditions. Incubator not at optimum. Infant not fine.";
}
String message = "Conditions: " + conditions;
sendSMS(message);
}
void sendSMS(String message) {
sim800l.println("AT+CMGF=1");
waitMillis(smsDelay);
sim800l.println("AT+CMGS=\"+254113405308\"");
waitMillis(smsDelay);
sim800l.println(message);
waitMillis(smsDelay);
sim800l.write(26);
waitMillis(smsDelay);
// Increment the message count
messageCountSent++;
// Delete all SMS messages
deleteAllSMS();
}
void waitMillis(unsigned long duration) {
static unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= duration) {
// Reset the timer
previousMillis = currentMillis;
// Perform the task that should happen after the specified duration
// (e.g., send a command, toggle something, etc.)
}
}
int deleteAllSMS() {
// Send the AT+CMGDA command to delete all SMS messages from SIM800L memory
sim800l.write("AT+CMGDA=4,DEL ALL\r\n");
waitMillis(smsDelay);
// Read and parse the response to get the number of deleted messages
int deletedMessages = 0;
while (sim800l.available()) {
String response = sim800l.readStringUntil('\n');
if (response.indexOf("DELETED") != -1) {
deletedMessages++;
}
}
return deletedMessages;
}