logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW

p.kaczmarek2 10 Kwi 2024 16:23 3120 17
REKLAMA
  • Wykres temperatury i wilgotności na stacji pogodowej ESP8266
    Mój poprzedni temat o tworzeniu wykresów na Arduino R4 uzyskał większy odzew niż się spodziewałem, więc teraz dla odmiany wykonuję podobny projekt ale w bardziej kompletnej formie i to na platformie ESP8266 w PlatformIO. Standardowo całość składana będzie z gotowych bibliotek, a proces opiszę w formie samouczka. Najpierw uruchomię tutaj czujnik temperatury i wilgotności DHT11, następnie pokażę jak można pobrać bieżący czas z Internetu. Potem zademonstruję jak można zbierać pomiary w pamięci w buforze kołowym, a na koniec wyświetlę je na prostej stronie WWW z wykresem, całość dostępna w obrębie naszego WiFi.

    Pierwsze kroki
    Jakiś czas temu publikowałem temat o ArduinoOTA i ESP8266 w PlatformIO, polecam się z nim zapoznać. Tutaj zakładam, że mamy uruchomione OTA i będę korzystać z tego, co wcześniej opracowałem. Dla przypomnienia - oto mój "hello world":
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    W tym temacie staramy się składać wszystko z gotowych elementów, więc użyjemy też gotowej biblioteki do czujnika DHT11. Musimy ją tylko zainstalować.
    Otwieramy zakładkę Libraries:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Wyszukujemy DHT. Biblioteka DHT wymaga też dodania Adafruit Unified Sensor Library, więc dodajemy obie biblioteki. Najpierw Unified Sensor:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Dodajemy do projektu:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Trzeba będzie wskazać, do którego naszego projektu tę bibliotekę dodajemy:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Dodane:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    W ten sposób dodajemy obie biblioteki. Czujne oko zauważy, że dodały się one też do naszego platformio.ini:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Również warto zauważyć, że na stronie biblioteki jest też przykład jej użycia:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Zintegrujmy go z naszym kodem. Pomiar wykonuję w momencie przełączenia stanu diody:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Na ten moment wyniki wysyłam tylko przez UART. Potem zrobimy stronkę internetową. Sprawdźmy najpierw, czy DHT w ogóle działa:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW

    Dodajemy stronę internetową
    Wystawienie naszych pomiarów na świat jest naprawdę bardzo proste. Do utworzenia serwera służy klasa ESP8266WebServer. Najpierw załączamy jej nagłówek:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Potem tworzymy jej instancję, argumentem jest port na którym powstanie serwer (HTTP to z reguły port 80):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Potem tworzymy funkcje obsługujące dane strony:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    W głównej pętli obsługujemy klientów:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    No i na koniec funkcja obsługująca główną stronę:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rezultat:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    To naprawdę bardzo proste. Teraz wyświetlimy temperaturę.


    Wyświetlamy temperaturę
    Aby wyświetlić temperaturę na stronie musimy dokonać dwóch rzeczy:
    - trzeba te pomiary zapisać, dla uproszczenia damy je do zmiennych globalnych
    - trzeba je potem umieścić w tekście strony, do formatowania napisu użyję mojego ulubionego sposobu, czyli bufora w stylu C i funkcji sprintf.
    Same zmienne globalne:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zapis do zmiennych globalnych:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zmodyfikowana funkcja tworząca stronę:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    W ten sposób na naszym ekranie pojawi się temperatura i wilgotność odczytana z DHT.

    Czas z sieci (NTP)
    NTP to Network Time Protocol, czyli sposób na pobranie czasu z sieci. Tutaj też mamy gotowca, skorzystamy z klasy NTPClient. Dodajemy odpowiednią bibliotekę, tak jak wcześniej:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Ta biblioteka też oczywiście ma gotowy przykład użycia:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Trzeba jeszcze uzyskać jakoś czas w postaci napisu. Jest do tego gotowa funkcja - getFormattedTime. Po integracji z naszą stroną otrzymujemy:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rezultat:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Jeśli jesteśmy ambitni to możemy samodzielnie formatować czas wedle własnego uznania. Mamy do tego funkcję strftime, która działa podobnie jak spritnf. W niej też formatujemy czas za pomocą specjalnych znaczników. Poniżej nieco rozwinięty przykład:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Lepsza organizacja
    Naszym celem jest jednak zbieranie pomiarów. Zanim go zrealizujemy, proponuję lepiej zorganizować sobie zapis pomiaru. Wprowadźmy strukturę reprezentującą pomiar. Tylko co taka struktura powinna zawierać? Zawrzemy w niej:
    - temperaturę (float)
    - wilgotność (też float)
    - czas (tutaj najlepiej użyć typu time_t, który de facto też jest liczbą, nie radzę podążać drogą zapisu czasu jako string, byłoby to niewydajne i niewygodne w dalszej obróbce)
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Potem można utworzyć globalnie instancję tej struktury:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    i nasz program będzie działać tak jak wcześniej, ważne tylko by zapisywać czas w momencie pomiaru a nie tworzyć go w momencie odczytania strony.

    Historia pomiarów - bufor kołowy - cz. 1
    Teraz trzeba wymyśleć jak przechowywać pomiary. Chciałoby się użyć zwykłej tablicy, ale co z usuwaniem starych pomiarów? Pamięć RAM nie jest nieskończona.
    Jest na to prosty sposób - przyda się nam tutaj bufor kołowy.
    Bufor kołowy to struktura danych oparta o tablicę, która pozwala na przechowywanie pewnej ilości elementów danych, a gdy bufor jest pełny, nowe dane zaczynają zastępować najstarsze. Jak sama nazwa wskazuje - indeks elementu do którego zapisujemy zatacza tutaj koło. Odpowiednia manipulacja indeksem tablicy (wraz z odpowiednim sposobem odczytu i zapisu) sprawia, że staje się ona buforem kołowym.
    Zdecydujmy się najpierw na rozmiar tablicy - jeśli chcemy mieć dzień pomiarów, gdzie pomiar jest co 10 minut, to starczy 24 * 6.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Potrzebujemy też indeks ostatnie pomiaru (ten indeks będzie "zataczał koła" po tablicy, będzie się zapętlać):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Funkcja dodająca pomiar (i zapętlająca indeks za pomocą operatora modulo):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    No i funkcja czyszcząca tablicę:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Oczywiście trzeba to jeszcze wpiąć w pobieranie pomiarów z DHT:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    oraz w ich wyświetlanie (na ten moment bez wykresu):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Nareszcie wykres
    Teraz pora utworzyć wykres. Wygenerujemy go podobnie jak w pokrewnym temacie: Rysowanie wykresów w HTML na Arduino R4 - statystyki, pomiary na mini stronie WWW.
    Zdecydowałem się na użycie do tego biblioteki chart.js
    Na stronie W3schools można znaleźć przykłady jej użycia:
    https://www.w3schools.com/js/js_graphics_chartjs.asp
    Cytując przykład z powyższej strony - wszystko sprowadza się do wpięcia naszych zebranych wartości do tablic:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Powyższy kod wygeneruje taki wykres:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Tablice cechuje to, że wszystkie elementy za wyjątkiem pierwszego są poprzedzone przecinkiem, co również musimy obsłużyć, pewnie za pomocą jakiegoś ifa.
    Tworzymy trzy tablice:
    - labele (oznaczenia, tutaj daty/czasy)
    - wartości temperatury
    - wartości wilgotności
    Przykładowe rozwiązanie:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Powyższe rozwiązanie jak na razie ignoruje bufor kołowy!
    Dodatkowo przerywam pętle wcześnie by pominąć "puste" pomiary.
    Potem zostaje umieścić tak wygenerowane tablice w reszcie kodu generującego wykres, który możemy wziąć chociażby z przykładów użycia tej biblioteki:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Oto rezultat, dla efektu podgrzałem czujnik mocną latarką:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW

    Poprawki i ulepszenia
    Kod z poprzedniego akapitu nie jest poprawny. Musimy respektować bufor kołowy oraz pomijać puste pomiary. Pomiar jest pusty, jeśli czas jest równy 0, natomiast iterację bufore zaczynamy od najstarszego wpisu, który identyfikujemy jako:
    
    (lastSample+1)%SAMPLES_COUNT
    

    operator % to modulo, reszta z dzielenia przez liczbę całkowitą. W ten sposób zaczynamy od najstarszego wpisu oraz kończymy na lastSample.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Można tu pokazać jeszcze rezultat, ale od strony wyglądu raczej nic się nie zmieni (no, chyba, że byśmy poczekali dłużej, wtedy bez poprawki na bufor kołowy wykres mógłby się psuć):
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW


    Częstotliwość pomiaru, sprzątanie
    Teraz jeszcze warto wydzielić te 1000 ms okresu próbkowania temperatury do osobnej zmiennej. Powiedzmy:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Tak naprawdę cały ten fragment kodu powinien być do przepisania, może by dało się użyć np. klasy Ticker, ale to może w kolejnej części.

    Wgląd w pełny kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zrzut ekranu ze zbierania próbek przez dłuższy czas w lekko zmodyfikowanej wersji programu:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW



    Podsumowanie
    Bardzo prosty i przyjemny projekt. W sam raz na początek z ESP. Po odpowiednim dobraniu ilości próbek (ogranicza nas pamięć RAM) i częstotliwości próbkowania można mieć ładne wykresy pokazujące temperaturę i wilgotność z ostatnich kilku dni.
    Oczywiście to tylko mały przykład i można tu wiele poprawić, np:
    - estetyka (podział wykresu na dwa, itd, jednostki)
    - kod (wspomniany Ticker by się przydał)
    - konfigurowalność (można by podpiąć WiFiManager by uniknąć potrzeby wpisywania na sztywno do kodu naszego SSID i hasła)
    - przydałoby się też sprawdzać przed pierwszym pomiarem czy czas z NTP jest już pobrany, jeśli nie, to pomijać pomiar
    Być może zajmę się tym w kolejnej części, a na razie zapraszam do komentowania. Czy realizowaliście tego typu bądź podobny projekt na ESP? A może ktoś pokusi się o rozwinięcie podanego tu przeze mnie zalążka i przeróbkę go w pełnoprawny system?

    Fajne? Ranking DIY
    Pomogłem? Kup mi kawę.
    O autorze
    p.kaczmarek2
    Moderator Smart Home
    Offline 
  • REKLAMA
  • #2 21040993
    bialy
    Poziom 16  
    Kiedyś DHT11 to był raczej wskaźnik niż czujnik temperatury (wskazywał czy rośnie czy spada ;D) .
    Jak jest teraz lepiej to się sprawdza ?
  • REKLAMA
  • #3 21041002
    p.kaczmarek2
    Moderator Smart Home
    Zasadniczo mogę się tylko zgodzić. Są też nieco lepsze czujniki, przykładowo BME280:
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Początkujący może potraktować to jako ćwiczenie i przerobić kod na inny czujnik, zasadniczo sprowadzi się to do tylko zmiany biblioteki, podłączenia elementu, no i dodania jednej zmiennej do pomiarów (jeśli chcemy uwzględniać ciśnienie)
    Pomogłem? Kup mi kawę.
  • REKLAMA
  • #4 21041078
    SylwekK
    Poziom 32  
    p.kaczmarek2 napisał:
    Są też nieco lepsze czujniki, przykładowo BME280:


    i jeszcze seria SHT3x mierzy temp&humi i jest chwalony :)
  • #5 21041318
    p.kaczmarek2
    Moderator Smart Home
    Kojarzę SHT3X, czasem go spotykam w produktach Tuya:
    https://www.elektroda.com/rtvforum/find.php?q=SHT3X+Tuya

    Ciekawe natomiast są czujniki temperatury z funkcją "alarm", wtedy można wprowadzać moduł WiFi w sen i wybudzać go alarmem:
    MCP9808 moduł czujnika I2C temperatury z alarmem - uruchomienie, protokół komunikacji
    Pomogłem? Kup mi kawę.
  • #6 21041790
    Nargo
    Poziom 22  
    SylwekK napisał:
    p.kaczmarek2 napisał:
    Są też nieco lepsze czujniki, przykładowo BME280:


    i jeszcze seria SHT3x mierzy temp&humi i jest chwalony :)


    Budżetowy zamiennik BMP280 u mnie to BME280+AHT20 w jednym module.
    Z wad jakie po prawie 6 miesiącach zauważyłem to na 4 układach różnica jednego 1'C-1.1'C między AHT a BME i potrzeba zmian w bibliotekach przy kompilacji Tasmoty.
    Z zalet to właśnie dwa czujniki temperatury w jednym module :) Po tym jak DHT22(AM2301) zaczął świrować w czujce temperatury zewnętrznej na garażu.
  • REKLAMA
  • #7 21041948
    mariomario
    Poziom 18  
    p.kaczmarek2 napisał:
    (..)
    "Zdecydujmy się najpierw na rozmiar tablicy - jeśli chcemy mieć dzień pomiarów, gdzie pomiar jest co 10 minut, to starczy 24 * 6."
    (..)


    Ja mam 'szybkie pytanie', bo bardzo zainteresował mnie ten projekt na ESP8266 -> Czy były może przeprowadzane jakieś testy, ile pomiarów wejdzie do pamięci RAM tego ESP8266, wejdzie tam powiedzmy pełne 30 ostatnich dni przy rozdzielczości odczytów wykonywanych co 15 min dla odczytów temperatury i wilgotności? Wiem, że są gotowe rozwiązania jak popularne termometry Xiaomi za kilkanaście zł, ale wolę coś z interfejsem webowym, tak jak w przypadku tego projektu na ESP..
  • #8 21041976
    p.kaczmarek2
    Moderator Smart Home
    @mariomario masz w internecie informacje ile RAM jest na ESP8266, tylko pytanie, czy aby na pewno chcesz użyć RAM? Aby po utracie zasilania zniknęło? Może lepiej użyć jakiejś zewnętrznej kości, chociażby EEPROM czy Flash, takie można z elektrośmieci nawet wylutować... albo w ostateczności pisać do flash od ESP8266, ale w sprytny sposób, oszczędzając cykle erase, zobacz sobie do mojego projektu OpenBeken do kodu flash vars który optymalizuje użycie flash:
    https://github.com/openshwprojects/OpenBK7231...ob/main/src/hal/bk7231/hal_flashVars_bk7231.c

    Dodatkowo jeśli byśmy optymalizowali pod kątem pamięci to trzeba by polepszyć strukturę danych. Ja tutorial piszę prosto i bez komplikacji, ale jeśli byśmy mieli redukować ilość pamięci to:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    można by znacznie odchudzić. Teraz to jest 12 bajtów (16 jeśli time_t jest 64 bitowy). Jaką tak naprawdę rozdzielczość i zakres temperatury chcemy?
    Jaki rozdzielczość wilgotności?
    Myślę, że spokojnie zamiast w dwóch float (8 bajtów) bym to upakował w 3 bajtach... w 2 chyba nie, ale 9 bitów na wilgotność a reszta na temperaturę...
    time_t (trzeba by sprawdzić czy tam jest 32-bitowy czy 64-bitowy) też można by zmniejszyć, chociażby licząc sekundy bądź dziesiątki sekund od 01.01.2024. Albo nawet minuty, bo czy dokładność co do sekundy jest potrzebna?

    Jak chcesz to ja mogę w kolejnej części coś podobnego opracować, ew. możemy wspólnie pomyśleć.
    Pomogłem? Kup mi kawę.
  • #9 21041977
    bialy
    Poziom 16  
    W opcji jak wyżej wychodzi około 46kb zajętości ramu na 30 dni. Można zoptymalizować zajętość bo 16bajtów na pomiar to w sumie sporo danych.
  • #10 21042000
    p.kaczmarek2
    Moderator Smart Home
    Co 15 minut odczyt daje nam 4 odczyty na godzinę, czyli 96 dziennie.
    30 dni, to 30*96 = 2880 odczytów
    Rzeczywiście, o ile ten time_t jest tam 64-bitowy to przy strukturze pomiaru o rozmiarze 16 bajtów wychodzi nam 46kB, tak jak napisał @bialy

    Natomiast myślę, że można by to odchudzić o co najmniej połowę, czyli 8 bajtów na pomiar, wtedy już jest 23kB.
    Pomogłem? Kup mi kawę.
  • #11 21042013
    mariomario
    Poziom 18  
    p.kaczmarek2 napisał:
    masz w internecie informacje ile RAM jest na ESP8266, tylko pytanie, czy aby na pewno chcesz użyć RAM? Aby po utracie zasilania zniknęło? Może lepiej użyć jakiejś zewnętrznej kości, chociażby EEPROM czy Flash, takie można z elektrośmieci nawet wylutować... albo w ostateczności pisać do flash od ESP8266, ale w sprytny sposób, oszczędzając cykle erase(..)

    Nie wiem jak innym forumowiczom, ..ale wg mnie fajny byłby taki projekt jak ten który po wejściu w interfejs webowy pokazuje aktualny (bieżący) odczyt temperatury i wilgotności wraz z aktualną godziną (odczytaną jak wyżej z serwera NTP), oraz np na tym samym dashboard'zie pod spodem wyrysowany wykres ze wszystkich zebranych danych temperatury i wilgotności w tablicy kołowej (w tym do tych np 30dni wstecz z rozdzielczością co 15min).
    Zapis danych jeśli zmieści się to w RAM to w sumie byłoby to wystarczające bo ESP i tak raczej trzeba z zasilacza zasilać ( bo żre sporo :) ), ale może da się jakoś dopisać funkcjonalność (checkbox "zapisz do Flash") która z poziomu web-interfejsu zapisywała by dane do Flash co np 24h jeden duży zapis z całego dnia z RAM -> do wbudowanego Flash (na płytce ESP8266), wtedy byłby 1 zapis na dobę i ewentualnie do stracenia dane z ostatniej doby.



    p.kaczmarek2 napisał:
    (..)Jaką tak naprawdę rozdzielczość i zakres temperatury chcemy?
    Jaki rozdzielczość wilgotności?
    (..)Myślę, że spokojnie zamiast w dwóch float (8 bajtów) bym to upakował w 3 bajtach... w 2 chyba nie, ale 9 bitów na wilgotność a reszta na temperaturę...
    time_t (trzeba by sprawdzić czy tam jest 32-bitowy czy 64-bitowy) też można by zmniejszyć, chociażby licząc sekundy bądź dziesiątki sekund od 01.01.2024. Albo nawet minuty, bo czy dokładność co do sekundy jest potrzebna?

    Temperatura z jednym miejscem po przecinku tak samo wilgotność, bo te czujniki rozdzielczość mają może i dobrą, ale dokładność (realna) to już i tak trochę loteria (kiedyś się bawiłem różnymi czujnikami i każdy co innego pokazuje..). Czas w formacie DD-MM-YYYY HH:MM też raczej dla większości byłby wystarczający.



    p.kaczmarek2 napisał:
    Jak chcesz to ja mogę w kolejnej części coś podobnego opracować, ew. możemy wspólnie pomyśleć.

    W wolnych chwilach chętnie dołączyłbym do takiego projektu
  • #12 21042317
    p.kaczmarek2
    Moderator Smart Home
    mariomario napisał:

    Nie wiem jak innym forumowiczom, ..ale wg mnie fajny byłby taki projekt jak ten który po wejściu w interfejs webowy

    Czyli trzeba by WiFiManager też podłączyć aby nie musieć na sztywno wpisywać danych sieciowych.

    mariomario napisał:

    na tym samym dashboard'zie pod spodem wyrysowany wykres ze wszystkich zebranych danych temperatury i wilgotności w tablicy kołowej (w tym do tych np 30dni wstecz z rozdzielczością co 15min).

    W pamięci tego nie oszacuję, ale trzeba by się zastanowić czy chcesz na raz przesyłać do przeglądarki wszystkie 2880 odczytów, czy też może zrobić mniej dokładny wykres "ostatnie 30 dni" oraz opcję wejścia w dokładniejsze wykresy z danego dnia.


    mariomario napisał:
    zapisywała by dane do Flash co np 24h jeden duży zapis z całego dnia z RAM -> do wbudowanego Flash (na płytce ESP8266), wtedy byłby 1 zapis na dobę i ewentualnie do stracenia dane z ostatniej doby.

    Czy jesteś pewien, że trzeba aż tak oszczędzać flash?
    Przykładowo W25Q80 wytrzymuje minimum 100 000 cykli usuwania (sektor 4KB):
    Wemos D1 "Arduino" i DHT11 - prosta stacja pogody z wykresami na stronie WWW
    Zakładając, że dziennie jest odczyt co 15 minut, czyli 96 odczytów, i że męczysz jeden sektor cały, to przekroczysz limit po 100000/96 = 1041 dniach
    Natomiast jeśli zastosujesz zalinkowane przeze mnie wcześniej rozwiązanie, które oszczędza cykle kasowania, to przy założeniu że struktura pomiaru ma 16 bajtów to polepszasz sytuację 4096/16 = 256-krotnie.
    Czyli po 266496 dniach osiągniesz minimalną ilość cykli erase... po 729 latach. To przy założeniu, że męczysz jeden sektor, ale można ich wydzielić np. 16... wtedy 729 jeszcze się 16-krotnie zwiększa.


    mariomario napisał:

    Temperatura z jednym miejscem po przecinku tak samo wilgotność, bo te czujniki rozdzielczość mają może i dobrą, ale dokładność (realna) to już i tak trochę loteria (kiedyś się bawiłem różnymi czujnikami i każdy co innego pokazuje..).

    Jeszcze musisz sprecyzować zakres temperatur bo -20°C do 40°C to co innego niż -40°C do 100°C. Chociaż i tak wiem, że z tym pakowaniem co do bitu to troszkę przesadzam, przy dzisiejszych pojemnościach flash to trochę sztuka dla sztuki
    Pomogłem? Kup mi kawę.
  • #13 21042544
    mariomario
    Poziom 18  
    p.kaczmarek2 napisał:
    mariomario napisał:

    Nie wiem jak innym forumowiczom, ..ale wg mnie fajny byłby taki projekt jak ten który po wejściu w interfejs webowy

    Czyli trzeba by WiFiManager też podłączyć aby nie musieć na sztywno wpisywać danych sieciowych.

    To by zdecydowanie poprawilo doswiadczenia z uzytkowania takiego termometru :) (pytanie tylko ile pamieci potem zostanie na dane z odczytow?)


    p.kaczmarek2 napisał:
    mariomario napisał:

    na tym samym dashboard'zie pod spodem wyrysowany wykres ze wszystkich zebranych danych temperatury i wilgotności w tablicy kołowej (w tym do tych np 30dni wstecz z rozdzielczością co 15min).

    W pamięci tego nie oszacuję, ale trzeba by się zastanowić czy chcesz na raz przesyłać do przeglądarki wszystkie 2880 odczytów, czy też może zrobić mniej dokładny wykres "ostatnie 30 dni" oraz opcję wejścia w dokładniejsze wykresy z danego dnia.

    Nawet bez tych powyzej omawianych optymalizacji mamy do 45KiB danych do przeslania z ESP do przegladarki. Raczej nie sa to duze ilosci danych. Wykres taki wygeneruje sie na smartfonie czy starszym PC bez problemu.


    p.kaczmarek2 napisał:
    mariomario napisał:
    zapisywała by dane do Flash co np 24h jeden duży zapis z całego dnia z RAM -> do wbudowanego Flash (na płytce ESP8266), wtedy byłby 1 zapis na dobę i ewentualnie do stracenia dane z ostatniej doby.

    Czy jesteś pewien, że trzeba aż tak oszczędzać flash?(..)
    Moznaby dac wtedy zapis danych do Flash co godzine, do stracenia wtedy jest jedynie ten godzinny odcinek czyli raptem 4 pomiary


    p.kaczmarek2 napisał:
    mariomario napisał:

    Temperatura z jednym miejscem po przecinku tak samo wilgotność, bo te czujniki rozdzielczość mają może i dobrą, ale dokładność (realna) to już i tak trochę loteria (kiedyś się bawiłem różnymi czujnikami i każdy co innego pokazuje..).

    Jeszcze musisz sprecyzować zakres temperatur bo -20°C do 40°C to co innego niż -40°C do 100°C. Chociaż i tak wiem, że z tym pakowaniem co do bitu to troszkę przesadzam, przy dzisiejszych pojemnościach flash to trochę sztuka dla sztuki

    Przy dzisiejszych pojemnosciach pamieci RAM i Flash raczej zrealizowac to tak jak wygodniej bez spiny o pojedyncze bity danych. Zakres temperatur -40C do 100C z wyswietlaniem do 1 miejsca po przecinku, mysle ze zadowoli wiekszosc potencjalnych uzytkownikow
  • #14 21042575
    p.kaczmarek2
    Moderator Smart Home
    mariomario napisał:

    Nawet bez tych powyzej omawianych optymalizacji mamy do 45KiB danych do przeslania z ESP do przegladarki. Raczej nie sa to duze ilosci danych.

    Nie grzebałem dużo w zaawansowanym Javascripcie i nie jestem na topie z tego języka, ale ja raczej myślałem że do przeglądarki pomiary już idą jako tekst, a nie jako dane binarne. Czyli przykładowo taka Javascriptowa tablica:
    Kod: Javascript
    Zaloguj się, aby zobaczyć kod

    Tutaj mamy 4 bajty (bo to ASCII) na pomiar, cztery, bo doliczam przecinek. Ale np z timestampami znacznie gorzej jest, w tym momencie jak piszę unix epoch time to 1712916348, a to już jest 10 znaków...
    No ale fakt, po podliczeniu ile bajtów w ASCII tego będzie i tak wychodzi podobny wynik jak te 16 bajtów binarnych.

    Dodatkowo można pomyśleć nie o stronie statycznej, tylko o stronie napisanej w Javascript komunikującej się z ESP poprzez API do pomiarów. To znaczy, najpierw jak mamy zbiorczy np. na 7 dni, to przykładowo odpytujemy ESP o średnie godzinne (co ESP sam policzy). Przy wyświetlaniu pomiarów z 7 dni nie potrzebujesz raczej rozdzielczości co do 15 minut.

    Chociaż chyba widziałem że w Javascript też już pliki binarne parsują. Bot na pewno "wie":
    @ElektrodaBot pokaż przykład pobrania z internetu poprzez GET i parsowania pliku binarnego w języku Javascript. Wczytaj z niego typ 16-bitowy integer oraz 32-bitowy integer.
    Pomogłem? Kup mi kawę.
  • #15 21042577
    ElektrodaBot
    AI od OpenAI ChatGPT4
    p.kaczmarek2 napisał:
    pokaż przykład pobrania z internetu poprzez GET i parsowania pliku binarnego w języku Javascript. Wczytaj z niego typ 16-bitowy integer oraz 32-bitowy integer.
    Witaj!

    Chętnie pokażę Ci, jak można pobrać plik binarny z internetu korzystając z metody GET i sparsować go w języku JavaScript, aby wydobyć z niego wartości typu 16-bitowego integer oraz 32-bitowego integer. Przygotowałem dla Ciebie krok po kroku proces realizacji tego zadania. Spróbujmy to zrobić razem!

    ### Krok 1: Pobieranie pliku binarnego

    Do pobrania pliku binarnego z internetu użyjemy Fetch API, które jest wbudowane w większości nowoczesnych przeglądarek internetowych. Poniższy kod pokazuje, jak to zrobić:

    Kod: Javascript
    Zaloguj się, aby zobaczyć kod


    W tym kodzie funkcja `pobierzPlikBinarny` przyjmuje jako argument URL pliku, który chcesz pobrać. Wykorzystuje ona Fetch API do wykonania żądania HTTP GET. Jeśli żądanie zakończy się sukcesem, odpowiedź jest przetwarzana jako `ArrayBuffer`, który jest typem używanym do przechowywania danych binarnych w JavaScript.

    ### Krok 2: Parsowanie pliku binarnego

    Po pobraniu danych binarnych musimy je odpowiednio sparsować, aby wydobyć z nich interesujące nas wartości. Do tego celu skorzystamy z obiektu DataView, który umożliwia interpretację danych binarnych przechowywanych w `ArrayBuffer`.

    Poniżej znajdziesz przykładową funkcję, która pokazuje, jak przetworzyć `ArrayBuffer` i odczytać z niego 16-bitową oraz 32-bitową liczbę całkowitą:

    Kod: Javascript
    Zaloguj się, aby zobaczyć kod


    W tym kodzie `dataView.getInt16(0, true)` odczytuje 16-bitową liczbę całkowitą zaczynając od pozycji 0 w buforze, używając kolejności bajtów Little Endian. Analogicznie `dataView.getInt32(2, true)` odczytuje 32-bitową liczbę całkowitą zaczynając od pozycji 2, ponieważ 16-bitowa liczba zajmuje 2 bajty.

    ### Krok 3: Łączenie wszystkiego

    Teraz, kiedy mamy funkcje do pobierania i parsowania danych, możemy je użyć razem, aby pobrać plik binarny z internetu i sparsować go w poszukiwaniu wartości:

    Kod: Javascript
    Zaloguj się, aby zobaczyć kod


    Upewnij się, że zmienisz `http://example.com/plik.bin` na URL wskazujący na faktyczne miejsce pliku binarnego, który chcesz pobrać i sparsować.

    Mam nadzieję, że te informacje są dla Ciebie pomocne. Jeśli masz jakiekolwiek pytania lub potrzebujesz dalszej asysty, śmiało pytaj. Powodzenia z Twoim projektem!
    Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
  • #16 21042590
    p.kaczmarek2
    Moderator Smart Home
    @mariomario chyba masz rację z tym, że nie ma sensu upakowywać bit co do bitu. Trochę z tym przesadzam z przyzwyczajenia, bo robiłem/robię systemy gdzie walczę o każdy bit itd.

    Jakby oferować binarne API pomiarów to można by po prostu kopiować z pamięci do odpowiedzi GET odczyty bez zamiany ich na tekst ASCII. W ten sposób uniknęlibyśmy wielu sprintf i podobnych operacji po stronie ESP.

    Ale i tak, z ciekawości...

    @ElektrodaBot Napisz parsowanie w Javascript obiektu DataView gdzie pierwsze 10 bitów to wartość A, następne 12 bitów to wartość B, a następne 18 bitów to C. Zaproponuj sposoby jak mogę to przetwarzać i rozbić wartości na osobne zmienne
    Pomogłem? Kup mi kawę.
  • #17 21042595
    ElektrodaBot
    AI od OpenAI ChatGPT4
    p.kaczmarek2 napisał:
    Napisz parsowanie w Javascript obiektu DataView gdzie pierwsze 10 bitów to wartość A, następne 12 bitów to wartość B, a następne 18 bitów to C. Zaproponuj sposoby jak mogę to przetwarzać i rozbić wartości na osobne zmienne
    Witaj ponownie!

    Parsowanie skomplikowanego formatu danych z obiektu `DataView` wymaga szczególnego podejścia, ponieważ będziemy pracować na poziomie bitowym. W twoim przypadku mamy do czynienia z łącznie 40 bitami danych, gdzie pierwsze 10 bitów to wartość A, następne 12 bitów to wartość B, a ostatnie 18 bitów to wartość C.

    Najpierw zobaczmy, jak można podzielić te dane na osobne zmienne:

    ### Krok 1: Przygotowanie do pracy z bitami

    JavaScript nie posiada bezpośredniego wsparcia do operacji na pojedynczych bitach na poziomie `DataView`. Z tego powodu będziemy musieli najpierw wczytać dane w większych blokach (np. 16-bitowych lub 32-bitowych), a następnie użyć operacji bitowych do ekstrakcji interesujących nas wartości.

    ### Krok 2: Odczyt danych i ekstrakcja wartości

    Zakładając, że nasze 40 bitów danych jest upakowane w pierwszych 5 bajtach bufora, możemy to zrobić w następujący sposób:

    Kod: Javascript
    Zaloguj się, aby zobaczyć kod


    ### Krok 3: Wyjaśnienie działania

    1. Odczytujemy 32-bitowe dane – to pozwala nam na łatwy dostęp do pierwszych 32 bitów (4 bajty). `getUint32` czyta wartości jako liczby bez znaku, co jest ważne przy pracach na bitach.
    2. Odczytujemy piąty bajt – pozwala na dostęp do ostatnich 8 bitów danych.
    3. Ekstrakcja wartości A – używamy operacji `&` (AND) z maską `0x3FF` (która w systemie dwójkowym składa się z 10 zapalonych bitów), aby zachować tylko 10 najmniej znaczących bitów.
    4. Ekstrakcja wartości B – tutaj najpierw przesuwamy bity w prawo o 10 miejsc, aby pozbyć się bitów odpowiadających A, a następnie ponownie stosujemy operację `&`, tym razem z maską dla 12 bitów (`0xFFF`).
    5. Ekstrakcja wartości C – wymaga nieco więcej pracy. Przesuwamy dane z pierwszych 32 bitów o 22 miejsca w prawo, aby pozostawić tylko najbardziej znaczące bity, które nie należą do wartości A i B. Wartość z piątego bajtu przesuwamy w lewo o 6 miejsc i dokonujemy operacji OR (`|`), aby dodać 2 brakujące bity, uzyskując łącznie 18 bitów danych na wartość C.

    ### Podsumowanie

    Oto sposób, w jaki możemy podzielić dane binarne na konkretne, mniejsze wartości bitowe w JavaScript. Kluczem jest użycie operacji bitowych, takich jak AND, OR oraz przesunięcia bitowe w lewo i w prawo, do manipulacji i ekstrakcji danych z większych bloków binarnych.

    Jeśli masz jakiekolwiek pytania lub potrzebujesz dalszych wyjaśnień, śmiało daj znać. Chętnie pomogę!
    Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
  • #18 21042604
    p.kaczmarek2
    Moderator Smart Home
    Widzę, że zasadniczo w JS wygląda to tak jakbym w C robił.
    Pomogłem? Kup mi kawę.
REKLAMA