Stabilność ESP8266

Ktoś z was miał może już jakieś większe doświadczenia z tym popularnym modułem? Ja dopiero zaczynam eksperymenty - pobawiłem się połączeniami pod terminalem, ale jeszcze nie złożyłem na nim żadnego większego projektu z MCU. Powoli projektuję jednak płytkę zegara nixie z synchronizacją czasu po NTP. Czy moduł można uznać za stabilny? To znaczy raz włączony będzie działał bez samodzielnego zawieszania się? Nie liczę tutaj oczywiście sytuacji, do których może dojść z winy użytkownika.

Pytam, ponieważ rozpoczynając eksperymenty z ENC28J60 (a później także W5100) natknąłem się na kilka mitów dotyczących ich stabilności. Układy miały się rzekomo nie nadawać do zastosowań takich jak automatyka domowa czy telemetria, ze względu na tendencję do samodzielnego wieszania się i zrywania połączeń. Tymczasem praktyka pokazała coś zupełnie innego - zaprojektowane przeze mnie płytki z tymi układami działają już dobre pół roku i przez ten czas udawało im się nabijać uptime liczony w tygodniach, jeśli nie miesiącach.

Czy istnieje jakaś różnica w stabilności pomiędzy poszczególnymi wersjami modułów? Bo na rynku dostępnych jest kilkanaście różnych odmian

- zaczynając od najpopularniejszej "01" (antena PCB i goldpiny) kończąc na znacznie bardziej profesjonalnie wyglądających modułach z anteną ceramiczną i metalowym ekranem nad elektroniką.

Może mity biorą się od początkujących użytkowników Arduino, którzy nie wiedzą, że taki moduł potrzebuje jednak odpowiednio wydajnego źródła zasilania i kondensatorów filtrujących w pobliżu pinu VCC?

Reply to
Atlantis
Loading thread data ...

Poszukaj w archiwum, kilka miesięcy temu była dyskusja o jego stabilności, kilku użytkowników opowiedziało swoje doświadczenia. Ogólnie nie jest źle.

Reply to
Marek

Hmm... Wczoraj zauważyłem ciekawą kwestię w związku z działaniem tego modułu. Najpewniej w oprogramowaniu jest jakiś błąd, bo połączenia UDP nie chcą działać prawidłowo, gdy korzystam z DNS-a. W przypadku TCP wszystko jest w porządku - po podaniu nazwy hosta (np. google.pl) połączenie zostało zestawione i udało mi się wymienić dane. Potem spróbowałem połączyć się z serwerem NTP i zaczęły się dziać dziwne rzeczy. System niby przyjął nazwę hosta (nie zwrócił "DNS fail") i rozpoczął procedurę wysyłania danych ("AT+CIPSEND=4,48", zwrócony znak ">"). Niestety nie przebiegała ona tak, jak powinna - po otrzymaniu 48 bajtów program nadal oczekiwał na kolejne dane. Dopiero wysłanie mu sporego nadmiaru danych (w tym chyba jakiejś komendy zakończonej "\r\n") spowodowało wyświetlenie błędu. Od tego momentu miałem już tylko "Busy inet..." i z modułu nie dało się korzystać. Próba połączenia się z serwerem NTP przez podanie numeru IP daje pozytywny skutek - moduł po otrzymaniu 48 bajtów zwraca "SEND OK".

Czy ktoś z Was zetknął się z podobnym błędem? Może dostępna jest jakaś nowsza wersja firmware'u z odpowiednią poprawką?

BTW ktoś wie coś na temat jakiejś biblioteki do obsługi tego modułu? Wszystko co widzę w sieci (głównie rozwiązania dla Arduino) wykorzystują spore delay'e do oczekiwania na odpowiedź modułu. Ja preferowałbym jednak rozwiązanie oparte o flagi i zdarzenia, mam ogólny zamysł jak to mogłoby wyglądać, ale nie chciałbym wyważać otwartych drzwi - zawsze łatwiej przeportować gotową bibliotekę, niż pisać własną od podstaw.

Reply to
Atlantis

formatting link

formatting link

Mógłbyś jaśniej to opisać, po co delaye skoro muszą i tak czekać na odpowiedź?

Reply to
Marek

A chyba już wiem, wysyłają polecenie AT, delay oczekując na odpowiedź, po czym sprawdzają bufor odbiorczy uarta... ależ to jest bardzo nieefektywne, zamiast delay procek mógłby robić w tym czasie coś innego.

Reply to
Marek

W dniu 2015-01-28 o 10:33, Marek pisze:

No właśnie wiem. ;) Dlatego gdybym ja się za to zabierał, to wszystko robiłbym na flagach i zdarzeniach. Na przykład wysyłając dane ustawiamy odpowiednią flagę i podajemy funkcji w pętli głównej wskaźnik do bufora. Dopóki flaga jest ustawiona, nie możemy rozpocząć kolejnego wysyłania, a czyści się ją po odebraniu "SEND OK". Podobnie można postąpić z "ready" i innymi sygnałami kontrolnymi. Sprawdzane byłoby też pojawienie się ">\r\n". Oczywiście wszystkie odpowiedzi byłyby odbierane i parsowane "w tle", przez funkcję w pętli głównej.

Nieco problematyczny jest tylko odbiór danych, które mogą się pojawić w dowolnym momencie jako "+IDP,<soc>,<len>:<data>\r\n". Sęk w tym, że ciąg danych może składać się z większej ilości linii, więc odebranie "\r\n" nie musi oznaczać końca odbioru danych. Trzeba by dać instrukcję warunkową, która sprawdza czy linijka po ":" zawiera mniej znaków niż "len" - jeśli tak, trzeba by uruchomić specjalny tryb odbioru danych, w którym kolejne napływające znaki nie są parsowane jako komendy, ale doklejane do końca bufora, aż do pobrania zadanej ilości.

Reply to
Atlantis

W dniu 2015-01-28 o 10:08, Marek pisze:

To jest najnowsza, oficjalna wersja firmware'u, czy jakieś alternatywne oprogramowanie, zmodyfikowane przez kogoś ze społeczności użytkowników?

Reply to
Atlantis

Obsługę modemu robi się maszyna stanów i bufirem fifo uarta, nie ma wtedy problemu z "unsolicited codes".

Reply to
Marek

alternatywne

użytkowników?

Z tego co czytałem chyba nie istnieje "oficjalna" nowa wersja, nowe sa tylko wersje społecznościowe. Ale mogę się mylić.

Reply to
Marek

W dniu 2015-01-28 o 12:14, Marek pisze:

Hmm... Możesz napisać coś więcej? Sam nie bawiłem się tym jeszcze, ale z tego co widzę po znajomych, to sporo osób (przyzwyczajonych do obsługi modułów Ethernet na SPI) narzeka na rozwiązanie przyjęte w ESP8266. Z drugiej strony praktycznie taki sam mechanizm od lat stosuje się w modemach, więc muszą istnieć jakieś sprawdzone rozwiązania. ;)

Reply to
Atlantis

W dniu 2015-01-27 o 10:06, Atlantis pisze:

Niekoniecznie to są mity. Mi W5500 po kilku, kilkunastu godzinach testów obciążeniowych potrafi "odłączyć" socket w trybie UDP (brak przerwań, nie zwiększa się licznik ilości danych odebranych, zawartość wszystkich rejestrów wygląda poprawnie). Niestety, nie udało mi się jak dotąd stworzyć reguły dającej 100% pewności, że socket się zawiesił i trzeba go ponownie zainicjować.

Reply to
Andrzej W.

Oj to dużo pisania, trochę nie na temat grupy. Ale tak ogólnie to są dwie ważne sprawy, pierwsza to prawidłowa obsługa bufora cyklicznego fifo, do którego pisze przerwanie uarta po odebraniu znaku. Bardzo fajnie jest to opisane w tym dokumencie (od strony 36)

formatting link
(nota bene dokument opisuje fajną minimalistyczną implementację ppp/tcp/udp na 8 bit mcu, sprawdzone, działa). Drugi bufor, to podręczny bufor api (aplikacyjny), do którego są "wyciągane" z fifo kolejne znaki i na podstawie jego zawartości api przełącza się w odpowiednie stany, obsługujące dane zdarzenie. Druga sprawa to opisanie wszystkich możliwych stanów maszyny. Najważniejszym stanem jest SM_IDLE, w której się oczekuje na "unsolicited codes". Kolejnym stanem może być np. SM_RECEIVE_SMS, w który się przełączamy ze stanu SM_IDLE po odebraniu np. +CMTI i powrót z powrotem do SM_IDLE, gdy zakończyliśmy procesowanie odebranego smsa. Zaletą takiego modelu jest to, że każdy stan jest nieblokujący mcu: gdy nie ma żadnego znaku do pobrania z fifo to nie ma nic do roboty i można wrócić do "main_loop". Gdy jest znak to go wyciągamy z fifo i sprawdzamy czy po "dołożeniu" go do lokalnego bufora mamy już kompletną odpowiedź modemu, jeśli nie znowu wracamy do "main_loop". Natomiast gdy mam już kompletną odpowiedź to ją identyfikujemy i przełączamy się na odpowiedni stan aby ją przeprocesować. Gdy api jest dłużej w jakimś stanie procesującym (nie sprawdza czy coś jest "nowego" w fifo), nieoczekiwane dane z modemu nie zginą bo są buforowane przez przerwanie piszące do fifo. Te dane zostaną odebrane z fifo po powrocie do stanu SM_IDLE.

"Unsolicited codes" nie pojawiają się np. w połowie odpowiedzi na jakieś polecenie AT, stąd nie ma zagrożenia, że popsują kontekst tej odpowiedzi (innego polecenia). Na uarcie musi być chwilowa cisza między komendami AT aby modem zwrócił taki kod. Sposób wysyłania tych kodów konfiguruje się poprzez AT+CNMI, najbezpieczniejsze jest AT+CNMI=3,1,0,0,0 bo to własnie włącza buforowanie sygnalizacji zdarzenia (gdy wystąpi w trakcie odpowiedzi na inne polecenie lub gdy modem jest w trybie data a nie command). W takim przypadku kod zostanie przesłany po zakończeniu transmisji poprzedniej odpowiedzi (pod warunkiem chwilowej "ciszy", o której wspomniałem wyżej).

To tak bardzo ogólnie. Oczywiście każdy stan może mieć swój "lokalny" idle, w których czeka np. na OK\r\n po jakimś poleceniu. Jak się podgląda taka komunikację "nodelay" na uarcie to bardzo ładnie ona wygląda, jest szybka i płynna.

Reply to
Marek

BTW mam jeszcze jedno pytanie co do tego modułu. Jaki jest właściwy sposób jego podłączenia? Na większości stron z przykładami dla Arduino podaje się następujące rozwiązanie:

VCC - wiadomo, zasilanie 3.3V GND - wiaodmo, masa RX - pin TX mikrokontrolera TX - pin RX mikrokontrolera CH_PD - podłączony bezpośrednio do VCC RST, GPIO0 i GPIO2 - wiszące w powietrzu

W tej chwili mam moduł podłączony właśnie w ten sposób. Działa... Niemniej nie podobają mi się pewne rzeczy:

1) Czy CH_PD nie powinien być podciągnięty rezystorem do VCC, a nie połączony bezpośrednio? 2) Czy tak samo piny RST, GPIO0 i GPIO2 nie powinny mieć ustalonej wartości przez podciągnięcie do VCC lub masy jakimś rezystorem?

Niektóre opisy radzą zresztą, żeby cztery środkowe piny podciągnąć do plusa, można tak przeczytać np. tu:

formatting link

Reply to
Atlantis

Nawet na główną Wykopu trafiło :)

formatting link

Reply to
Grzegorz Niemirowski

W dniu 2015-01-28 o 16:23, Marek pisze:

Z buforami cyklicznymi akurat jakoś sobie radzę - stosuję je standardowo w swoich projektach, zarówno po stronie odbiorczej, jak i nadawczej.

Hmm... Czyli krótko mówią mogę zrobić to np. za pomocą tablicy, w której będę trzymał typ strukturalny złożony z łańcucha tekstowego (wszystkie możliwe komendy zmieniające stan) oraz jakiejś zmiennej (np. enum) określającej ten stan. Potem w pętli głównej cyklicznie pobieram kolejny znak z bufora cyklicznego i na bieżąco sprawdzam (strncasecmp_P) czy zawartość bufora pokrywa się z którymś z tekstów umieszczonych w tabeli. Jeśli tak - ustawiam przypisany mu stan. Oczywiście to, co odbywa się w danym momencie w pętli głównej musiałoby zależeć od obecnego stanu - inaczej program zachowywałby się podczas oczekiwania na komendę, inaczej podczas odbierania znaków składających się na SMS-a albo nadchodzące dane TCP.

Reply to
Atlantis

Przykład szkieletu stanów i ich obsługi z moich wypocin:

typedef enum { SM_INITIALIZE=0, SM_WAIT_FOR_INIT, SM_EVENT_WAIT_INIT, SM_EVENT_WAIT, SM_RETR_SMS_R, SM_RETR_SMS_W1, SM_RETR_SMS_W2, SM_SEND_INIT, SM_SEND_WAIT1, SM_SEND_P2, SM_SEND_WAIT2, SM_SEND_NETWORKQ_INIT, SM_SEND_NETWORKQ_WAIT, SM_STATUS_GET, SM_STATUS_WAIT, SM_CALLOUT_SET, SM_CALLOUT_WAIT, SM_HANGUP_SET, SM_HANGUP_WAIT }SM_STATE;

static SM_STATE gsm_state;

void gsm_task() {

switch (gsm_state) { case SM_INITIALIZE: // break;

case SM_WAIT_FOR_INIT: // break; ....

} }

W pętli głównej w main () wywołujesz tylko gsm_task();. Zajrzyj do pdfa do którego podawałem link w poprzednim poście, do źródła ppp.c, cały ppp jest zrobiony na maszynie stanów.

Reply to
Marek

No cóż... Dwie kolejne obserwacje:

1) Należy BARDZO uważać ze stosowaniem komendy AT+CIUPDATE, która ma rzekomo przeprowadzać internetową aktualizację firmware'u modułu. Tak naprawdę jednak (w zależności od wersji posiadanego FW) albo generuje błędy, albo brickuje moduł - na szczęście odwracalnie. 2) W najnowszej wersji firmware'u AT
formatting link
ciągle występuje błąd z wysyłaniem danych UDP, jeśli korzystamy przy tym z DNS-a. Może Chińczycy jeszcze go nie zauważyli? ;)
Reply to
Atlantis

Wcale się nie śmiej, w chińskiej dokumentacji do prostych urządzeń/modułów używających tcp/up przykłady z adresami ip zamiast nazw to standard, wcale bym się nie zdziwił, że nie przetestowali z nazwami hosta. Nawę hosta na pewno prawidłowo podajesz w argumencie polecenia (cytowanie stringa)?

Reply to
Marek

W dniu 2015-01-29 o 18:27, Marek pisze:

Będę musiał sprawdzić, czy da się do kogoś w tej sprawie napisać...

Testuję pod terminalem, zapis wygląda następująco: AT+CIPSTART=4,"UDP","time.windows.com",123\r\n Gdzie \r" to znak powrotu, a "\n" to znak nowej linii.

Reply to
Atlantis

Hmm... Wgranie poniższego softu usunęło problem. W dodatku znacząco zmniejszył się czas odpowiedzi na pinga.

formatting link

Reply to
Atlantis

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.