Autor:
Tomasz Francuz
Redakcja:
Dondu
Artykuł jest częścią cyklu: Moduły WiFi
W
pierwszej części naszego mini-cyklu o
ESP8266 dowiedzieliśmy się co nieco o tym jaki moduł kupić i czym one się między sobą różnią. Skoro mamy już moduł nadszedł czas, aby go ożywić, czyli się z nim skomunikować. W tej części pokażę jak połączyć moduł z mikrokontrolerem i jakie na użytkownika czyhają potencjalne pułapki.
Pamiętajcie tylko, że na rynku jest dużo różnych wersji modułów ESP i jeszcze więcej wersji firmware. Po prostu nie jestem w stanie przetestować wszystkich. Jeśli więc traficie na moduł, który zachowuje się odmiennie niż w naszym opisie to dajcie proszę znać pisząc komentarz do tego artykułu.
Kabelkologia
Zanim zaczniemy grzebać przy module jeszcze raz przypomnę – moduł wymaga zasilania z zakresu
3,0-3,6V, czyli w praktyce standardowego
3,3V. Ponieważ impulsowo może pobierać nawet ponad
200mA, musimy zadbać o to, aby zasilacz był w stanie taki prąd dostarczyć. Stąd też, jeśli używasz np. Arduino, do którego podłączonych jest sporo różnych urządzeń, to pomyśl o lepszym zasilaniu niż wbudowany na płytce stabilizator.
Pamiętaj też, że dodatkowe kondensatory: elektrolityczny (do kilkuset µF) i ceramiczny 100nF nie zaszkodzą, a mogą pomóc.
Pamiętaj, moduł nie toleruje zasilania 5V, jego piny sterujące też nie są 5V-tolerant, chyba że kupiłeś moduł z translatorami poziomów.
Stąd też połączenie
ESP8266 z mikrokontrolerami zasilanymi typowo z
5V nie może odbywać się bezpośrednio. W takiej sytuacji będziemy potrzebowali:
- dodatkowego stabilizatora low-drop (LDO), który z 5V zrobi nam 3,3V do zasilania modułu,
- konwertera poziomów 5V na 3,3V – rezystor lub dzielnik rezystorowy – taki konwerter potrzebny jest na linię RxD modułu, którą łączymy z wyjściem TxD UART mikrokontrolera i ewentualnie na wykorzystywane linie GPIO (wejścia/wyjścia).
A może prościej będzie przesiąść się na zasilanie 3,3V i raz na zawsze zakończyć problemy związane z różnymi domenami zasilania? Pamiętajmy, że niektóre wersje
AVR-ów można zasilać z
3,3V – klasyczne (ATtiny, ATmega - np. ATmega8A lub ATmega8L), będą wymagały tylko ograniczenia maksymalnej częstotliwości taktowania.
Ale np. AVR z rodziny
XMEGA będą pracowały nawet z taktowaniem
32MHz przy zasilaniu
3,3V. Ponieważ bardzo lubię tą rodzinę mikrokontrolerów, a mają one w kontekście naszego modułu
ESP także inne zalety, w dalszej części pokażę przykłady oparte na tych mikrokontrolerach.
Odsłona pierwsza – łączymy moduł z PC
Ponieważ naszą zabawę z modułem
ESP8266 zaczniemy od prostych poleceń i po prostu oswojenia się z nową zabawką, wygodnie będzie połączyć moduł z komputerem PC. Tu pojawia się drobny problem – moduł do komunikacji wykorzystuje interfejs
UART, a współczesne
PC-ty raczej go nie mają – z interfejsów szeregowych posiadają m.in.
USB.
Nawet jeśli ktoś ma jeszcze w domu komputer z
RS232 to też nie ma się co cieszyć –
ESP wykorzystuje tzw.
RS232-TTL, czyli stany logiczne kodowane są w nim tak jak w układach logicznych, czyli stan niski to ok.
0V, a wysoki to
3,3V.
Natomiast klasyczny RS232 pracuje przy poziomach napięć ±12V, stąd też podłączenie ESP do klasycznego RS232 niechybnie zakończy jego życie.
Ok, potrzebujemy więc przejściówkę
USB-RS232-TTL z poziomami
3,3V. Tak się dobrze składa, że tego typu przejściówki możemy kupić za parę złotych z darmową dostawą np. na AliExpress.
Możemy też kupić opisywany w
poprzedniej części tego cyklu moduł wyposażony już w przejściówkę na
USB – w takiej sytuacji moduł po prostu łączymy z
PC-tem kablem
USB i możemy rozpocząć przygodę. A jeśli nie mamy modułu z wbudowanym
USB? To musimy sobie sami połączyć moduł z przejściówką wg pokazanego poniżej rysunku:
 |
FT232-moduł |
Czyli łączymy:
- RxD modułu z TxD przejściówki
- TxD modułu z RxD przejściówki
- łączymy GND i Vcc (3,3V) – tu uwaga:
Nigdy nie wykorzystuj napięcia
3,3V z przejściówki do zasilania modułu. W przejściówce znajduje się
stabilizator LDO, który zasila część logiki oraz bufory
IO układu,
lecz ma ograniczoną wydajność prądową. W przypadku
FT232 daje max
50mA – czyli ponad czterokrotnie mniej niż wymaga tego moduł
ESP8266!
- pin CH_PD łączymy z 3,3V bezpośrednio lub przez rezystor 4k7-10k
- jeśli moduł ma wyprowadzony pin GPIO15 to łączymy go z GND (w dalszej części wyjaśnię o co chodzi)
- pin REST (RESET) łączymy przez rezystor z 3,3V lub zostawiamy niepodłączony.
Wybierając przejściówkę pamiętajmy, aby wybrać taką, która daje na wyjściu poziomy logiczne w standardzie
3,3V. Niektóre dają na wyjściu
5V – w takim przypadku niepotrzebnie sobie skomplikujemy podłączenie
ESP – wymagany będzie dodatkowy stabilizator i prosta translacja poziomów napięć.
I to tyle, proste, prawda? Wykorzystanie chipu
FT232 jest proste i tanie, ale my przecież zajmujemy się mikrokontrolerami, może więc trochę skomplikujemy to proste połączenie?
Wykorzystanie modułu Xplained Mini
W drugim wydaniu swojej książki „
Język C dla mikrokontrolerów AVR. Od podstaw do zaawansowanych aplikacji” wykorzystuję do realizacji przykładów moduł
Xplained Mini – kosztuje on niewiele (w USA parę dolarów), ale w Polsce też go można kupić tanio, np. w Seguro za niecałe 50 zł. Trochę więcej o tym fajnym module możesz poczytać na naszym blogu w artykule:
Xplained Mini – czyli to, co Atmel już dawno temu zrobić był powinien
Dlaczego
Xplained jest fajny? Bo na pokładzie ma mikrokontroler
ATMega168/328P, czyli ten sam, który jest w popularnym Arduino, cała płytka ma format Arduino i pasują do niej shieldy Arduino, a co więcej na płytce jest programator/debugger, czyli mamy wszystko, co potrzebne, aby wystartować z AVR. Ale mamy jeszcze jedną fajną rzecz – płytka zawiera konwerter
RS232-TTL-USB! A więc możemy ją wykorzystać jako przejściówkę do podłączenia modułu
ESP8266 do
PC-ta. W tym celu musimy odnaleźć na płytce dwa punkty oznaczone jako
RX i
TX:
 |
Xplained Mini |
Znajdują się one po lewej stronie mikrokontrolera leżącego przy gnieździe
USB, tuż pod napisem
ATMega328P. Jeśli do tych punktów podłączymy
UART modułu
ESP to będziemy mogli się z nim komunikować przez
USB. Z tym, że musimy pamiętać o ważnej rzeczy – standardowo moduł
Xplained Mini pracuje z zasilaniem
5V (można to zmienić na
3,3V, wymaga to jednak drobnych zmian w module, które na razie pominiemy).
Stąd też o ile sygnał
TxD modułu możemy bezpośrednio doprowadzić do dziurki oznaczonej jako
RX na
Xplained, o tyle, sygnał z dziurki oznaczonej
TX musimy doprowadzić do wejścia
RxD ESP poprzez rezystor lub dzielnik rezystorowy, tak aby zbić napięcie do bezpiecznego poziomu
3,3V. W tym celu możemy np. zbudować dzielnik z rezystorami
10k i
20k, tak jak na rysunku (wartości rezystorów nie są krytyczne, ważny jest ich stosunek):
 |
Dzielnik rezystorowy |
Musimy pamiętać jeszcze o jednej drobnej rzeczy – piny
RX i
TX modułu
Xplained są połączone z pinami
TxD i
RxD mikrokontrolera
ATMega168/328P znajdującego się na module –
musimy pamiętać, aby przed wykorzystaniem modułu jako przejściówkę RS-USB wczytać do ATMegi program, który nie wykorzystuje tych pinów. W przeciwnym przypadku mogą pojawić się zakłócenia w transmisji. Dodatkową zaletą
Xplained jest to, że posiada on na pokładzie stabilizator
3,3V, możemy więc z niego zasilać
ESP – stosowne napięcie dostępne jest na listwie po lewej stronie modułu.
I to tyle. Jak widzimy wykorzystanie
Xplained Mini jest równie proste jak dedykowanej przejściówki
RS232-USB.
XMEGA pokazuje pazurki…
Jak już napisałem, bardzo lubię mikrokontrolery
XMEGA, pokażę więc jak je wykorzystać do zbudowania przejściówki
USB-RS232 i podłączenia modułu
ESP do
PC-ta. Po co wykorzystywać
XMEGA? Ano jest ku temu kilka powodów. Po pierwsze, pracuje on przy zasilaniu 3,3V, odpada więc konieczność wykonania jakiejkolwiek konwersji poziomów logicznych. Czyli jest prosto.
Jest jeszcze jedna zaleta – w cenie układu
FTDI (oczywiście jeśli kupujemy osobny układ, a nie chiński gotowiec), możemy kupić
XMEGA-ę z wbudowanym interfejsem
USB. Daje nam to o wiele większe możliwości zabawy i przyda się w kolejnych odcinkach o
ESP8266. Do tego na naszym rodzimym rynku jest kilka firm (LeonInstruments, Modułowo), które sprzedają świetne płytki rozwojowe z
XMEGA – dlaczego więc ich nie wykorzystać?
Osoby regularnie czytające bloga wiedzą, że
XMEGA-ę można w prosty sposób oprogramować tak, aby działała jako przejściówka
USB-RS232 – pokazałem to w tym artykule:
XMEGA: Emulacja portu szeregowego na XMEGA
Teraz wykorzystamy to rozwiązanie do stworzenia uniwersalnej przejściówki. W tym celu wystarczy wgrać prosty gotowiec i dodać dosłownie parę linii kodu. A konkretnie, musimy skonfigurować interfejs
UART wykorzystywany do komunikacji z
ESP8266 – w naszym przypadku będzie to
USARTC0 (wykorzystamy piny 2 i 3
PORTC, do których należy podłączyć piny
TxD i
RxD modułu):
void usart_init()
{
PORTC_OUTSET=PIN3_bm;
PORTC_DIRSET=PIN3_bm; //Pin TxD musi być wyjściem
USARTC0.CTRLB=USART_TXEN_bm | USART_RXEN_bm; //Włącz nadajnik USART
USARTC0.CTRLC=USART_CHSIZE_8BIT_gc; //Ramka 8 bitów, bez parzystości, 1 bit stopu
USARTC0.CTRLA=USART_RXCINTLVL_LO_gc; //Włącz przerwanie odbiornika USART
}
Warto zwrócić uwagę na to, że konfigurując
USART nigdzie nie ustawiamy szybkości, z jaką będzie działał. Nastąpi to dopiero w chwili, gdy
PC otworzy nasz port szeregowy, przesyłając deskryptor z konfiguracją portu wybraną przez użytkownika. Zignorujemy większość danych zawartych w przesłanym deskryptorze, wykorzystamy tylko jedną – określającą szybkość pracy
USART:
void uart_config(uint8_t port, usb_cdc_line_coding_t * cfg)
{
//Konfiguracja w odpowiedzi na otwarcie CDC
usart_set_baudrate(&USARTC0, cfg->dwDTERate, F_CPU); //Konfigurujemy USARTC0 tak jak użytkownik skonfigurował VCOMM, ale uwzględniamy tylko baudrate
}
Teraz musimy jeszcze napisać funkcję odbierającą znaki z modułu i wysyłającą je na
USB:
ISR(USARTC0_RXC_vect)
{
udi_cdc_putc(USARTC0_DATA);
}
Po każdym odebranym znaku zgłoszone zostanie przerwanie, w którym odebrany znak będzie transmitowany przez
USB do
PC-ta. To samo musimy jeszcze zrobić ze znakami odbieranymi z
PC-ta przez
USB i wysyłać je do
ESP:
while (1)
{
if(udi_cdc_is_rx_ready())
USART_putchar(&USARTC0, udi_cdc_getc()); //Przepisz to co otrzymałeś na USART sterujący modułem
}
Tym razem w pętli głównej (i tak nie mamy nic ciekawszego do roboty) czekamy aż coś zostanie przesłane przez
USB i wysyłamy to przez
USARTC0 do modułu
ESP8266.
Do pobrania (kompletny projekt w
Atmel Studio):
ESP8266-PC.ZIP (
kopia)
Po odpaleniu programu na
PC powinniśmy zobaczyć nowy port szeregowy – to co na niego wyślemy trafi do
ESP, a to co odbierzemy to komunikaty wysłane do nas z
ESP. Proste prawda?
Zachęcam do wykorzystania
XMEGA do realizacji komunikacji
PC-USB-RS232-TTL-ESP8266 – jest to bardzo uniwersalne rozwiązanie i ma kilka zalet, o których już wspomniałem. Ale ma także inne.
Przede wszystkim jest to mikrokontroler, więc daje nam dużą elastyczność w dodawaniu potrzebnych funkcji. W szczególności możemy wymyślić inny sposób komunikacji niż poprzez wirtualny port szeregowy – ale to dla zaawansowanych. Zaletą, którą z pewnością wykorzystamy to posiadanie wielu linii
IO, którymi możemy sterować, a przede wszystkim możemy je połączyć z liniami
GPIO modułu, dzięki czemu możemy badać jego stan, sterować nimi, lub np. realizować komunikację z modułem przy pomocy innych interfejsów, np.
SPI. Ale o tym później. Dla mnie najważniejszą zaletą wykorzystania
XMEGA jest to, że mam ją pod ręką :-)
Pierwsze testy komunikacji
Ok, podłączyliśmy moduł z
PC-tem – nie ważne na który sposób się zdecydowałeś, dalsze kroki wyglądają identycznie. Czas przetestować połączenie.
Lecz zanim to zrobisz – warto jeszcze raz sprawdzić poprawność połączeń elektrycznych – głupio byłoby sobie na wstępie uszkodzić moduł
WiFi (strata niewielka, ledwie parę złotych), lub port
USB (tu straty mogą być większe). Ponieważ zapewne nie możesz się doczekać pierwszej odpowiedzi z modułu jeszcze w tym odcinku nawiążemy z nim połączenie…
Terminal
Co prawda mamy już wszystkie połączenia, ale na
PC potrzebujemy jeszcze wygodny program, który umożliwi wysyłanie i odbiór danych z i do modułu. W sieci dostępnych jest sporo różnych programów terminali, osobiście lubię
RealTerm – jest on całkowicie za darmo i ma wiele użytecznych funkcji. Zresztą czytelnicy naszego bloga już go kilkakrotnie poznali.
Można go pobrać ze strony domowej projektu:
realterm.sourceforge.net
Po jego pobraniu, odpalamy go i w zakładce
Port wybieramy parametry konfiguracyjne połączenia (szybkość, format danych), wirtualny port szeregowy, który posłuży do realizacji połączenia, a następnie klikamy
Open.
Przykłady użycia Realterm:
Co po resecie?
Moduł
ESP8266 tuż po resecie wysyła na pin
TxD krótki komunikat informujący o przyczynie resetu oraz informacje diagnostyczne. Możemy to wykorzystać do testu komunikacji. W tym celu odpalamy terminal, ustawiamy szybkość transmisji na
76800 bodów (tak, Chińczycy to dziwny ludek, najwyraźniej mają kłopoty z konsekwencją, moduł co chwilę zmienia szybkość pracy
UART),
bez parzystości,
8 bitów danych i
jeden bit stopu, czyli w skrócie:
76800 8N1
Po ustawieniu terminala i nawiązaniu połączenia na chwilę łączymy wejście modułu
REST (od RESET, kolejny Chiński akronim) do masy, po czym zostawiamy je niepodłączone lub łączymy do
Vcc. W efekcie powinniśmy zaobserwować komunikat wysyłany przez moduł:
 |
Pierwsza komunikacja |
Jeśli otrzymaliśmy taki lub podobny komunikat to znaczy, że wszystko jest na dobrej drodze i mamy połączenie.
Pamiętaj, że jeśli zamiast powyższego komunikatu otrzymasz ciąg dziwnych znaków to też nie jest źle – po prostu wybrałeś niewłaściwą szybkość transmisji, lecz komunikacja jest ok i nie ma się czym przejmować.
Jeśli natomiast nie uzyskałeś nic to:
- sprawdź jeszcze raz wszystkie połączenia i poprawność montażu (nawet, jeśli sprawdzałeś to już 100 razy to sprawdź i sto pierwszy),
- sprawdź, czy połączyłeś piny TxD przejściówki z RxD modułu i RxD przejściówki z TxD modułu,
- co jest mało prawdopodobne, ale możliwe – Chińczycy znowu coś zmienili w firmware i twój moduł nie wysyła żadnych komunikatów przy starcie – nie liczyłbym na to, ale kto wie. Jeśli spotkasz się z taką sytuacją to koniecznie daj nam znać.
Magia z GPIO15
Dla poprawnego startu modułu pin GPIO15 (o ile występuje na module) powinien mieć stan niski. Na modułach, na których pin ten nie jest wyprowadzony najprawdopodobniej odpowiednie wejście chipsetu jest połączone z masą na stałe. Na modułach, które posiadają ten pin może być różnie.
Jak zwykle musimy zdawać sobie sprawę z tego, że normy, standardy i logika to coś zupełnie dla inżynierów z Chin niepojętego i nie przywiązują do tych pojęć dużej wagi.
W niektórych modułach pin ten jest połączony z masą (poprzez jakiś rezystor ściągający do GND?), na innych najwyraźniej nie.
W efekcie, jeśli widzisz w terminalu, że bootowanie kończy się na napisie „
waiting for host” (tak jak na poprzednim screenshocie), to spróbuj połączyć
GPIO15 na stałe do masy. Bez tego chip nie wejdzie w
tryb poleceń AT i dalsza komunikacja nie będzie możliwa. Jeśli bootowanie przebiegło pomyślnie to powinieneś zobaczyć coś mniej więcej takiego:
 |
Prawidłowe bootowanie |
Jak widzisz, po kilku liniach sensownych informacji, pozwalających się zorientować m.in. w typie modułu i ilości dostępnej pamięci
FLASH, na końcu mamy jakieś śmieci. Czy to problem? Otóż nie, to kolejny przykład na to, że myśli Chińczyków biegną własnymi, niekoniecznie prostymi torami … otóż jak już wspomniałem, moduł rozpoczyna bootowanie ustawiając
UART na
76800 8N1, ale w trakcie zmienia ustawienia na
9600 8N1 lub na
115200 8N1 (
zależy to od wersji firmware, więc sprawdź obie możliwości).
Ponieważ dalsze komunikaty są wysyłane już przy innej szybkości
USART będziemy obserwować właśnie owe śmieci. W efekcie, jeśli ustawimy szybkość
UART na docelową dla danego modułu (
9600 lub
115200) to początek komunikatu będzie składał się ze śmieci, za to końcówka będzie zrozumiała:
 |
Prawidłowe bootowanie ze zmienioną szybkością |
Dla nas istotne jest jedno – cały przesłany komunikat powinien zakończyć się ciągiem „
ready \n\r”. Jeśli tak się stało to znaczy, że moduł jest gotowy do pracy i oczekuje na nasze polecenie.
Wydajmy więc pierwsze polecenie (komendę AT)
AT+GMR – jest to polecenie wyświetlające aktualną wersję firmware i
SDK używanego przez moduł. Polecenia przesyłamy w zależności od używanego terminala. W
RealTerm, przechodzimy do
zakładki Send, w której wpisujemy polecenie
AT+GMR, jednocześnie pamiętając, żeby w polu
EOL (znaki końca linii) koniecznie zaznaczyć
+CR + LF. Dzięki temu terminal do każdego wysyłanego łańcucha automatycznie doda znaki końca linii, które są wymagane przez moduł dla poprawnego rozpoznania polecenia.
W odpowiedzi powinniśmy uzyskać mniej więcej coś takiego:
 |
Pierwsze polecenie - AT+GMR |
Jak widzimy uzyskaliśmy informację, że moduł zawiera
wersję parsera komend AT 0.23.0.0 z kwietnia 2015 roku oraz
wersję SDK 1.0.1.
Co ważne każde polecenie AT kończy się komunikatem OK. Dzięki temu wiemy, że moduł poprawnie zinterpretował i wykonał polecenie.
Możemy jeszcze wydać polecenie
AT+RST, w wyniku którego moduł jest resetowany, a my uzyskujemy komunikaty jak poniżej:
 |
Resetowanie modułu poleceniem AT+RST |
Dlaczego o tym poleceniu wspominam? Właściwie z jednego powodu – aby po raz kolejny pokazać „konsekwencję” inżynierów. Tym razem, podczas resetu nie jest zmieniana szybkość
UART, w efekcie poprawnie zobaczymy wszystkie komunikaty towarzyszące resetowi.
Możemy jeszcze przetestować część radiową modułu – w tym celu wydajemy polecenie
AT+CWMODE=3 i
AT+CWLAP, w efekcie powinniśmy otrzymać
listę Access Pointów znajdujących się w otoczeniu:
 |
Pierwsza komunikacja radiowa |
Ok, najtrudniejsze mamy za sobą – mamy komunikację z modułem, widzimy sieci bezprzewodowe, w kolejnej części zajmiemy się nawiązywaniem połączenia i przesyłaniem danych.