[4] STM32CUBE w przykładach (obsługa ESP8266)

 

W tej części kursu, dodamy do omawianego mikrokontrolera STM32F411 z zestawu KA-NUCLEO-F411CE, obsługę sieci Wi-Fi i stosu TCP/IP. Wykorzystamy w tym celu, w roli karty sieciowej, kolejny mikrokontroler – układ ESP8266. Do komunikacji między układami użyty zostanie interfejs UART oraz polecenia AT Hayesa. Efektem naszych prac będzie bardzo prosty serwer WWW udostępniający stronę internetową, pozwalającą wybrać kolor świecenia diody RGB znajdującej się na płytce rozwojowej lub podłączonej do układu z zewnątrz.

Układ ESP8266 to jednak nie tylko karta sieciowa. Jest on pełnoprawnym mikrokontrolerem, którego również możemy programować. Posiada on 32-bitowy rdzeń CPU Tensilica Xtensa LX106 taktowany zegarem o częstotliwości 80 MHz, 64 kB pamięci RAM dla kodu, 96 kB pamięci RAM dla danych oraz pamięć Flash o rozmiarze zależnym od wersji. Układ wspiera standardy sieci Wi-Fi 802.11 b/g/n. Występuje w kilku wersjach różniących się, oprócz rozmiaru pamięci Flash, także ilością wyprowadzonych pinów i kształtem wbudowanej anteny oraz możliwością podłączenia zewnętrznej. W tym kursie wykorzystany zostanie moduł w wersji ESP8266-01, posiadający wbudowaną, na płytce mikrokontrolera, antenką i wyprowadzone 8 pinów – w tym dwa piny interfejsu UART, zasilanie, masę oraz piny ogólnego przeznaczenia (GPIO). Układ ESP operuje na napięciach 0-3.3V, identycznie jak STM32F411 na wykorzystywanej przeze mnie płytce rozwojowej KA-NUCLEO-F411CE. Domyślnie, wszystkie mikrokontrolery tej serii, mają wgrane oprogramowanie działające w roli karty sieci bezprzewodowej oraz implementacji stosu protokołów TCP/IP sterowanej przy pomocy poleceń AT Hayesa.

Fot. 1. Zdjęcie modułu ESP8266-01

Na układy z rodziny ESP8266 powstało wiele ciekawych projektów, z czego moim zdaniem, najbardziej ambitnym, jest, w pełni programowym nadajnik sygnału telewizyjnego – projekt „channel3”, autorstwa CNLohr (https://github.com/cnlohr/channel3). Generuje on kolorowy obraz w standardzie NTSC i nadaje go falami radiowymi, poprzez jeden z pinów GPIO, do którego podłączona jest antena. Generowanym obrazem są ruchome, również trójwymiarowe, wizualizacje. W trakcie emisji sygnału, mikrokontroler obsługuje także sieć Wi-Fi i pozwala na sterowanie nadawanym sygnałem przez stronę WWW.

Dlaczego więc, tak po prostu nie zaprogramujemy tego układu? Programowanie mikrokontrolerów serii ESP8266 nie jest tak proste, jak programowanie układów z rodziny STM32 z użyciem biblioteki HAL. Nie dysponujemy tak zaawansowanym i jednocześnie prostym w obsłudze narzędziem jak generator konfiguracji CubeMX. Cały czas pamiętać też musimy o tym że ten sam rdzeń obsługuje zarówno nasz program, jak i wszystkie akcje związane z obsługą sieci Wi-Fi – programujemy więc zdarzenia wywoływane w odpowiednich momentach. Istnieją wprawdzie frameworki i środowiska, sprowadzające programowanie ESP8266 do programowania platformy „Arduino z Wi-Fi”, jednak znacznie ograniczają one możliwości tych układów. Następca serii ESP8266 – układ ESP32 posiada już dwa rdzenie CPU, z czego jeden może być przeznaczony tylko do wykonywania naszego kodu, a drugi zajmuje się obsługą sieci Wi-Fi.

 

Zestaw poleceń AT Hayesa

Wspomniane już wyżej polecenia Hayesa, są równie stare jak, omówiony w poprzedniej części kursu, interfejs RS232. Od dawna służyły one i wciąż są wykorzystywane do sterowania wszelkiego rodzaju modemami – początkowo akustycznymi i podłączanymi do linii telefonicznych, gdzie polecenia przesyłane były przez interfejs COM – RS232, a obecnie do sterowania modemami GSM, UMTS, czy nawet LTE, przez interfejs USB.

Polecenia AT interpretowane przez układ ESP8266 mogą zostać użyte na cztery sposoby:
1) dopisując po identyfikatorze polecenia znak zapytania, możemy odczytać obecnie ustawioną wartość danego parametru, np. nazwę sieci Wi-Fi, poleceniem: AT+CWJAP?;
2) dopisując znak równości i wartość parametru, możemy ją zmienić, np. AT+CWJAP=”NAZWA_SIECI”,”KLUCZ_SIECIOWY”;
3) dopisując znaki równości i zapytania, możemy dowiedzieć się, jakie wartości przyjmuje dany parametr, np. tryb pracy urządzenia – AT+CWMODE=?,
4) podając sam identyfikator, możemy wykonać polecenie, np. przeskanować sieci Wi-Fi w pobliżu i wyświetlić ich nazwy – AT+CWLAP.

Jedno polecenie może występować w kilku wariantach, lecz nie musi. Zazwyczaj wykonanie polecenia kończy się zwrotem kilku linii odpowiedzi, z których ostatnia zawiera ciąg „OK”, jeśli udało się wykonać polecenie lub „ERROR”, w przypadku błędu. To niestety również nie jest regułą i część odpowiedzi kończy się innymi ciągami, jak na przykład „no change”, w przypadku próby ponownego ustawienia takiej samej wartości dla danego parametru. Poniżej znajduje się spis popularnych poleceń, wraz z opisami ich działania.

  • AT – Testuje komunikacje z układem ESP8266. Zwraca ciąg „OK”, jeśli mamy połączenie, a układ jest gotowy do pracy.
  • AT+RST – Powoduje ponowne uruchomienie układu ESP8266. Ostatnim komunikatem po restarcie jest ciąg „ready”.
  • AT+CWMODE=ID_TRYBU_PRACY – Wybiera tryb pracy układu: 1) urządzenie końcowe Wi-Fi; 2) punkt dostępowy Wi-Fi; 3) urządzenie końcowe + punkt dostępowy
  • AT+CWLAP – Skanuje sieci bezprzewodowe w okolicy i podaje ich parametry – rodzaj szyfrowania, nazwę sieci, adres MAC punktu dostępowego oraz siłę sygnału. Polecenie działa tylko w trybie pracy urządzenia końcowego.
  • AT+CWJAP=”NAZWA_SIECI,”KLUCZ_SIECIOWY” – Łączy się z siecią bezprzewodową o podanej nazwie i kluczu sieciowym (haśle). Polecenie działa tylko w trybie pracy urządzenia końcowego.
  • AT+CWQAP – Rozłącza się z siecią bezprzewodową. Polecenie działa tylko w trybie pracy urządzenia końcowego.
  • AT+CWSAP=”NAZWA_SIECI,”KLUCZ_SIECIOWY,NR_KANAŁU,SZYFROWANIE – Tworzy sieć bezprzewodową, rozgłaszaną przez urządzenie, w trybie pracy punktu dostępowego (polecenie działa tylko w tym trybie). Jako szyfrowanie możemy wybrać następujące wartości: 0) Sieć otwarta (bez szyfrowania); 2) Szyfrowanie WPA PSK; 3) Szyfrowanie WPA2 PSK; 4) Szyfrowanie WPA PSK + WPA2 PSK
  • AT+CWLIF – Wyświetla listę urządzeń przyłączonych do punktu dostępowego (polecenie działa tylko w tym trybie).
  • AT+CWDHCP=TRYB_PRACY,0/1 – Włącza (1) lub wyłącza (0) klienta i/lub serwer usługi sieciowej DHCP, pozwalającej na automatyczne przydzielanie i pobieranie adresu IP oraz pozostałej konfiguracji urządzenia końcowego. Domyślnie, usługa DHCP jest włączona zarówno jako serwer w trybie punktu dostępowego (moduł przydziela konfigurację innym urządzeniom które przyłączą się do jego sieci), jak i klient w trybie pracy urządzenia końcowego (urządzenie samo pobiera sobie konfigurację).
  • AT+CIPSTA=”ADRES_IP / AT+CIPAP=”ADRES_IP” – Ustawia adres IP układu ESP8266, w trybie pracy urządzenia końcowego (AT+CIPSTA) i kolejno, punktu dostępowego (AT+CIPAP).
  • AT+CIPMUX=0/1 – Włącza (1) / wyłącza (0) obsługę wielu połączeń równocześnie – maksymalnie pięciu, numerowanych od 0 do 4.
  • AT+CIPSERVER=0/1,PORT – Uruchamia (1) lub zamyka (0) serwer TCP – gniazdo nasłuchujące, na podanym porcie. Polecenie działa jedynie w trybie wielopołączeniowym (AT+CIPMUX=1).
  • AT+CIPSTART=[NR_POŁĄCZENIA,]”TCP/UDP,”ADRES_IP_SERWERA,PORT – Nawiązuje połączenie TCP lub UDP z serwerem o podanym adresie IP lub domenie, na wskazanym porcie. W trybie wielopołączeniowym, pierwszym parametrem jest numer połączenia (0-4), nie występuje on w trybie jednopołączeniowym.
  • AT+CIPSEND=[NR_POŁĄCZENIA,]ILOŚĆ_BAJTÓW – Wysyła strumień bajtów o podanym rozmiarze, przez nawiązane uprzednio, poleceniem AT+CIPSERVER lub AT+CIPSTART, połączenie. W trybie wielopołączeniowym należy podać numer połączenia, w trybie jednopołączeniowym, pomijamy pierwszy parametr.
  • AT+CIPCLOSE[=NR_POŁĄCZENIA] – Zamyka nawiązane uprzednio, poleceniem AT+CIPSERVER lub AT+CIPSTART, połączenie. W trybie wielopołączeniowym należy podać jego numer.
  • AT+CIFSR – Zwraca obecny adres IP modułu ESP8266.

Po nawiązaniu połączenia TCP lub UDP, dane odebrane od strony przeciwnej, przesyłane są przez układ ESP8266 poprzedzone ciągiem +IPD[,NR_POŁĄCZENIA],ROZMIAR_DANYCH:.

Na podstawie powyższego spisu poleceń, możemy przygotować skrypt który prześlemy do modułu ESP8266 po uruchomieniu obu mikrokontrolerów. Sekwencja poleceń która spowoduje przyłączenie się do sieci Wi-Fi, pobranie adresu IP oraz uruchomienie serwera-gniazda TCP na porcie 80, prezentuje się następująco:

AT+CWMODE=1
AT+CWJAP=”NAZWA_SIECI”,”KLUCZ_SIECIOWY”
AT+CIPMODE=1
AT+CIPSERVER=1,80

Jeśli chcielibyśmy utworzyć sieć Wi-Fi na kanale 11, obsługującą szyfrowania WPA i WPA2 PSK, musimy wykonać poniższe polecenia:

AT+CWMODE=2
AT+CWSAP=”NAZWA_SIECI”,”KLUCZ_SIECIOWY”,11,4
AT+CIPMODE=1
AT+CIPSERVER=1,80

Czym właściwie jest TCP, porty i jak w uproszczeniu przebiega komunikacja w Internecie?

W spisie poleceń użyłem określeń: połączenie i gniazdo TCP. Czym jednak jest to połączenie? Komputery wymieniają się w Internecie danymi w pakietach IP. Internet z natury jest siecią bezpołączeniową. Każdy pakiet może być wysłany pod dowolny adres IP bez zestawiania połączenia. Jest on przełączany indywidualnie przez routery, na trasie od źródła do celu. Z samych pakietów IP nie korzysta się jednak zbyt często.

Protokół TCP działa nad protokołem IP. Z jednej strony, udostępnia on aplikacjom połączeniowy kanał którym przesyłane są strumienie danych między dwoma urządzeniami końcowymi, z drugiej, dzieli te dane i pakuje w pakiety IP, w celu przesyłu przez sieć. Zajmuje się też retransmisją zgubionych lub uszkodzonych na trasie pakietów i szeregowaniem ich we właściwej kolejności w miejscu odbioru. Serwer TCP to gniazdo nasłuchujące – oczekuje on na połączenia przychodzące na określonym porcie (w segmentach TCP przesyłane są 16-bitowe identyfikatory portów), nawiązywane również z określonego portu po stronie aplikacji klienckiej. Protokół TCP pozwala w ten sposób na używanie wielu serwerów i nawiązywanie wielu połączeń równocześnie.

Nad protokołem TCP (i UDP) działają jeszcze inne protokoły, standaryzujące sposób przesyłania danych w sieci. Jednym z tych protokołów jest HTTP, służący do przesyłania stron internetowych oraz plików z serwerów do przeglądarek WWW. Korzysta on z protokołu TCP i zwyczajowo działa na porcie 80.

Typowe żądanie HTTP wysyłane przez przeglądarkę zaczyna się od ciągu GET / HTTP/1.1, po którym następuje kilka linii nagłówków HTTP, w których przeglądarka przedstawia siebie oraz swoje możliwości, przesyłane są także parametry połączenia. Pierwszy znak / w powyższym początku zapytania to adres pliku który chcemy pobrać – / oznacza stronę główną. Jeśli wypełnimy na stronie WWW formularz (przesyłający dane metodą GET) i wyślemy jego zawartość, wszystkie wypełnione pola zostaną dopisane po znaku pytajnika do nazwy pliku, jako kolejne zmienne – np. GET /?red=100&green=50&blue=10 HTTP/1.1 i przesłane w kolejnym żądaniu. Odpowiedź składa się z ciągu HTTP/1.1 200 OK (jeśli nie wystąpił błąd) i serii nagłówków, po której przesyłany jest plik/strona WWW. Zazwyczaj, połączenie utrzymywane jest w celu dalszej komunikacji, możemy jednak z tego zrezygnować i uprościć działanie serwera, dopisując do odpowiedzi nagłówek Connection: close i zamykając połączenie, po odesłaniu odpowiedzi.

W dalszej części tego artykułu, przedstawiona została bardzo uproszczona implementacja serwera tego protokołu. Nasz program, połączy się z siecią Wi-Fi, uzyska automatycznie adres IP oraz pozostałe parametry konfiguracyjne, uruchomi serwer TCP na porcie 80 i będzie oczekiwał na połączenia przychodzące. Gdy takie zostanie nawiązane, przez przeglądarkę internetową, sprawdzony zostanie adres URI do jakiego odwołuje się żądanie HTTP przesłane w połączeniu, następnie serwer odpowie na nie przesyłając stronę WWW z formularze umożliwiającym wybór koloru i zamknie połączenie. Jeśli w żądaniu przesłane zostaną również dane z formularza, program zmieni także kolor świecenia diody RGB.

Testowanie działania układu ESP8266

Jeśli chcemy przetestować działanie komend AT Hayesa i zobaczyć jak odpowiada na nie układ ESP8266, ale nie posiadamy adaptera USB<->UART, możemy w jego miejsce użyć płytki rozwojowej KA-NUCLEO lub dowolnej innej, z programatorem ST-LINK i wyprowadzonymi pinami RX/TX interfejsu UART, łączącego programator ST-LINK i programowany układ.

Na płytce KA-NUCLEO, dla zapewnienia kompatybilności wyprowadzeń z Arduino, są ta piny D0 (pin odbiorczy) i D1 (pin nadawczy), podłączone odpowiednio do wyprowadzeń PA3 i PA2 procesora. Za ich obsługę, po stronie układu STM32F411, odpowiada interfejs USART2.

Tworzymy w tym celu nowy projekt programu STM32CubeMX, wybieramy nasz mikrokontroler (dla przypomnienia, na płytce KA-NUCLEO, jest to układ STM32F411CEU6) i na pierwszej planszy konfiguratora – „Pinout”, odnajdujemy wyżej wspomniane piny, klikamy na każdy z nich lewym przyciskiem myszy i z listy funkcji alternatywnych, wybieramy opcję „GPIO_Input”, aby układ STM32 nie przeszkadzał nam w transmisji. Odszukujemy też dowolny inny pin dostępny, na naszej płytce rozwojowej, do dyspozycji użytkownika. Na płytce KA-NUCLEO, następny pin (obok pinów RX/TX) – D2, przyłączony jest do wyprowadzenia mikrokontrolera, o oznaczeniu PA10. Ustawiamy go w tryb wyjścia – „GPIO_Output”. Podłączony zostanie on do pinu „CH_PD” układu ESP8266.

Rys. 2. Ustawienia wyprowadzeń mikrokontrolera w programie STM32CubeMX

Ponieważ pin „CH_PD”, przez cały czas pracy z układem, powinien być w stanie wysokim (3.3 V), ustawiamy mu ten stan jako domyślny – przechodzimy do planszy „Configuration”, z zakładki „System” wybieramy pozycję GPIO, odszukujemy pin „CH_PD”, zaznaczamy go i z listy „GPIO Output Level” wybieramy opcję „High”.

Rys. 3. Ustawianie domyślnej wartości logicznej, na pinie wyjściowym „CH_PD”

Przy pomocy kabli połączeniowych, łączymy płytkę KA-NUCLEO i układ ESP8266. Piny RX/TX interfejsów UART obu układów podłączamy na przemian, tak aby pin odbiorczy jednego z nich był połączony z pinem nadawczym drugiego. Pin ustawiony w tryb wyjścia (D2), łączymy z pinem „CH_PD” układu ESP. Nie zapominamy także o podłączeniu zasilania (3.3V) i masy.

Rys. 4. Wyprowadzenia modułu ESP8266

Następnie generujemy nowy projekt, w sposób opisany w poprzednich częściach oraz importujemy go w środowisku System Workbench for STM32, kompilujemy źródła, wgrywamy program na mikrokontroler i uruchamiamy go. Teraz możemy już uruchomić, znany z poprzedniej części, program PuTTY i podobnie jak zostało to wcześniej opisane, wybrać w nim typ połączenia szeregowego – w polu „Connection Type” wybieramy opcję „Serial”, wybrać port szeregowy, który system operacyjny przydzielił programatorowi ST-LINK – np. „COM3” oraz ustawić szybkość połączenia. Układy ESP z nowszym oprogramowaniem pracują domyślnie z szybkością transmisji 115200, ze starszym – 9600.

Rys. 5. Ustawianie parametrów połączenia szeregowego w programie PuTTY
Rys. 6. Komunikacja z modułem ESP8266

Układ ESP8266, podobnie jak większość innych urządzeń z którymi komunikujemy się poleceniami AT Hayesa, interpretuje tylko jeden format oznaczeń końca linii/polecenia. Są to niedrukowalne znaki ASCII – CR (powrót karetki/kursora na początek linii) oraz LF (przejście do nowej linii), co przypomina działanie maszyny do pisania. Niestety, nie jest to format wykorzystywany przez Windowsa. Aby więc układ ESP8266 prawidłowo odebrał od nas polecenie, musimy zakończyć je tymi dwoma znakami. Wykonujemy to, kombinacjami klawiszy Ctrl+M (CR) oraz Ctrl+J (LF).

Do pobrania