#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
// -------SENSOR PINS---------
#define TEMP_SENSOR 4
#define PH_SENSOR 35
#define WATER_LEVEL 34
// ---SAFE RANGE CONSTANTS FOR FOR FISH POND PARAMETERS-------
#define SAFE_PH_MIN 6.8
#define SAFE_PH_MAX 8.2
#define SAFE_TEMP_MIN 24
#define SAFE_TEMP_MAX 30
#define WATER_OK 80
#define WATER_MID 40
// ------- LEDs FOR SAFE STATUS INDICATION -------------
#define LED_R 15
#define LED_Y 2
#define LED_G 0
#define BUZZER 16
//----------------------------------------
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "Holuwaferanmi"
#define AIO_KEY "aio_oHqM34c3GcbwZMoaNRfIRoCKsgyU"
WiFiClient client;
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 16, 2);
// oneWire instance to communicate with DS18B20 sensor
OneWire oneWire(TEMP_SENSOR);
DallasTemperature tempSensor(&oneWire); // Pass our oneWire reference to Dallas Temperature sensor
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish ph_feed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/ph-level");
Adafruit_MQTT_Publish temp_feed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperature");
Adafruit_MQTT_Publish waterL_feed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/water-level");
float temp;
float pH_val;
const char *water_status[] = {"LOW", "MID", "OK"};
float water_level = 0;
//icon for termometer
byte thermometer_icon[8] =
{
B00100,
B01010,
B01010,
B01110,
B01110,
B11111,
B11111,
B01110
};
byte water_icon[8] = //icon for water droplet
{
B00100,
B00100,
B01010,
B01010,
B10001,
B10001,
B10001,
B01110,
};
void monitorParams(){
// Read temperature from DS18B20 sensor
tempSensor.requestTemperatures();
temp = tempSensor.getTempCByIndex(0);
// Read pH Value
int pH_adc = analogRead(PH_SENSOR);
pH_val = (float)pH_adc * 14.0 / 4095;
// pH_val = map(pH_adc, 0, 4095, 0.0, 14.0);
// Read Water level value
int wLevel_adc = analogRead(WATER_LEVEL);
water_level = map(wLevel_adc, 0, 4095, 100, 0);
}
void display(){
// refresh only if value changes
static float temp_d = temp;
static float pH_val_d = pH_val;
static int water_level_d = water_level;
if (temp_d != temp || pH_val_d != pH_val || water_level_d != water_level){
// LCD.clear();
temp_d = temp;
pH_val_d = pH_val;
water_level_d = water_level;
}
static String pH_status = "Unknown!";
if(pH_val>=6.8 && pH_val<=7.8)
pH_status = "OK";
else if(pH_val<=6.7)
pH_status = "ACIDIC!";
else
pH_status = "ALKALINE!";
LCD.home();
// LCD.print("pH:"+String(pH_val, 1)+" Temp:"+String(temp, 1)+"C ");
LCD.print("pH:");
LCD.print(pH_val, 1);
LCD.print((pH_status=="OK")? " OK" : " "+pH_status+" ");
LCD.setCursor(0, 1);
LCD.write(1);
LCD.print(" " + String(temp, 1) + "C ");
LCD.write(2);
LCD.print(" " + String((uint8_t) water_level)+"% ");
// Turn ON RGB LED accordingly
static uint32_t led_time_prev = millis();
if ((water_level >= WATER_OK) && (temp>=SAFE_TEMP_MIN && temp<=SAFE_TEMP_MAX) && (pH_status == "OK")) {
// Turn ON Green LED
digitalWrite(LED_R, 0);
digitalWrite(LED_Y, 0);
digitalWrite(LED_G, 1);
} else if((water_level>=WATER_MID && water_level<WATER_OK) || (temp>=SAFE_TEMP_MIN-4 && temp<SAFE_TEMP_MIN) || (temp>SAFE_TEMP_MAX && temp<=SAFE_TEMP_MAX+2)) {
// Turn ON Yellow LED
digitalWrite(LED_R, 0);
digitalWrite(LED_Y, 1);
digitalWrite(LED_G, 0);
} else {
// Blink Red LED
if (millis() - led_time_prev >= 100) {
digitalWrite(LED_R, !digitalRead(LED_R));
digitalWrite(BUZZER, !digitalRead(BUZZER));
led_time_prev = millis();
}
digitalWrite(LED_Y, 0);
digitalWrite(LED_G, 0);
}
}
void cloudUpdate() {
static uint32_t prev_time;
const uint32_t update_interval = 5000;
if (millis() - prev_time >= update_interval) {
if (mqtt.connected()) {
// publish all parameters to clou
ph_feed.publish(pH_val);
temp_feed.publish(temp);
waterL_feed.publish(water_level);
} else {
// reconnect to the MQTT server
int8_t status;
if (!mqtt.connected() && WiFi.status() == WL_CONNECTED) {
Serial.print("Connecting to MQTT... ");
if ((status = mqtt.connect()) == 0) {
Serial.println("connected");
} else {
Serial.print("failed, status code =");
Serial.print(mqtt.connectErrorString(status));
Serial.println(" try again in 5 seconds");
}
}
}
prev_time = millis();
}
}
void setup() {
// put you setup code here, to run once:
// Start the DS18B20 sensor
tempSensor.begin();
// LED pins init
pinMode(LED_R, OUTPUT);
pinMode(LED_Y, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(BUZZER, OUTPUT);
digitalWrite(LED_R, 0);
digitalWrite(LED_Y, 0);
digitalWrite(LED_G, 0);
digitalWrite(BUZZER, 1);
// LCD init
LCD.init();
LCD.backlight();
LCD.createChar(1, thermometer_icon);
LCD.createChar(2, water_icon);
LCD.home();
LCD.print(" Fish Pond ");
LCD.setCursor(0, 1);
LCD.print(" Monitor ");
delay(2000);
digitalWrite(BUZZER, 0);
// WiFi Init
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Connecting to ");
LCD.setCursor(0, 1);
LCD.print("WiFi...");
WiFi.begin("Wokwi-GUEST", "", 6);
// Wait 10s max for WiFi fo connect
uint32_t time_start = millis();
while (millis() - time_start <= 10000) {
if (WiFi.status() == WL_CONNECTED){
break;
}
delay(10);
}
LCD.clear();
if (WiFi.status() == WL_CONNECTED){
LCD.print("WiFi Connected!");
} else {
LCD.print("WiFi connection");
LCD.setCursor(0, 1);
LCD.print("Failed !");
}
delay(2000);
LCD.clear();
analogReadResolution(12); // 12-bit resolution
analogSetAttenuation(ADC_11db); // Extend input range to ~3.9V
}
void loop() {
// put your main code here, to run repeatedly:
monitorParams();
display();
cloudUpdate();
// delay(10); // this speeds up the simulation
}
Water Level simulator
pH sensor simulator