Automatsko zalivanje bašte sa ESP32 i Wi-Fi-jem

Lekcija 17 od 17 · Arduino i ESP32

U lekciji automatsko zalivanje sa Arduinom bašta se zalivala sama, ali smo stanje videli samo u Serial Monitor-u. ESP32 ima ugrađen Wi-Fi, pa može da napravi malu veb stranu: na telefonu vidiš vlažnost zemlje, da li pumpa radi, i možeš da je pokreneš jednim dodirom. Pumpu i relej već poznaješ iz lekcije pumpa za vodu sa ESP32.

Razlike u odnosu na Arduino Uno

Arduino UnoESP32
napon pinova5 V3,3 V – ulaz ne sme da dobije više
analogni ulazA0, vrednosti 0–1023GPIO34 (ADC1), vrednosti 0–4095
napajanje senzora5V3V3 (kapacitivni senzor v1.2 radi i na 3,3 V)
relejobičan 5 V modulmodul koji pouzdano radi sa signalom od 3,3 V
mrežanemaWi-Fi i Bluetooth
Zašto GPIO34? Pinovi grupe ADC2 ne mogu da se koriste za analogno merenje dok je Wi-Fi uključen. GPIO32–39 pripadaju grupi ADC1 i rade i sa Wi-Fi-jem. GPIO34 je samo ulazni pin – idealan za senzor.

Povezivanje

SENZOR VLAŽNOSTI     ESP32
VCC  --------------> 3V3
GND  --------------> GND
AOUT --------------> GPIO34

RELEJ MODUL          ESP32
VCC  --------------> VIN (5 V sa USB-a)
GND  --------------> GND
IN   --------------> GPIO23

BATERIJA (+) -> COM releja,  NO releja -> (+) pumpe,  (-) pumpe -> BATERIJA (-)

Relej modul napajamo sa pina VIN (5 V iz USB kabla), a upravljamo ga signalom od 3,3 V sa GPIO23. Ako relej „klikće“ nepouzdano, potreban je modul predviđen za 3,3 V logiku.

Kalibracija

Kao i kod Arduina, prvo izmeri vrednosti SUVO (senzor na vazduhu) i MOKRO (senzor u čaši vode). Kod ESP32 brojevi su veći jer je opseg 0–4095 – na primer oko 3000 na vazduhu i oko 1300 u vodi. Za merenje možeš da koristiš program iz lekcije o LDR senzoru – samo ga ostavi na GPIO34.

Program

U program upiši ime svoje Wi-Fi mreže i lozinku, kao i svoje vrednosti kalibracije. Posle učitavanja otvori Serial Monitor (115200): ESP32 će ispisati adresu, na primer http://192.168.1.45. Otvori je na telefonu ili računaru u istoj Wi-Fi mreži.

// ESP32 – automatsko zalivanje sa veb stranom (Wi-Fi)
#include <WiFi.h>
#include <WebServer.h>

const char* SSID    = "IME_MREZE";      // upiši ime svoje Wi-Fi mreže
const char* LOZINKA = "LOZINKA";        // i lozinku

const int SENZOR_PIN = 34;              // analogni ulaz (ADC1), samo ulaz
const int RELEJ_PIN  = 23;
const int RELEJ_UKLJ  = HIGH;           // za LOW-trigger relej zameni HIGH i LOW
const int RELEJ_ISKLJ = LOW;

const int SUVO  = 3000;                 // kalibracija: senzor na vazduhu (0–4095)
const int MOKRO = 1300;                 // kalibracija: senzor u čaši vode
const int PRAG  = 35;                   // ispod 35 % zemlja je suva

const unsigned long PORCIJA_MS  = 3000;     // pumpa radi 3 s
const unsigned long UPIJANJE_MS = 30000;    // pauza za upijanje 30 s

WebServer server(80);

int  vlaznost = 0;
bool pumpaRadi = false;
bool automatski = true;
unsigned long pumpaUkljucena = 0;
unsigned long krajZalivanja = 0;
unsigned long poslednjeMerenje = 0;

int procitajVlaznost() {
  long zbir = 0;
  for (int i = 0; i < 10; i++) {
    zbir += analogRead(SENZOR_PIN);
    delay(2);
  }
  int procenat = map(zbir / 10, SUVO, MOKRO, 0, 100);
  return constrain(procenat, 0, 100);
}

void pumpa(bool ukljuci) {
  digitalWrite(RELEJ_PIN, ukljuci ? RELEJ_UKLJ : RELEJ_ISKLJ);
  pumpaRadi = ukljuci;
  if (ukljuci) pumpaUkljucena = millis();
  else krajZalivanja = millis();
}

String stranica() {
  String s = "<!DOCTYPE html><html><head><meta charset='utf-8'>";
  s += "<meta name='viewport' content='width=device-width'>";
  s += "<meta http-equiv='refresh' content='5'><title>Basta</title></head><body>";
  s += "<h1>Pametna basta</h1>";
  s += "<p>Vlaznost zemlje: <b>" + String(vlaznost) + " %</b></p>";
  s += "<p>Pumpa: <b>" + String(pumpaRadi ? "radi" : "ne radi") + "</b></p>";
  s += "<p>Automatski rezim: <b>" + String(automatski ? "ukljucen" : "iskljucen") + "</b></p>";
  s += "<p><a href='/zalij'>Zalij sada</a> | <a href='/auto'>Promeni rezim</a></p>";
  s += "</body></html>";
  return s;
}

void nazadNaPocetnu() {
  server.sendHeader("Location", "/");
  server.send(303, "text/plain", "");
}

void setup() {
  Serial.begin(115200);
  pinMode(RELEJ_PIN, OUTPUT);
  digitalWrite(RELEJ_PIN, RELEJ_ISKLJ);

  WiFi.begin(SSID, LOZINKA);
  Serial.print("Povezivanje");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Otvori u pregledacu: http://");
  Serial.println(WiFi.localIP());

  server.on("/", []() { server.send(200, "text/html", stranica()); });
  server.on("/zalij", []() { if (!pumpaRadi) pumpa(true); nazadNaPocetnu(); });
  server.on("/auto", []() { automatski = !automatski; nazadNaPocetnu(); });
  server.begin();
}

void loop() {
  server.handleClient();                       // odgovaramo pregledaču

  if (millis() - poslednjeMerenje >= 1000) {   // merenje jednom u sekundi
    poslednjeMerenje = millis();
    vlaznost = procitajVlaznost();
    Serial.println(vlaznost);
  }

  // pumpa se sama gasi posle jedne porcije
  if (pumpaRadi && millis() - pumpaUkljucena >= PORCIJA_MS) {
    pumpa(false);
  }

  // automatski režim: suva zemlja i prošlo je vreme za upijanje
  if (automatski && !pumpaRadi && vlaznost < PRAG &&
      millis() - krajZalivanja >= UPIJANJE_MS) {
    pumpa(true);
  }
}

Zašto ovde nema delay(30000)?

Veb server mora stalno da odgovara pregledaču – to radi server.handleClient() u petlji. Kada bismo pisali delay(30000) kao u Arduino verziji, strana se 30 sekundi ne bi otvarala. Zato vreme merimo funkcijom millis() (broj milisekundi od uključenja) i samo proveravamo „da li je prošlo dovoljno vremena“:

  • pumpa se gasi kada od uključenja prođe PORCIJA_MS;
  • nova porcija može tek kada od poslednjeg zalivanja prođe UPIJANJE_MS;
  • vlažnost se meri jednom u sekundi.

Veb strana

  • server.on("/", …) – na adresi / šalje stranu sa vlažnošću i stanjem pumpe. Strana se sama osvežava na 5 sekundi (meta refresh).
  • /zalij – pokreće jednu porciju zalivanja, pa vraća na početnu stranu.
  • /auto – uključuje ili isključuje automatski režim (npr. kada presađuješ biljku).
Bezbednost: stranu vidi svako u tvojoj Wi-Fi mreži. Za školski projekat to je u redu, ali uređaj ne „otvaraj“ prema internetu bez zaštite lozinkom.

Zadaci za vežbu

  1. Dodaj na stranu i broj zalivanja od uključenja.
  2. Dodaj zaštitu iz Arduino verzije: posle 5 porcija zaredom bez uspeha, isključi automatski režim i na strani ispiši upozorenje.
  3. Dodaj na stranu dugme „Stop“ koje odmah gasi pumpu.
  4. Istraži: kako bi ESP32 slao vlažnost na neki IoT servis da bi se videla i van kuće? (vidi lekcije o Internetu stvari)

Proveri znanje

Otvori kviz

Kviz: zalivanje sa ESP32

1. Zašto se senzor vezuje na GPIO34?




2. Koji opseg vraća analogRead() na ESP32?




3. Zašto se u programu ne koristi delay(30000)?




4. Ko može da otvori veb stranu bašte?