Georgeous Abu GhattasAtallah Abu ghattas
Published © LGPL

ESP32 Poultry Farm Monitoring System

A low-cost ESP32 IoT system that monitors poultry water temperature in real time on a 20,000-bird farm, sending alerts and reducing producti

ExpertFull instructions providedOver 3 days9
ESP32 Poultry Farm Monitoring System

Things used in this project

Story

Read more

Schematics

Diagram

Code

Full working code final version

C/C++
#define BLYNK_TEMPLATE_ID   "TMPL4eYo2sC40"
#define BLYNK_TEMPLATE_NAME "Farm Monitor"
#define BLYNK_AUTH_TOKEN    "I6_GzoCxnX204UKD_7_aeXPVpOJdnH9w"

#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <HTTPClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <time.h>

// ====== WiFi ======
char ssid[] = "Khalil";
char pass[] = "920279551";

// ====== DS18B20 ======
#define ONE_WIRE_BUS 26
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// ====== Google Sheets ======
const char* serverName = "https://script.google.com/macros/s/AKfycbzsrIaciRF1ct3iLpT3XgZmvyOvlk3tDOVYzBoWpIoUzpHllf8jrLqgrxz6XGGjEeNo/exec";

// ====== NTP ======
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 7200, 60000);

// ====== Temp Tracking ======
float tempSum = 0;
float tempMin = NAN;
float tempMax = NAN;
int tempCount = 0;

int lowHour, lowMin;
int highHour, highMin;

// ====== Timing ======
unsigned long lastRead = 0;
const unsigned long readInterval = 1000;

unsigned long lastBlynk = 0;
const unsigned long blynkInterval = 180000; // 3 minutes

// ====== Send Tracking ======
int lastSentHour = -1;


// ======================
// SAVE TO GOOGLE SHEETS
// ======================
void saveToSheets(int currentHour, int currentMinute, String currentDate) {

  if (tempCount == 0) return;

  float tempAvg = tempSum / tempCount;

  int blockHour = (currentHour / 1) * 1;
  String blockLabel = String(blockHour < 10 ? "0" : "") + String(blockHour) + ":00";

  String dataRow = "{\"method\":\"append\""
                   ", \"date\":\"" + currentDate + "\""
                   ", \"timestamp\":\"" + blockLabel + "\""
                   ", \"temperature_avg\":" + String(tempAvg, 1) +
                   ", \"temperature_min\":" + String(tempMin, 1) +
                   ", \"temperature_max\":" + String(tempMax, 1) +
                   ", \"low_time\":\"" + String(lowHour < 10 ? "0" : "") + String(lowHour) + ":" + String(lowMin < 10 ? "0" : "") + String(lowMin) + "\""
                   ", \"high_time\":\"" + String(highHour < 10 ? "0" : "") + String(highHour) + ":" + String(highMin < 10 ? "0" : "") + String(highMin) + "\"}";

  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(serverName);
    http.addHeader("Content-Type", "application/json");
    int resp = http.POST(dataRow);
    Serial.print("Sheets row sent, response: ");
    Serial.println(resp);
    http.end();
  }

  // Reset stats
  tempSum = 0;
  tempCount = 0;
  tempMin = NAN;
  tempMax = NAN;
}


// ======================
// CHECK LOGGING
// ======================
void checkLogging(int currentHour, int currentMinute, String currentDate) {

  if (currentHour % 1 == 0 && currentMinute == 0 && currentHour != lastSentHour) {
    lastSentHour = currentHour;
    saveToSheets(currentHour, currentMinute, currentDate);
  }
}


// ======================
// SETUP
// ======================
void setup() {
  Serial.begin(115200);
  sensors.begin();
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  Serial.println("Setup finished");

  timeClient.begin();
  timeClient.update();
}


// ======================
// LOOP
// ======================
void loop() {

  Blynk.run();
  timeClient.update();

  int currentHour   = timeClient.getHours();
  int currentMinute = timeClient.getMinutes();

  time_t epoch = (time_t)timeClient.getEpochTime();
  struct tm *ptm = gmtime(&epoch);
  String currentDate = String(ptm->tm_mday) + "/" + String(ptm->tm_mon + 1) + "/" + String(ptm->tm_year + 1900);

  checkLogging(currentHour, currentMinute, currentDate);

  // ===== Read Temp every 1 second =====
  if (millis() - lastRead >= readInterval) {

    sensors.requestTemperatures();
    float temp = sensors.getTempCByIndex(0);

    if (!isnan(temp) && temp > -50 && temp < 80) {

      tempSum += temp;
      tempCount++;

      if (isnan(tempMax) || temp > tempMax) {
        tempMax = temp;
        highHour = currentHour;
        highMin = currentMinute;
      }

      if (isnan(tempMin) || temp < tempMin) {
        tempMin = temp;
        lowHour = currentHour;
        lowMin = currentMinute;
      }

    } else {
      Serial.println("Invalid temperature reading skipped.");
    }

    lastRead = millis();
  }

  // ===== Blynk every 3 minutes =====
  if (millis() - lastBlynk >= blynkInterval) {

    sensors.requestTemperatures();
    float temp = sensors.getTempCByIndex(0);

    Serial.print("Current Temp: ");
    Serial.println(temp);

    Blynk.virtualWrite(V1, temp);

    if (temp > 30) {
      Blynk.logEvent("high_temp", "🔴 Temperature too high! " + String(temp) + "°C");
    }

    if (temp < 5) {
      Blynk.logEvent("low_temp", "🔵 Temperature too low! " + String(temp) + "°C");
    }

    lastBlynk = millis();
  }

  delay(100);
}

Credits

Georgeous Abu Ghattas
1 project • 1 follower
Atallah Abu ghattas
1 project • 1 follower

Comments