[ESP8266] - Zegar pogodynka

Pozostałe układy mikrokontrolerów, układy peryferyjne i inne, nie mieszczące się w powyższych kategoriach.
Awatar użytkownika
inż.wielki
User
User
Posty: 307
Rejestracja: niedziela 20 gru 2015, 23:11

[ESP8266] - Zegar pogodynka

Postautor: inż.wielki » sobota 03 mar 2018, 00:38

Ahoj!

Jak zapowiadałem, tak zrobiłem, w ciągu tygodnia powstał twór zegarko podobny. A wszystko zaczęło się od tego że od majrfienda przyszedł oled 0,96".
Pierwsze co, podpiąłem go do Arduino i spróbowałem coś wyświetlić z całkiem pozytywnym skutkiem. Zaskoczyła mnie jakość wyświetlanego tekstu, mimo małych rozmiarów wszystko było czytelne. Na początku nie bardzo wiedziałem co z tym zrobić, więc postanowiłem uruchomić oleda na ESP8266 i tak docieramy do sedna.

Projekt realizuje:
  • pokazywanie aktualnej daty i godziny
  • Synchronizacja daty i godziny z serwerami NTP
  • Prezentowanie temperatury wewnątrz i na zewnątrz pomieszczenia
  • Prezentowanie wilgotności wewnątrz i na zewnątrz pomieszczenia

To co jest warte zanotowania, nie został tutaj użyty żaden czujnik zewnętrzny. Parametry zza okna pobierane są z portalu http://openweathermap.org/ za pomocą API.

Zanim przejdę do omówienia kodu, parę zdjęć z działania:
Zegar:
IMG_20180302_230718_HDR.jpg

IMG_20180302_230622_HDR.jpg


Pomiar temperatury:
IMG_20180302_230648_HDR.jpg


Pomiar wilgotności:
IMG_20180302_230627_HDR.jpg


Wróćmy jednak do pogody. Jest to bardzo prosta metoda, pozwala na pobranie bardzo dużej ilości parametrów z dowolnego miejsca na świecie, jako parametr odniesienia można podać nazwę miasta, jego kod (do znalezienia w dokumentacji), lub też współrzędne geograficzne. Po więcej odsyłam do dokumentacji http://openweathermap.org/current .
A teraz przybliżę tak pokrótce czego ja użyłem i jak to wykorzystać.

Generalnie korzystanie z API sprowadza się do wysłania odpowiednio spreparowanego zapytania HTTP, a w odpowiedzi otrzymujemy dane w różnej postaci. Ja wykorzystałem format JSON. Wygląda to tak:

Zapytanie:

Kod: Zaznacz cały

http://samples.openweathermap.org/data/2.5/weather?id=2172797&appid=b6907d289e10d714a6e88b30761fae22

To jest zapytanie testowe, wyciągnięte z dokumentacji.

Rezultat:

Kod: Zaznacz cały

   {
   "coord":{"lon":145.77,"lat":-16.92},
   "weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03n"}],
   "base":"stations",
   "main":{"temp":300.15,"pressure":1007,"humidity":74,"temp_min":300.15,"temp_max":300.15},
   "visibility":10000,
   "wind":{"speed":3.6,"deg":160},
   "clouds":{"all":40},
   "dt":1485790200,
   "sys":{"type":1,"id":8166,"message":0.2064,"country":"AU","sunrise":1485720272,"sunset":1485766550},
   "id":2172797,
   "name":"Cairns",
   "cod":200
   }


Kod:

Kod: Zaznacz cały

static uint32_t tcp_send_packet(void)
{
    char *string = "GET /data/2.5/weather?id=2172797&appid=b6907d289e10d714a6e88b30761fae22\r\n\r\n ";
    uint32_t len = strlen(string);
    err_t error;
    /* push to buffer */
    error = tcp_write(pcb, string, strlen(string), TCP_WRITE_FLAG_COPY);

    if (error) {
        return 1;
    }

    /* now send */
    error = tcp_output(pcb);
    if (error) {
        return 1;
    }
    return 0;
}

Połączenie jest realizowane za pomocą lwip, pełny kod, jak wyżej, na github w libie WEATHER.

Jak widać poza temperaturą i wilgotnością można stąd wyciągnąć dużo więcej informacji. Idealne do zbudowania pogodynki, bez stosowania zewnętrznych czujników. Jedyną wadą jest wymóg podłączenia do internetu.

No to czas na parser, na szczęście nie musimy tego ręcznie parsować, ponieważ SDK od producenta udostępnia gotowy moduł do tworzenia i parsowania formatu JSON. Struktura JSON jest zbudowana na podstawie tak zwanych węzłów. Każdy węzeł ma swoje parametry. Należy zwrócić uwagę jak bardzo zagnieżdżona ja informacja, którą chcemy wyłuskać. W tym wypadku aby wyciągnąć dane o temperaturze, najpierw trzeba uzyskać dostęp do głównego węzła, tzw root, następnie do węzła main, a na koniec można stamtąd wyciągnąć dane używając nazw pól.

Kod:

Kod: Zaznacz cały

    char *out;
    char *msg;
    cJSON *root;
    cJSON *mainTemp;
    cJSON *mainValues;
    int temp;
    int humidity;
    char *city;
   
    msg = strstr(jsonMsg, "{\"coord\":");
    if(msg == NULL)
    {
        newData.error_code = ERR_BUF;.
        return;
    }

    root = cJSON_Parse(msg);

    if (!root).
    {
        printf("Error before: [%s]\n", cJSON_GetErrorPtr());
        newData.error_code = ERR_VAL;
    }
    else.
    {
        mainValues = cJSON_GetObjectItem(root, "main");
        temp = cJSON_GetObjectItem(mainValues, "temp")->valueint;
        humidity = cJSON_GetObjectItem(mainValues, "humidity")->valueint;
        city =  cJSON_GetObjectItem(root, "name")->valuestring;

        cJSON_Delete(root);
        free(out);
    }


Akurat tutaj wyciągnięte są dane o temperaturze, wilgotności i nazwa miasta. Reszta kodu jest dostępna na GITHUB.

Zegar jest synchronizowany z serwerami NTP poprzez protokół SNTP. Na chwilę obecną jest to tylko 1 połączenie, na samym starcie systemu, następnie odczyt czasu następuje z wewnętrznego RTC. W SDK jest wbudowany moduł SNTP, od razu podłączony do RTC, wystarczy wywołać odpowiednie funkcje aby zaktualizować czas na RTC po odczycie z NTP, lub odczycie samego czasu z RTC.
Inicjalizacja NTP:

Kod: Zaznacz cały

     configTime(1, 1, "pool.ntp.org", NULL, NULL, 1);

Tak, to jest takie PROSTE. Nie trzeba bawić się z libami, z ręczną aktualizacją czasu, wystarczy wywołać maszynkę, która zrobi to za nas. Po co wyważać drzwi, które są otwarte :)
Pobranie czasu z wewnętrznego RTC:

Kod: Zaznacz cały

    time_t now;
    int formatCnt = 0;
    char time_buf[100];
    struct sensor_reading *data;
   
    time(&now);
    localtime_r(&now, &timeinfo);.
    strftime(time_buf, sizeof(time_buf), "%H:%M", &timeinfo);
    printf("TIME: %s\r\n", time_buf);


Ale ale, przecież to nie zadziała, jak nie będzie połączenia z siecią wifi, tutaj znów z pomocą przychodzi środowisko producenta! Wszystko jest gotowe, jedyne co wystarczy zrobić to zmienić w pliku conn_ap.c odpowiednie defajny.

Kod: Zaznacz cały

#define DEMO_AP_SSID      "SSID"
#define DEMO_AP_PASSWORD "pass"

Połączenie to wywołanie funkcji:

Kod: Zaznacz cały

conn_ap_init();


Kod projektu znajduje się w serwisie GITHUB. Za liba do rozmawiania z wyświetlaczem serdecznie dziękuje Antystatycznemu! Jego lib również tam się znajduje (za jego zgodą :) ), pozwoliło mi to zaoszczędzić wiele czasu. Cały projekt jest oparty o system RTOS. Do kompilacji wymagane jest SDK-RTOS. Jeżeli ktoś będzie chciał pociągnąć dalej temat to wrzucę cały gotowy projekt, wraz z SDK, który lekko zmodernizowałem, poprawiłem parę rzeczy, które (według mnie) były źle zaprojektowane. Dla osób zainteresowanych rozpoczęciem zabawy z pisaniem na ESP wykorzystając SDK będzie kilka słów wyjaśnienia jak tego używać, jak zbudować sobie toolchain, oraz jak skonfigurować środowisko do pracy.
Na chwilę obecną środowisko działa na zasadzie, klik i skrypt robi za kodera wszystko, kompiluje, przygotowuje i wgrywa kod na ESP.

W internecie jest na prawdę dużo stron oferujących podobne usługi. Myślę nad dołożeniem informacji na temat jakości powietrza, też wykorzystując ten sam sposób co powyżej.

GITHUB
https://github.com/kisielos12/ESP8266_W ... ree/master

ToDo:
  • Przygotować środowisko z czystym startowym projektem
  • W wypadku braku połączenia sieci wifi, odpalić własną sieć i poprzez WWW ustawiać połączenie z siecią
  • Może następny ekran z parametrami powietrza

Pozdrawiam
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Wróć do „Inne mikroklocki, również peryferyjne”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości