Serwisy partnerskie:
Close icon
Serwisy partnerskie

Samouczek serwera WWW ESP32

Article Image
Elmax
Jednym z najciekawszych projektów jakie możemy zbudować ucząc się pracy z płytką opartą o Wi-Fi jest serwer WWW. Pokażemy jak zbudować prosty serwer WWW z ESP32.

Serwer WWW jest zasadniczo urządzeniem, które przechowuje, przetwarza i dostarcza strony internetowe do klientów internetowych, które mogą obejmować od przeglądarek na naszych laptopach do aplikacji mobilnych na naszych smartfonach. Komunikacja między klientem a serwerem odbywa się za pomocą specjalnego protokołu zwanego Hypertext Transfer Protocol (HTTP). Klient używa adresu URL do złożenia żądania o konkretną stronę, a serwer odpowiada treścią tej strony lub komunikatem o błędzie, jeśli strona nie jest dostępna.

W naszym przypadku, zamiast odpowiadać konkretną stroną internetową, adres URL będzie wykorzystywany do sterowania stanem diod LED podłączonych do ESP, a dokonane zmiany będą aktualizowane na stronie internetowej. Na przykład, jeśli adres URL taki jak "http://192.168.1.1/ledon" zostanie wpisany do przeglądarki, serwer WWW zrozumie, że nadszedł czas, aby włączyć diodę LED, a następnie zaktualizuje stan diody LED do "ON" na stronie internetowej. To samo stanie się, gdy dioda będzie musiała się wyłączyć.

Po zakończeniu tego projektu- kursu będziesz  wiedział, jak skonfigurować serwer WWW na ESP32 i połączyć się z nim za pomocą klienta (strony internetowej), aby sterować jego pinami GPIO.

Wykaz elementów
Ilość
Symbol
Nazwa/opis/gdzie kupić

Płytka DOIT Devkit V1 ESP32 została użyta w tym projekcie ze względu na jej oczywistą popularność wśród konstruktorów. Możesz użyć dowolnej innej płytki opartej na ESP32 do tego projektu.

Schemat

Schemat dla tego projektu jest dość prosty. Jak wspomnieliśmy wcześniej, będziemy przełączać diody LED, aby zademonstrować co można osiągnąć używając serwera WWW NodeMCU i chociaż diody LED są tutaj używane, możesz zdecydować się na użycie bardziej użytecznych komponentów, takich jak przekaźnik, który może dać Ci możliwość zdalnego sterowania urządzeniami w Twoim domu. Podłącz komponenty tak jak pokazano poniżej.

Schemat podłączenia elementów do modułu DOIT Devkit V1 ESP32

Dodatnie nóżki zielonej i czerwonej diody LED są podłączone do pinów GPIO 26 i 27 na ESP32 (odpowiednio), podczas gdy ich ujemne nóżki są podłączone do masy przez rezystor 220 omów, aby ograniczyć natężenie prądu płynącego przez diody LED.

Mając gotowy schemat, możemy teraz przejść do kodu projektu.

Kod

Do stworzenia szkicu dzisiejszego projektu użyjemy Arduino IDE ze względu na jego wszechstronność, ogromne wsparcie i popularność. Aby móc to zrobić, należy zainstalować pliki wspierające płytkę ESP32 w Arduino IDE. Algorytm działania polega na podłączeniu ESP32 do punktu dostępowego i wygenerowaniu adresu IP, za pomocą którego urządzenia podłączone do ESP mogą uzyskać dostęp do serwera WWW. Klient (strona internetowa działająca na podłączonych urządzeniach), w połączeniu z serwerem, serwuje stronę internetową, na której znajdują się przyciski do sterowania diodami LED, a za przyciskami umieszczona jest funkcja obsługująca akcje, które występują po ich kliknięciu.

Aby ograniczyć długość kodu, który musimy napisać, skorzystamy z biblioteki ESP32 WiFi Library. Biblioteka ta zawiera funkcje, które ułatwiają skonfigurowanie ESP32 jako serwera WWW. Biblioteka ta, wraz z kilkoma innymi, jest spakowana razem z plikami płytki ESP32 i jest automatycznie instalowana po zainstalowaniu plików płytki ESP32 w Arduino IDE.

Zaczynamy jak zwykle, od dołączenia biblioteki wymaganej dla projektu, która w tym przypadku jest po prostu biblioteką WiFi.h.

#include <WiFi.h>

Następnie dodajemy dane uwierzytelniające punktu dostępowego WiFi, do którego będzie podłączone ESP32. Upewnij się, że nazwa użytkownika i hasło znajdują się pomiędzy cudzysłowami. Określamy również port, przez który system będzie się komunikował i tworzymy zmienną do przechowywania żądań.

// Replace with your network credentials
const char* ssid     = "Enter_SSID_here";
const char* password = "Enter_Password_here";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

Następnie deklarujemy piny ESP32, do których podłączone są czerwona i zielona dioda LED oraz tworzymy zmienne przechowujące stan diod LED.

int greenled = 26;
int redled = 27; 

String greenstate = "off";// state of green LED
String redstate = "off";// state of red LED

Mając to już za sobą, przechodzimy do funkcji void setup().

Zaczynamy od zainicjalizowania monitora szeregowego (będzie on później używany do debugowania) i ustawiamy pinModes pinów, do których podłączone są diody LED jako wyjścia. Następnie ustawiamy piny "LOW", aby zapewnić, że układ startuje w stanie neutralnym.

void setup() {
  Serial.begin(115200);
 // Set the pinmode of the pins to which the LEDs are connected and turn them low to prevent flunctuations
  pinMode(greenled, OUTPUT);
  pinMode(redled, OUTPUT);
  digitalWrite(greenled, LOW);
  digitalWrite(redled, LOW);

Następnie łączymy się z punktem dostępowym, używając danych uwierzytelniających jako argumentów funkcji WiFi.begin() oraz funkcji WiFi.status() do sprawdzenia, czy połączenie się powiodło.

WiFi.begin(ssid, password);
Serial.print("Connecting to ");
Serial.println(ssid);
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}

Jeżeli połączenie się powiedzie, na monitorze szeregowym zostanie wyświetlony tekst informujący o tym fakcie, a także adres IP serwera sieciowego. Ten adres IP staje się adresem internetowym dla serwera i jest tym, co musimy wpisać w dowolnej przeglądarce internetowej w tej samej sieci, aby uzyskać dostęp do serwera.

Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());// this will display the Ip address of the Pi which should be entered into your browser

Po wykonaniu tych czynności uruchamiamy serwer za pomocą funkcji server.begin() i przechodzimy do funkcji void loop( ).

server.begin();

Funkcja void loop() jest miejscem, w którym wykonywana jest większość pracy. Zaczynamy od użycia funkcji server.available() do nasłuchiwania połączeń przychodzących od klientów. Kiedy klient jest dostępny i połączony, odczytujemy żądanie klienta i wysyłamy nagłówek jako odpowiedź.

WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

Następnie sprawdzamy, czy żądanie klienta wskazuje na naciśnięcie przycisku w celu włączenia/wyłączenia któregokolwiek z pinów, zaczynając od zielonej diody LED. Jeśli żądanie wskazuje "ON", pin jest ustawiany w stan wysoki, a zmienna stanu jest odpowiednio aktualizowana i vice versa.

// turns the GPIOs on and off
           if (header.indexOf("GET /green/on") >= 0) {
             Serial.println("green on");
             greenstate = "on";
             digitalWrite(greenled, HIGH);
           } else if (header.indexOf("GET /green/off") >= 0) {
             Serial.println("green off");
             greenstate = "off";
             digitalWrite(greenled, LOW);
           } else if (header.indexOf("GET /red/on") >= 0) {
             Serial.println("red on");
             redstate = "on";
             digitalWrite(redled, HIGH);
           } else if (header.indexOf("GET /red/off") >= 0) {
             Serial.println("red off");
             redstate = "off";
             digitalWrite(redled, LOW);
           }

Następnie tworzymy stronę internetową, która będzie wyświetlana i aktualizowana przez NodeMCU w miarę interakcji z użytkownikiem. Kluczową funkcją do tego jest funkcja Client.println(), która służy do wysyłania skryptów HTML linia po linii do klienta (przeglądarki).

Zaczynamy od użycia "doctype", aby wskazać, że kilka następnych tekstów, które mają zostać wydrukowane, to linie HTML.

client.println("<!DOCTYPE html><html>");

Następnie dodajemy poniższe linie, aby strona była responsywna niezależnie od używanej przeglądarki.

client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");

Wrzucamy również kilka fragmentów CSS do klienta, aby strona była przyjazna dla użytkownika. Możesz to edytować, aby dodać swój własny kolor, styl czcionki, itp.

client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");

Następnie nagłówek strony jest wysyłany wraz z przyciskami, które są ustawione tak, aby wyświetlać ON lub OFF w zależności od aktualnego stanu diod LED. Przycisk będzie wyświetlał OFF, jeśli aktualny stan jest ON i odwrotnie.

client.println("<body><h1>ESP32 Web Server</h1>");

// Display current state, and ON/OFF buttons for green LED
client.println("<p>green - State " + greenstate + "</p>");
// If the green LED is off, it displays the ON button       
if (greenstate == "off") {
  client.println("<p><a href=\"/green/on\"><button class=\"button\">ON</button></a></p>");
} else {
  client.println("<p><a href=\"/green/off\"><button class=\"button button2\">OFF</button></a></p>");
} 
   
// Display current state, and ON/OFF buttons for Red LED  
client.println("<p>red - State " + redstate + "</p>");
// If the red LED is off, it displays the ON button       
if (redstate == "off") {
  client.println("<p><a href=\"/red/on\"><button class=\"button\">ON</button></a></p>");
} else {
  client.println("<p><a href=\"/red/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");

Następnie zamykamy połączenie i pętla przechodzi od nowa.

// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");

Kompletny kod projektu jest dostępny poniżej oraz w dziale download tego poradnika.

#include <WiFi.h>

// Replace with your network credentials 
const char* ssid = "Enter_SSID_here"; 
const char* password = "Enter_Password_here"; 

// Set web server port number to 80 

WiFiServer server(80); 

// Variable to store the HTTP request String header;
String header;
// Declare the pins to which the LEDs are connected 
int greenled = 26;
int redled = 27; 

String greenstate = "off";// state of green LED
String redstate = "off";// state of red LED


void setup() {
  Serial.begin(115200);
 // Set the pinmode of the pins to which the LEDs are connected and turn them low to prevent flunctuations
  pinMode(greenled, OUTPUT);
  pinMode(redled, OUTPUT);
  digitalWrite(greenled, LOW);
  digitalWrite(redled, LOW);
  //connect to access point
  WiFi.begin(ssid, password);
  Serial.print("Connecting to ");
  Serial.println(ssid);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());// this will display the Ip address of the Pi which should be entered into your browser
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /green/on") >= 0) {
              Serial.println("green on");
              greenstate = "on";
              digitalWrite(greenled, HIGH);
            } else if (header.indexOf("GET /green/off") >= 0) {
              Serial.println("green off");
              greenstate = "off";
              digitalWrite(greenled, LOW);
            } else if (header.indexOf("GET /red/on") >= 0) {
              Serial.println("red on");
              redstate = "on";
              digitalWrite(redled, HIGH);
            } else if (header.indexOf("GET /red/off") >= 0) {
              Serial.println("red off");
              redstate = "off";
              digitalWrite(redled, LOW);
            }
       
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>green - State " + greenstate + "</p>");
            // If the green LED is off, it displays the ON button       
            if (greenstate == "off") {
              client.println("<p><a href=\"/green/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/green/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 27 
            client.println("<p>red - State " + redstate + "</p>");
            // If the red LED is off, it displays the ON button       
            if (redstate == "off") {
              client.println("<p><a href=\"/red/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/red/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Demo

Podłącz DOIT ESP32 Devkit do komputera, upewnij się, że jest on wybrany jako typ płytki w Arduino IDE, następnie wklej kod w IDE, zweryfikuj i wyślij. Po zakończeniu wysyłania kodu otwórz monitor szeregowy. Powinieneś zobaczyć wyświetlony adres IP, jak pokazano na poniższym obrazku.

Adres IP

Podłącz urządzenie (telefon komórkowy lub komputer) do tej samej sieci co ESP32, a następnie otwórz przeglądarkę internetową na tym urządzeniu i wpisz adres IP z monitora szeregowego w pasku adresu. Powinna otworzyć się strona internetowa, którą utworzyliśmy na serwerze WWW, jak pokazano na poniższym obrazku. Klikając na przyciski można przełączać diody LED.

Strona internetowa serwowana klientowi

Jak wspomniano wcześniej, w miejsce diod LED można podłączyć przekaźniki lub inny rodzaj aktuatora, aby uczynić projekt bardziej użytecznym.

Do pobrania
Download icon ESP32 serwer www

Artykuł ESP32 WEBSERVER TUTORIAL opracowano w wersji polskiej na podstawie współpracy z portalem www.electronics-lab.com.

Firma:
AUTOR
Źródło
www.electronics-lab.com
Udostępnij
Zobacz wszystkie quizy
Quiz weekendowy
Edukacja
1/10 Jak działa rezystor LDR?
UK Logo
Elektronika dla Wszystkich
Zapisując się na nasz newsletter możesz otrzymać GRATIS
najnowsze e-wydanie magazynu "Elektronika dla Wszystkich"