5.11 Fattoria Intelligente Controllata via Web

5.11.0 Connettere la scheda ESP32 alla rete

La scheda ESP32 è dotata di Wi-Fi (2.4G) e Bluetooth (4.2), che le consentono di connettersi facilmente al Wi-Fi e comunicare con altri dispositivi sulla rete.

Cosa devi preparare:

  • Un Wi-Fi a 2.4 GHz (può essere un hotspot mobile o un router)

  • Il nome e la password del Wi-Fi

  • Un telefono/IPAD/computer che possa connettersi allo stesso Wi-Fi.

Arduino IDE ti fornisce il file di libreria <WiFi.h>, che supporta le configurazioni Wi-Fi e il monitoraggio della rete Wi-Fi di ESP32.

A. Modalità stazione base (STA o modalità client Wi-Fi): In questa modalità, ESP32 si connette all’hotspot Wi-Fi (AP).

B. Modalità AP (Soft-AP o modalità hotspot Wi-Fi): In questa modalità, altri dispositivi Wi-Fi si connettono a ESP32.

C. Modalità AP-STA: In questa modalità, ESP32 è un hotspot Wi-Fi e un dispositivo Wi-Fi che si connette a un altro hotspot Wi-Fi.

D. Queste modalità sono compatibili con diverse modalità di sicurezza, come WPA, WPA2 e WEP.

E. È in grado di scansionare gli hotspot Wi-Fi, inclusa la scansione attiva e passiva.

F. Supporta la modalità promiscua per monitorare i pacchetti Wi-Fi IEEE802.11.

Per i dettagli sul Wi-Fi, fare riferimento a:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html

Sito ufficiale ESPRESSIF: https://www.espressif.com.cn/en/home

Apri il codice 5.11.0Connect-the-ESP32-to-the-Network con Arduino IDE.

#include <WiFi.h>

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

void setup() {
  Serial.begin(9600);
  //Initialize Wifi
  WiFi.begin(ssid, password);
  //Scan for wifi. If connection fails, stay in connecting, and execute "while" loop
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  //Connected. Print the IP address
  Serial.println("Connected to WiFi");
  Serial.println(WiFi.localIP());
}

void loop() {
}

Cambia your_SSID nel codice con il nome del tuo Wi-Fi e your_PASSWORD con la password del Wi-Fi.

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

Scegli la scheda ESP32 Dev Module e la porta COM, quindi carica il codice.

5458448

Risultato del Test:

Carica il codice e la scheda si connetterà alla rete Wi-Fi e stamperà l’indirizzo IP sul monitor seriale.

image-20250417153507142

5.11.1 Configurare un Sito Web - HELLOWORLD

Finché è connessa al Wi-Fi, la libreria del server Web di ESP32 è in grado di fornire pagine web. Nel seguente codice di esempio, abbiamo configurato un semplice sito web per mostrare “Hello, World!”.

Apri il codice 5.11.1WiFi-HTML-HELLOWORLD con Arduino IDE.

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

WebServer server(80); //Set the server port to 80. Enter the website by IP address rather than the port number.

//Initialize the website
void handleRoot() {
  //Used to send HTTP to the client-side for response, sending 200 means success.
  server.send(200, "text/html", "<h1>Hello, World!</h1>");
}

void setup() {
  Serial.begin(9600);
  //Initialize wifi
  WiFi.begin(ssid, password);
  //Scan for wifi. If connection fails, stay in connecting, and execute "while" loop
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  //Connected. Print the IP address
  Serial.println("Connected to WiFi");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  //Start server
  server.begin();
  Serial.println("Web server started");
}

void loop() {
  server.handleClient();
}

Cambia your_SSID nel codice con il nome del tuo Wi-Fi e your_PASSWORD con la password del Wi-Fi. Quindi carica il codice.

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

Scegli la scheda ESP32 Dev Module e la porta COM, quindi carica il codice.

5458448

Risultato del Test:

In questo codice di esempio, stabiliamo un server Web tramite la libreria WebServer su ESP32. La funzione handleRoot() richiede l’elaborazione nel percorso radice e invia una risposta HTML di “Hello, World!” al lato client. Quindi, setup() imposta la route radice e server.begin() avvia il server Web.

Clicca sul monitor seriale per visualizzare l’indirizzo IP:

image-20250417155849702

NOTA: Quando PC, telefoni cellulari e scheda ESP32 sono connessi a una stessa rete, è possibile visitare questo sito web da PC e telefoni contemporaneamente.

Accedi all’IP nel browser del PC o del telefono:

image-20250417155955349

Nota: Richiede Wi-Fi a 2.4 GHz, non 5G. Il PC o il telefono cellulare che accede all’indirizzo IP deve essere connesso allo stesso Wi-Fi della scheda ESP32.

image-20250417160135272

5.11.2 Fattoria intelligente controllata via web

flo11

Apri il codice 5.11.2WiFi-HTML-Smart-Farm con Arduino IDE.

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <LiquidCrystal_I2C.h>
#include <dht11.h>
#include <ESP32Servo.h>

// Definizioni dei Pin
#define DHT11PIN        17  // Pin del sensore di temperatura e umidità
#define LEDPIN          27  // Pin del LED
#define SERVOPIN        26  // Pin del Servo
#define FANPIN1         19  // Pin IN+ della ventola
#define FANPIN2         18  // Pin IN- della ventola
#define STEAMPIN        35  // Pin del sensore di vapore
#define LIGHTPIN        34  // Pin della fotoresistenza
#define SOILHUMIDITYPIN 32  // Pin del sensore di umidità del suolo
#define WATERLEVELPIN   33  // Pin del sensore di livello dell'acqua
#define RELAYPIN        25  // Pin del relè

// Inizializza sensori e componenti
dht11 DHT11;
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myservo;  // Oggetto Servo per controllare il servo

// Credenziali WiFi
const char *SSID = "your_SSID";
const char *PASS = "your_PASSWORD";

// Crea oggetto WebServer
WebServer server(80);

// Variabili per il controllo degli stati
static int A = 0;
static int B = 0;
static int C = 0;

// Contenuto della pagina Web HTML
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<title>TEST HTML ESP32</title>
<head>
  <meta charset="utf-8">
  <style>
    html, body {
      margin: 0;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      background-color: #f0f0f0;
    }

    /* Il contenitore principale dei pulsanti */
    .btn {
      display: flex;
      justify-content: center;  /* Centra i pulsanti */
      gap: 10px;  /* Aggiunge spazio tra i pulsanti */
      width: 320px;  /* Imposta la larghezza per assicurare che i pulsanti siano ben raggruppati */
      flex-wrap: wrap; /* Permette ai pulsanti di andare a capo se necessario */
      margin-bottom: 20px;  /* Spazio tra i pulsanti e la visualizzazione dei dati */
    }

    /* Stile del pulsante */
    .btn button {
      width: 70px;  /* Imposta la larghezza per i pulsanti */
      height: 70px;  /* Imposta l'altezza per i pulsanti */
      border: none;
      font-size: 16px;
      color: #fff;
      background-color: #89e689;
      cursor: pointer;
    }

    .btn button:active {
      top: 2px;
    }

    /* L'area di visualizzazione dei dati */
    #dht {
      text-align: center;  /* Centra il testo */
      width: 320px;  /* Stessa larghezza del contenitore dei pulsanti */
      color: #fff;
      background-color: #47a047;
      font-size: 18px; /* Regola la dimensione del carattere per la leggibilità */
      padding: 10px;
      border-radius: 10px;  /* Angoli arrotondati */
      box-sizing: border-box;
      margin-bottom: 10px; /* Aggiunge spazio tra la visualizzazione dei dati e i pulsanti */
    }

  </style>
</head>
<body>

  <!-- Area di visualizzazione per i dati del sensore -->
  <div id="dht"></div>

  <!-- Riga di pulsanti -->
  <div class="btn">
    <button id="btn-led" onclick="setLED()">LED</button>
    <button id="btn-fan" onclick="setFan()">Ventola</button>
    <button id="btn-feeding" onclick="setFeeding()">Alimentazione</button>
    <button id="btn-watering" onclick="setWatering()">Irrigazione</button>
  </div>

  <script>
    function setLED() {
      var payload = "A"; 
      var xhr = new XMLHttpRequest();
      xhr.open("GET", "/set?value=" + payload, true);
      xhr.send();
    }
    function setFan() {
      var payload = "B"; 
      var xhr = new XMLHttpRequest();
      xhr.open("GET", "/set?value=" + payload, true);
      xhr.send();
    }
    function setFeeding() {
      var payload = "C"; 
      var xhr = new XMLHttpRequest();
      xhr.open("GET", "/set?value=" + payload, true);
      xhr.send();
    }
    function setWatering() {
      var payload = "D"; 
      var xhr = new XMLHttpRequest();
      xhr.open("GET", "/set?value=" + payload, true);
      xhr.send();
    }

    setInterval(function () {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById("dht").innerHTML = this.responseText;
        }
      };
      xhttp.open("GET", "/dht", true);
      xhttp.send();
    }, 1000)
  </script>

</body>
</html>

)rawliteral";

// Funzione per unire i dati del sensore in formato HTML
String Merge_Data(void) {
  String dataBuffer;
  String Humidity;
  String Temperature;
  String Steam;
  String Light;
  String SoilHumidity;
  String WaterLevel;
  
  // Leggi il sensore DHT11
  int chk = DHT11.read(DHT11PIN);
  
  // Leggi altri sensori
  Steam = String(analogRead(STEAMPIN) / 4095.0 * 100);
  Light = String(analogRead(LIGHTPIN));
  int shvalue = analogRead(SOILHUMIDITYPIN) / 4095.0 * 100 * 2.3;
  shvalue = shvalue > 100 ? 100 : shvalue;
  SoilHumidity = String(shvalue);
  int wlvalue = analogRead(WATERLEVELPIN) / 4095.0 * 100 * 2.5;
  wlvalue = wlvalue > 100 ? 100 : wlvalue;
  WaterLevel = String(wlvalue);
  Temperature = String(DHT11.temperature);
  Humidity = String(DHT11.humidity);
  
  // Costruisci il contenuto HTML
  dataBuffer += "<p>";
  dataBuffer += "<h1>Dati Sensore</h1>";
  dataBuffer += "<b>Temperatura:</b><b>" + Temperature + "</b><b>℃</b><br/>";
  dataBuffer += "<b>Umidità:</b><b>" + Humidity + "</b><b>%rh</b><br/>";
  dataBuffer += "<b>Livello Acqua:</b><b>" + WaterLevel + "</b><b>%</b><br/>";
  dataBuffer += "<b>Vapore:</b><b>" + Steam + "</b><b>%</b><br/>";
  dataBuffer += "<b>Luce:</b><b>" + Light + "</b><br/>";
  dataBuffer += "<b>Umidità del Suolo:</b><b>" + SoilHumidity + "</b><b>%</b><br/>";
  dataBuffer += "</p>";

return dataBuffer;
}

// Configura le azioni in base alle richieste HTTP ricevute
void Config_Callback() {
  if (server.hasArg("value")) {
    String HTTP_Payload = server.arg("value");
    Serial.printf("[%lu]%s\r\n", millis(), HTTP_Payload.c_str());

    if (HTTP_Payload == "A") {
      if (A) {
        digitalWrite(LEDPIN, LOW);
        A = 0;
      } else {
        digitalWrite(LEDPIN, HIGH);
        A = 1;
      }
    }

    if (HTTP_Payload == "B") {
      if (B) {
        digitalWrite(FANPIN1, LOW);
        digitalWrite(FANPIN2, LOW);
        B = 0;
      } else {
        delay(500);
        digitalWrite(FANPIN1, HIGH);
        digitalWrite(FANPIN2, LOW);
        delay(500);
        B = 1;
      }
    }

    if (HTTP_Payload == "C") {
      if (C) {
        myservo.write(80);
        delay(500);
        C = 0;
      } else {
        C = 1;
        myservo.write(180);
        delay(500);
      }
    }

    if (HTTP_Payload == "D") {
      digitalWrite(RELAYPIN, HIGH);
      delay(400);
      digitalWrite(RELAYPIN, LOW);
      delay(650);
    }
  }
  server.send(200, "text/plain", "OK");
}

// Gestisce l'accesso a URL non validi
void notFound() {
  server.send(404, "text/plain", "Not found");
}

void setup() {
  Serial.begin(9600);
  
  // Connessione al WiFi
  WiFi.begin(SSID, PASS);
  while (!WiFi.isConnected()) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connesso.");
  Serial.println("Indirizzo IP: ");
  Serial.println(WiFi.localIP());

  // Configura i pin
  pinMode(LEDPIN, OUTPUT);
  pinMode(STEAMPIN, INPUT);
  pinMode(LIGHTPIN, INPUT);
  pinMode(SOILHUMIDITYPIN, INPUT);
  pinMode(WATERLEVELPIN, INPUT);
  pinMode(RELAYPIN, OUTPUT);
  pinMode(FANPIN1, OUTPUT);
  pinMode(FANPIN2, OUTPUT);

  delay(1000);

  // Collega il servo al pin
  myservo.attach(SERVOPIN);
  myservo.write(180);

  // Inizializza LCD
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("IP:");
  lcd.setCursor(0, 1);
  lcd.print(WiFi.localIP());

  // Configura i percorsi del server
  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", index_html);
  });

  server.on("/dht", HTTP_GET, []() {
    server.send(200, "text/plain", Merge_Data().c_str());
  });

  server.on("/set", HTTP_GET, Config_Callback);
  server.onNotFound(notFound);

  // Avvia il server
  server.begin();
}

void loop() {
  server.handleClient();
}

Cambia your_SSID nel codice con il nome del tuo wifi e your_PASSWORD con la password del wifi. Quindi carica il codice.

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

Scegli la scheda ESP32 Dev Module e la porta COM, quindi carica il codice.

5458448

Risultato del test:

NOTA: Quando PC, telefoni cellulari e scheda ESP32 sono connessi a una rete, è possibile visitare questo sito web su PC e telefoni contemporaneamente.

Visualizza l’indirizzo IP da LCD1602:

image-20250417161040242

Inserisci l’indirizzo IP nei browser dei telefoni cellulari o del PC, potrai vedere i valori dei sensori nella parte superiore della pagina e controllare il LED, la ventola, la cabina di alimentazione e la pompa dell’acqua con i pulsanti sottostanti.

cou117

Nota: Richiede WIFI a 2.4 GHz, non 5G. Il PC o il telefono cellulare che accede all’indirizzo IP deve essere connesso allo stesso WIFI della scheda ESP32.

image-20250417160135272