sobota, 4 maja 2019

Moduł WiFi ESP8266-01 i Arduino - publikowanie danych z czujnika DHT11 w ThingSpeak

ESP8266-01 to niewielki moduł umożliwiający komunikację Arduino po WiFi ze światem zewnętrznym. Z racji na bardzo przystępną cenę i podobny jak w Arduino próg wejścia moduł ten jest świetnym kandydatem dla projektów IOT. Co więcej, sam może pracować w roli pełnoprawnego mikrokontrolera. Tworzenie kodu i jego przesyłanie do ESP możliwe jest z poziomu Arduino IDE. W tym poście dane z czujnika DHT11 postaram się przesłać na platformę IoT - ThingSpeak, gdzie będą one dostępne w postaci wykresów.

ESP8266-01
Zgromadzone w serwisie dane można importować do pliku CSV i dalej przetwarzać na przykład w programie kalkulacyjnym. W wersji darmowej ThingSpeak, żądania (requesty HTTP) mogą być wysyłane nie częściej niż co 15 sekund.


Specyfikacja
  • napięcie zasilania 3,3V
  • pobór prądu do 300mA
  • standard WiFI 802.11 b/g/n, 2,4GHz
  • wsparcie zabezpieczeń: WPA, WPA2
  • wsparcie dla komend AT
  • 8 pinów
    • w tym 3 piny I/O
    • interfejs UART
  • wbudowana pamięć Flash 1MB
  • LED-y sygnalizujące pracę modułu (zasilanie - czerwony i transmisję danych - niebieski). Jeden z posiadanych modułów ma tylko niebieski LED - więc tu bywa różnie.
  • wymiary: 24,8 x 14,3mm
Posiadane przeze mnie moduły są koloru czarnego (płytka PCB) i mają po 1MB pamięci Flash. Wersje w kolorze niebieskim mają po 500kB i tych trzeba się wystrzegać.


Piny modułu

Pin(y) Opis
Vcc Zasilanie 3,3V
GND Masa
Tx Pin TX złącza szeregowego
Rx Pin RX złącza szeregowego
RST Reset układu stanem niskim na tym pinie
CH_PD (EN) Chip enable pin - podanie stanu niskiego powoduje przejście w tryb uśpienia. Do aktualizacji oprogramowania oraz komunikacji przez UART należy podać stan wysoki
GPIO0 Wyprowadzenie GPIO nr 0. Do aktualizacji, należy podać stan niski (połączyć z GND).
GPIO2 Wyprowadzenie GPIO nr 2.

Patrząc na schematy podłączenia ESP dostępne w sieci, są różnice w podłączeniu pinów RST i CH_PD. Ja zostawiam niepodłączony pin RST i CH_PD podpięty bezpośrednio do wysokiego napięcia (3,3V). Nie mniej jednak jest wiele schematów, gdzie CH_PD jest wpięty do napięcia zasilania przez rezystor 10k. Z kolei RST można spotkać podłączone do napięcia zasilania bezpośrednio lub przez rezystor 3,3k.
Rozkład i przeznaczenie pinów (simba-os.readthedocs.io)

Na AliExpress można znaleźć parę modułów przystosowanych bezpośrednio do pracy z tym modułem ESP. Moduły te wyposażone są w gniazda przeznaczone dla ESP. Ja nabyłem kilka widocznych na zdjęciu poniżej, m.in. moduł programatora, sterownik LEDów WS2812, czujnik temperatury i wilgotności DHT11, czujnik temperatury DS18S20, moduł z przekaźnikiem oraz przejściówkę umożliwiającą wpięcie ESP do płytki stykowej.

Przykłady modułów współpracujących  z ESP8266-01

Na AliExpress można spotkać także moduły z dwoma i czterema przekaźnikami oraz moduły z czujnikami DHT22 i DS18B20. Dostępne są też programatory z przełącznikiem między normalną pracą a trybem programowania i lepiej te wybierać. Ja akurat kupiłem moduł bez zworki i musiałem ją dolutować między pinem masy a pinem GPIO0. Niebezpośrednio jednak robię zwarcie, tylko poprzez rezystor SMD1206 o wartości 470. Chodzi o ograniczenie prądu w sytuacji, gdy na tym pinie jest ustawiony stan wysoki i bez tego rezystora nastąpiłoby zwarcie. Zworka (zwarcie GPIO0 z masą poprzez rezystor 470) używana jest w trybie programowania i rozwarta przy normalniej pracy/komunikacji z ESP.


Posiadany programator

Dodana zworka między GND i GPIO0 
Uruchomienie

Przed rozpoczęciem zabawy, należy pamiętać o paru rzeczach, które mogą zniszczyć opisywany układ:
  • napięcie zasilania to 3,3V. Wyższe (np. 5V) zniszczy układ. To samo dotyczy pinów ESP (nie mniej jednak w sieci można znaleźć bezpośrednie łączenie pinów Arduino Uno do złącza szeregowego ESP) - maks. 3,3V. Ponadto wydajność prądowa źródła na poziomie co najmniej 500mA.
  • programator także musi dostarczać napięcie 3,3V
  • maksymalne napięcie na wejściu przetwornika ADC to 1V
  • maksymalny prąd wyjściowy na pinach I/O (wejścia/wyjścia) to 12mA
Kolejny krok to konfiguracja Arduino IDE opisana m.in. tutaj. W skrócie instaluje się dodatkowy pakiet dla obsługi modułów ESP8266. Następnie trzeba wybrać z menu Tools/Board opcję "Generic ESP8266 Module" i odpowiedni port COM pod którym jest wpięty konwerter/programator USB. Teraz pod IDE można wybrać m.in. taki przykład jak WIFIScan i wgrać na ESP. Następnie, po usunięciu zworki programowania (programator) i otwarciu okienka monitora portu szeregowego (Arduino IDE), powinny pokazać się znalezione identyfikatory pobliskich sieci WIFI.

Aktualizacja firmware

Po wgraniu przykładu powyżej, pojawia się pytanie, jak wyczyścić ESP z powyższego kodu, aby powrócić do komunikacji komendami AT po interfejsie szeregowym. Może też zajść potrzeba aktualizacji oprogramowania. Do wgrania firmware'u użyłem programu ESP8266 Download Tool (wersja 3.8.5) oraz firmware ESP8266_NonOS_AT_Bin_V1.7.4ai-thinker-v1.1.1.bin. Konfiguracja widoczna jest na screenie.

 



Test przy użyciu terminala 

Zakupiony moduł posiada wgrany firmware AI-Thinker, który umożliwia komunikację z modułem za pomocą komend AT ze standardową prędkością 115200. Skorzystałem z terminala dostępnego w Arduino IDE. Poza wspomnianą prędkością musiałem jeszcze zmienić kodowanie końca linii z  "Newline" na "Both NL & CR". Dopiero wtedy udało mi się dla wysłanej komendy "AT" otrzymać oczekiwany wynik w postaci "OK".

Przykłady kilku poleceń (jeśli nie działają trzeba ustawić tryb pracy modułu - AT+CWMODE)
  • Sprawdzenie wersji firmware:
    AT+GMR
  • Miękki reset:
    AT+RST
  • Ustawienie modułu jako klienta
    AT+CWMODE=1
    możliwe inne opcje: 2 - Access Point, 3 - klient + Access point
  • Podłączenie do sieci WIFI (po resecie automatyczne łączenie do podanej wcześniej sieci WIFI)
    AT+CWJAP="ssid","pass"
  • Aktualny adres IP
    AT+CIPSTA?
  • Zamykanie połączenia
    AT+CWQAP
  • Wyszukiwanie lokalnych sieci WIFI:
    AT+CWLAP
Terminal - wersja firmware

Na dłuższą metę takie korzystanie z modułu za pomocą komend AT i terminala jest mało pasjonujące i przychodzi czas na napisanie jakiegoś kawałka kodu. Można na przykład w kodzie Arduino zaszyć komendy AT i za ich pomocą komunikować się z ESP8266. Można też w Arduino IDE pisać kod pod ESP i go flash'ować. W obu przypadkach jest to C/C++ (tyle, że bardziej strawne). Istnieją jeszcze inne możliwości tworzenia kodu na ESP w zamierzeniu prostsze niż C/C++, bo pisane w językach wyższego poziomu.
  • skrypty LUA na firmware NodeMcu. Na stronie LUA chwalą się, że "Lua is a powerful and fast programming language that is easy to learn and use and to embed into your application"
  • MicroPython - skrojona pod mikrokontrolery wersja Pythona
  • JavaScript na firmware Espruino

Więcej na temat komend jest w dokumencie ESP8266 AT Instruction Set.


ESP8266 jako moduł WIFI dla Arduino Uno

Zgodnie z tytułem postaram się wysłać wyniki pomiarów dostarczane przez DHT11 do serwisu ThingSpeak.com. To jedna z najpopularniejszych platform IoT, na której można w przystępny sposób zbierać i prezentować przesłane dane z poziomu strony WWW. W tym podejściu, czujnik jest obsługiwany przez Arduino Uno. Arduino za pośrednictwem interfejsu szeregowego wysyła wyniki pomiarów do ESP, skąd trafiają do sieci WWW przesyłane w postaci requestów HTTP.


Prototyp układu

Uruchomienie układu raczej było bezproblemowe, choć nie obyło się bez dymu. W opisywanych wcześniej modułach, wpięty moduł ESP "wchodzi/przesłania" płytkę modułu. Okazuje się, że w przypadku wspomnianej wcześniej przejściówki do płytki stykowej jest odwrotnie (widać to na zdjęciu powyżej). W konfiguracji "ESP nad przejściówką" wyjście zasilacza (plus) jest zwierane do masy i właśnie dlatego dym pochodził od układu scalonego (stabilizatora 3,3V) w zasilaczu. Druga rzecz, to podanie stanu wysokiego (3,3V) na pin CH_PD - przynajmniej ja o tym zapomniałem. Poza tym konieczna jest jakaś konwersja poziomu sygnału na wyjściu TX z Arduino. Użyłem tu dzielnika napięcia.

Schemat połączeń

Odnośnie kodu - użyłem biblioteki adafruit/DHT-sensor-library do obsługi DHT11. Dodatkowo wymagana  jest adafruit/Adafruit_DHT_Unified. Może to trochę przerost treści nad formą, bo w sieci można znaleźć kilkanaście linii obsługi tego czujnika. Jednak wolę wygodę w kodowaniu, dopóki wystarcza pamięci ;) Do uruchomienia przykładu wymagane jest podanie identyfikatora własnej sieci WIFI (zmienna HOST), hasła do sieci (zmienna PASS) oraz klucza (zmienna API)  dostępowego do API ThingSpeak wygenerowanego na tej stronie. Dodatkowo, ustawienie stałej DEBUG na true powoduje pokazywanie w terminalu komend AT wysyłanych z Arduino do ESP.

#include "SoftwareSerial.h"
#include <DHT_U.h>
#include <DHT.h>

#define DHTPIN 2
#define DHTTYPE DHT11
#define RX 10
#define TX 11

#define DEBUG false

String API = "your_api_key";
String HOST = "api.thingspeak.com";
String PORT = "80";

String AP = "your_ssid";
String PASS = "your_password";
String temp, hum, hic;
String request;

SoftwareSerial esp(RX, TX);
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  initSerial();
  initDht();  
  initEsp();
}

void initSerial()
{
    Serial.begin(9600);
}

void initDht()
{
    dht.begin();
}

void initEsp() 
{
    esp.begin(115200);
    espData("AT+RST", 1000);
    espData("AT+CWMODE=1", 1000);
    espData("AT+CWJAP=\""+ AP +"\",\""+ PASS +"\"", 1000);
    while (!esp.find("OK")) {          
        //Wait for connection
    }
    delay(1000);
}

void loop()
{
    doMeasure();
    sendRequest();
    delay(10000);
}

void doMeasure()
{
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    if (isnan(h) || isnan(t)) {
        Serial.println("Failed to read from DHT sensor!");
        return;
    }

    temp = String(t);
    hum = String(h);
    hic = String(dht.computeHeatIndex(t, h, false));
}

void sendRequest()
{
    request = "GET /update?api_key="+ API +"&field1="+String(temp)+"&field2="+String(hum)+"&field3="+String(hic);
    espData("AT+CIPMUX=1", 1000);
    espData("AT+CIPSTART=0,\"TCP\",\""+ HOST +"\","+ PORT, 1000);
    espData("AT+CIPSEND=0," +String(request.length()+4), 1000);
    esp.find(">");
    esp.println(request);     
    espData("AT+CIPCLOSE=0", 1000);
}

String espData(String command, const int timeout)
{ 
    Serial.print("AT Command ==> ");
    Serial.print(command);
    Serial.println("     ");
    String response = "";
    esp.println(command);
    long int time = millis();
  
    while ( (time + timeout) > millis()) {
        while (esp.available()) {
            char c = esp.read();
            response += c;
        }
    }

    if (DEBUG) {
        Serial.print(response);
    }
  
    return response;
}

Komendy AT wysyłane przez Arduino

Na wykresach widać efekt chwilowego przyłożenia kciuka do czujnika. Dane odbierane są co 10 sekund. W przypadku ciągłego zbierania danych trzeba by ten czas wydłużyć do 15 sekund z racji na wspomniane wcześniej ograniczenia darmowego konta w ThingSpeak.

Wykresy z wynikami pomiarów na ThingSpeak

Źródła:
1) ThingSpeak
2) ESP8266EX Datasheet
3) ESP8266 Technical Reference
4) A Beginner's Guide to the ESP8266 (świetny wstęp do ESP8266)
5) ESP8266 a Complete Beginners Guide (IOT)
6) Instalacja obsługi ESP8266 w IDE Arduino
7) ESP8266 Arduino Core’s documentation
8) ESP8266 AT Instruction Set
9) Connect ESP8266 to ThingSpeak

Brak komentarzy:

Prześlij komentarz