M5Stack ATOM S3 to kompaktowa i wszechstronna jednostka mikrokontrolera, szczególnie przydatna w projektach Internetu Rzeczy (IoT). Połączenie jej z modułem Ethernet otwiera świat możliwości dla aplikacji podłączonych do sieci. Ten artykuł zawiera kompleksowy przewodnik po budowie prostego serwera WWW na M5Stack ATOM S3 z użyciem modułu Ethernet, szczegółowo wyjaśniając kod i badając potencjalne ulepszenia.
Wymagania sprzętowe:
-
M5Stack ATOM S3
-
Moduł Ethernet M5Stack (lub kompatybilny)
-
Kabel USB Type-C do programowania
-
Kabel Ethernet do połączenia sieciowego
Wymagania dotyczące oprogramowania:
-
Arduino IDE (z obsługą płytek ESP32)
-
Biblioteka M5Stack dla ATOM S3
#include "M5AtomS3.h" #include#include #define SCK 5 #define MISO 7 #define MOSI 8 #define CS 6 byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x99}; // adres MAC (często nadpisywany przez DHCP) IPAddress ip(192, 168, 1, 177); // Statyczny adres IP (nieużywany w tym przykładzie z włączonym DHCP) EthernetServer server(80); // Utwórz obiekt serwera na porcie 80 (HTTP) void setup() { auto cfg = M5.config(); AtomS3.begin(cfg); AtomS3.Display.setTextColor(ZIELONY); AtomS3.Display.setTextDatum(środek_środek); AtomS3.Display.setFont(&fonts::Orbitron_Light_24); AtomS3.Display.setTextSize(1); SPI.begin(SCK, MISO, MOSI, -1); // Inicjalizuj komunikację SPI dla Ethernetu Ethernet.init(CS); // Inicjalizuj chip Ethernet za pomocą pinu CS AtomS3.Display.drawString("Inicjalizacja...", AtomS3.Display.width() / 2, 60); while (Ethernet.begin(mac) != 1) { // Próba uzyskania adresu IP przez DHCP Serial.println("Błąd pobierania adresu IP przez DHCP, ponawianie próby..."); opóźnienie(1000); } // Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Nie znaleziono osłony Ethernet. Przepraszam, nie można uruchomić bez sprzętu. :("); while (true) { delay(1); // nic nie rób, nie ma sensu uruchamiać bez sprzętu Ethernet } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("Kabel Ethernet nie jest podłączony."); } server.begin(); // Uruchom serwer Serial.print("serwer jest na "); Serial.println(Ethernet.localIP()); // Wydrukuj przypisany adres IP AtomS3.Display.setTextSize(0.5); AtomS3.Display.clear(); AtomS3.Display.drawString(Ethernet.localIP().toString().c_str(), AtomS3.Display.width() / 2, 60); // Wyświetl IP na ekranie } void loop() { EthernetClient client = server.available(); // Sprawdź, czy jest nowe połączenie klienta if (client) { // Jeśli klient jest połączony Serial.println("nowy klient"); boolean currentLineIsBlank = true; while (client.connected()) { // Dopóki klient jest nadal połączony if (client.available()) { // Jeśli klient wysłał dane char c = client.read(); // Odczytaj znak od klienta Serial.write(c); // Wydrukuj znak w Monitorze portu szeregowego if (c == '\n' && currentLineIsBlank) { // Sprawdź koniec żądania HTTP // Send HTTP response client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Połączenie: zamknij"); client.println("Odśwież: 5"); // Odśwież stronę co 5 sekund client.println(); // Pusta linia sygnalizująca koniec nagłówka client.println(""); client.println(""); client.print("Witaj, moduł LAN M5Stack!"); client.println(""); break; // Wyjście z wewnętrznej pętli while (żądanie przetworzone) } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } } opóźnienie(1); client.stop(); // Zamknij połączenie klienta Serial.println("klient rozłączony"); } }
✔ Skopiowano!
Szczegółowe wyjaśnienie:
- Zawiera: Kod zaczyna się od dołączenia niezbędnych bibliotek: M5AtomS3.h dla ATOM S3, SPI.h do komunikacji SPI (używanej przez moduł Ethernet), oraz M5_Ethernet.h dla funkcji Ethernet.
- Definiuje: Instrukcje #define definiują piny SPI używane przez moduł Ethernet. Są one kluczowe dla prawidłowej komunikacji.
- Adres MAC: byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x99}; deklaruje adres MAC. Chociaż jest uwzględniony, jest on często nadpisywany przez serwer DHCP, gdy urządzenie łączy się z siecią.
- Adres IP: IPAddress ip(192, 168, 1, 177); definiuje statyczny adres IP. Jednak w tym przykładzie używany jest DHCP, więc ten statyczny adres IP nie jest faktycznie przypisany do urządzenia. To jest symbol zastępczy.
- Serwer Ethernet: EthernetServer server(80); tworzy instancję klasy EthernetServer, która nasłuchuje przychodzących połączeń na porcie 80 (standardowy port HTTP).
- funkcja set up():
- auto cfg = M5.config(); AtomS3.begin(cfg);: Inicjalizuje sprzęt M5 ATOM S3.
-
Następujące linie konfigurują wyświetlanie tekstu: ustawianie koloru, wyrównania, czcionki i rozmiaru.
-
SPI.begin(SCK, MISO, MOSI, -1); inicjalizuje komunikację SPI przy użyciu zdefiniowanych pinów. -1 oznacza, że biblioteka SPI nie zarządza żadnym konkretnym pinem wyboru układu.
-
Ethernet.init(CS); inicjalizuje chip Ethernet za pomocą określonego pinu wyboru chipu (CS).
-
AtomS3.Display.drawString("Inicjalizacja...", AtomS3.Display.width() / 2, 60); wyświetla "Inicjalizacja..." na ekranie ATOM S3, aby wskazać, że inicjalizacja jest w toku.
-
Pętla while (Ethernet.begin(mac) != 1) próbuje uzyskać adres IP za pomocą DHCP. Kontynuuje ponawianie próby co sekundę, aż zostanie otrzymany ważny adres IP. To właśnie tutaj ATOM S3 otrzymuje swój adres sieciowy.
-
Kod następnie sprawdza, czy sprzęt Ethernet jest obecny oraz czy nawiązano połączenie (kabel). Jeśli nie, program zatrzymuje się. Jest to ważne dla niezawodnej pracy.
-
server.begin(); uruchamia serwer Ethernet, przygotowując go do akceptowania nadchodzących połączeń.
-
Przypisany adres IP (uzyskany przez DHCP) jest wyświetlany w Monitorze Szeregowym oraz na ekranie ATOM S3.
7. pętla()
funkcja:
- EthernetClient client = server.available(); sprawdza, czy jakiś klient połączył się z serwerem. server.available() zwraca obiekt EthernetClient, jeśli klient jest dostępny, lub null, jeśli nie.
- Blok if (client) wykonuje się, jeśli klient jest połączony.
- boolean currentLineIsBlank = true; to flaga używana do wykrywania końca żądania HTTP.
- Pętla while (client.connected()) trwa tak długo, jak klient pozostaje połączony.
- if (client.available()) sprawdza, czy klient wysłał jakieś dane.
- char c = client.read(); odczytuje pojedynczy znak z żądania klienta.
- Serial.write(c); wyświetla odebrany znak w Monitorze portu szeregowego do celów debugowania.
- Kod następnie analizuje żądanie HTTP. Warunek if (c == '\n' && currentLineIsBlank) sprawdza koniec żądania HTTP. Pusta linia (\n\r\n lub \n\n) zazwyczaj oznacza koniec nagłówków.
Jeśli wykryto koniec żądania, serwer wysyła odpowiedź HTTP:
-
HTTP/1.1 200 OK
: Standardowa odpowiedź HTTP wskazująca sukces. *Content-Type: text/html
: Określa, że ciało odpowiedzi jest w formacie HTML. *Connection: close
: Informuje klienta, że po wysłaniu odpowiedzi połączenie zostanie zamknięte. To proste podejście; można użyć połączeń trwałych dla bardziej efektywnej komunikacji. *Refresh: 5
: Ten nagłówek nakazuje przeglądarce odświeżać stronę co 5 sekund. Tworzy to efekt dynamiczny. * Pusta linia (client.println();
) jest kluczowa; oddziela nagłówki HTTP od właściwej treści. * Następnie wysyłana jest zawartość HTML:
. To prosty HTML, który zostanie wyświetlony w przeglądarce. *Hello M5Stack LAN Module!
break;
wychodzi z wewnętrznej pętliwhile (client.connected())
, ponieważ odpowiedź została wysłana. * Kod następnie obsługuje logikę wykrywania końca żądania HTTP.if (c == '\n')
sprawdza znak nowej linii, wskazujący początek nowej linii w żądaniu.currentLineIsBlank
jest ustawiane natrue
, gdy napotkany zostanie znak nowej linii.else if (c != '\r')
sprawdza, czy znak nie jest powrotem karetki. Jeśli nie jest powrotem karetki, oznacza to, że na bieżącej linii są dane, więccurrentLineIsBlank
jest ustawiane nafalse
. Ta logika skutecznie wykrywa pustą linię sygnalizującą koniec nagłówków HTTP. *delay(1);
zapewnia krótkie opóźnienie, dając przeglądarce czas na przetworzenie odebranych danych. *client.stop();
zamyka połączenie z klientem. *Serial.println("client disconnected");
wyświetla komunikat w Monitorze Szeregowego, wskazujący, że klient się rozłączył.
Ulepszenia i dalszy rozwój:
-
Dynamiczna zawartość: Obecny HTML jest statyczny. Możesz generować dynamiczną zawartość, używając zmiennych i logiki w swoim kodzie Arduino. Na przykład, możesz wyświetlać odczyty czujników, sterować siłownikami lub pokazywać aktualny czas.
-
Obsługa różnych żądań: Kod obecnie odpowiada na każde żądanie tym samym HTML-em. Możesz zaimplementować logikę obsługi różnych metod HTTP (GET, POST itp.) oraz różnych adresów URL, co pozwoli Ci stworzyć bardziej złożony interfejs sieciowy.
-
HTML Formularze i dane użytkownika: Dodaj formularze HTML do swojej strony internetowej, aby umożliwić użytkownikom wprowadzanie danych. Następnie możesz przetwarzać te dane na ATOM S3 i używać ich do sterowania swoimi urządzeniami.
-
WebSockets: Do komunikacji w czasie rzeczywistym rozważ użycie WebSockets zamiast HTTP. WebSockets umożliwiają dwukierunkową komunikację między klientem a serwerem, co jest niezbędne dla interaktywnych aplikacji.
-
Bezpieczeństwo: W środowiskach produkcyjnych bezpieczeństwo jest kluczowe. Wdroż mechanizmy uwierzytelniania i autoryzacji, aby chronić swoje urządzenie i dane.
-
Integracja systemu plików: Przechowuj pliki HTML, CSS i JavaScript na karcie SD lub pamięci flash i udostępniaj je z ATOM S3. Pozwala to na tworzenie bardziej zaawansowanych interfejsów internetowych.
-
AJAX i JavaScript: Użyj AJAX (Asynchroniczny JavaScript i XML), aby dynamicznie aktualizować części strony internetowej bez konieczności pełnego przeładowania strony. To poprawia doświadczenie użytkownika.
-
mDNS (Multicast DNS): Użyj mDNS, aby nadać swojemu ATOM S3 czytelną nazwę w sieci lokalnej, co ułatwi dostęp.
-
Obsługa błędów: Wdrożenie solidnej obsługi błędów, aby łagodnie zarządzać sytuacjami takimi jak rozłączenia sieci lub nieprawidłowe dane wejściowe użytkownika.
-
OTA (Over-The-Air) Aktualizacje: Wdrażaj aktualizacje OTA, aby umożliwić zdalną aktualizację oprogramowania układowego Twojego ATOM S3.
Rozwiązywanie problemów:
-
Brak adresu IP: Sprawdź swoje połączenie sieciowe, upewnij się, że DHCP jest włączone na routerze oraz zweryfikuj, czy moduł Ethernet jest prawidłowo podłączony do ATOM S3.
-
Nie można połączyć: Sprawdź dwukrotnie adres IP ATOM S3, upewnij się, że jest w tej samej sieci co twój komputer, i zweryfikuj, czy nie ma zapór sieciowych blokujących połączenie.
-
Problemy z monitorem szeregowym: Upewnij się, że prędkość transmisji w Monitorze szeregowym odpowiada prędkości transmisji użytej w twoim kodzie (zazwyczaj 115200).
To rozszerzone wyjaśnienie zapewnia bardziej szczegółowe zrozumienie kodu i oferuje punkt wyjścia do tworzenia bardziej zaawansowanych aplikacji serwera internetowego na M5Stack ATOM S3. Pamiętaj, aby konsultować się z dokumentacją M5Stack oraz innymi zasobami online w celu uzyskania bardziej szczegółowych informacji i przykładów.