Quantcast
Channel: Majsterkowo - zrób to sam!
Viewing all articles
Browse latest Browse all 1332

Odczyt bezprzewodowej sondy temperatury i wilgotności

$
0
0
Moja stacja

Krótkie wprowadzenie

Artykułem tym chciałbym się z Wami podzielić tym jak udało mi się odczytać przy pomocy Arduino UNO R3 wartości temperatury i wilgotności wysyłane przez bezprzewodową sondę. Od jakiegoś czasu zajmuję się monitorowaniem warunków (temperatura, wilgotność) w mieszkaniu i na zewnątrz. Celem moim jest zbudowanie jeszcze przed tą zimą inteligentnego systemu sterowania ogrzewaniem i wentylacją w mieszkaniu. Jestem w posiadaniu stacji pogodowej (mniej więcej takiej) z bezprzewodową sondą temperatury i wilgotności. Postanowiłem nauczyć się odczytywać jej wskazania i przesyłać je do komputera. [caption id="attachment_5611" align="aligncenter" width="396"]Stacja pogodowa Dokładnie taką stację posiadam[/caption]

Zapytanie do producenta

Pierwszą rzeczą jaką postanowiłem zrobić to zapytać producenta o protokół jakim przesyłane są te wartości. Początek był obiecujący. Miły pan wprawdzie nie wiedział nic więcej ponad to, że sonda nadaje na częstotliwości 433 MHz, ale obiecał się dowiedzieć. Skończyło się jednak na mailowej odpowiedzi o treści "Tak, pytałem u źródła, niestety, nie da się tak zrobić, aby czujka sczytywała do innego urządzenia niż nasza stacja bazowa." Oczywiście nie uwierzyłem :)

Pytanie na majsterkowo.pl

Postanowiłem poszukać pomocy gdzie indziej, a mianowicie na portalu http://majsterkowo.pl. Zadałem pytanie w wątku http://majsterkowo.pl/forum/arduino-i-bezprzewodowy-czujnik-temperatury-i-wilgotnosci-t816.html licząc na pomoc społeczności. Jednak jedyna odpowiedź jaką dostałem brzmiała "W opisie jest napisane z jaką stacją to współpracuje. Do pracy z Arduino tego raczej nie zmusisz, producent na pewno zadbał o odpowiednie kodowanie sygnału." Nie zabrzmiało to zbyt zachęcająco, ale oczywiście tym bardziej w to nie uwierzyłem ;)

Kupno odbiornika RF 433

W międzyczasie zakupiłem między innymi nadajnik i odbiornik RF 433 MHz. [caption id="attachment_5618" align="aligncenter" width="396"]Kilka zakupionych elementów Odbiornik i nadajnik, wyświetlacz LCD oraz DHT22[/caption]
To te dwa najmniejsze zielone elementy.

Analiza sygnału

Kupno analizatora

Buszując gdzieś po sieci natrafiłem na pojęcie "analizatora stanów logicznych". Pomyślałem, że właśnie tego potrzebuję. W sieci znalazłem bardzo bogatą ofertę tego typu urządzeń od takich za wiele tysięcy złotych (np http://www.conrad.pl/websale7/?Ctx={ver%2f7%2fver}{st%2f3ec%2fst}{cmd%2f0%2fcmd}{m%2fwebsale%2fm}{s%2fconrad%2fs}{l%2f01-aa%2fl}{p1%2fd2f6e56f669660582c6750d86eaf57b8%2fp1}{md5%2f5ffac58ff15c6a24fcf953c797b8c9b3%2fmd5}&act=product&prod_index=123271&cat_index=SHOP_AREA_17630_1114018&otp1=tablink2) do bardzo prostych i tanich podłączanych bezpośrednio do portu LPT (drukarkowego) w komputerze. Ostatecznie zdecydowałem się na takie urządzenie: [caption id="attachment_5619" align="aligncenter" width="396"]Analizator stanów logicznych Analizator stanów logicznych[/caption] Analizator ten ma 8 kanałów, częstotliwość odczytu do 24 MHz i ... kosztuje tylko 57 PLN :) Znalazłem go na Allegro. Do tego analizatora należy pobrać oprogramowanie ze strony http://www.saleae.com/.

Odczyt sygnałów

Aby odczytać nadawane przez sondę sygnały postanowiłem podłączyć analizator bezpośrednio do nadajnika RF wewnątrz sondy. Po otwarciu sondy wnętrze przedstawia się następująco [caption id="attachment_5620" align="aligncenter" width="396"]Wnętrze sondy Wnętrze sondy[/caption]
Żółtymi przewodami podpięty jest czujnik temperatury, dwoma czarnymi czujnik wilgotności, czerwonym i czarnym baterie, a trzema czerwonymi nadajnik RF. To właśnie tam podpiąłem się analizatorem stanów logicznych.
Do podpięcia się bardzo brakowało mi krokodylków lub specjalnych sond. W przyszłości na pewno sobie takie kupię.
Następnie rozpocząłem pomiar. Ustawiłem częstotliwość próbkowania na 1 MHz, wyłączyłem wszystkie kanały poza pierwszym. Włączyłem dla niego opcję "Require rising edge transition", która powoduje, że pomiar danych rozpocznie się dopiero kiedy sygnał na wejściu zmieni się z niskiego na wysoki i nacisnąłem "Start". Po jakimś czasie (sonda nadaje co ok 50-56 sekund - więcej o tym później) na ekranie ujrzałem taki obrazek: [caption id="attachment_5621" align="aligncenter" width="396"]Widok na wszystkie dane Widok na wszystkie dane[/caption] Widać na nim, że odczytane zostały dane, że nadawanie trwało trochę ponad 0,8s. Po powiększeniu początku danych zobaczyłem: [caption id="attachment_5622" align="aligncenter" width="396"]Powiększony początek pomiaru Powiększony początek pomiaru[/caption] Widać, że sonda nadaje krótki "piki" (stan wysoki), a pomiędzy nimi przerwy. Stan wysoki zawsze trwa ok 560μs, a przerwy pomiędzy nimi 8640, 3800 i 1900μs. Przerwa 8640 μs występuje na samym początku transmisji, na samym końcu oraz tylko kilka razy w środku. Przerwy 3800 i 1900 o wiele częściej i są pomieszane. W tym momencie wydawało mi się, że 8640 to jakiś sygnał synchronizująco-rozdzielający, a te dwie pozostałe przerwy oznaczają bity o wartościach 0 i 1. Czas to sprawdzić.

Analiza w arkuszu kalkulacyjnym

Analizę danych postanowiłem przeprowadzić w LibreOffice Calc (dla niewtajemniczonych to taki darmowy odpowiednik Excela ;) ). Po wybraniu w oprogramowaniu analizatora opcji "Options/Export Data" (Ctrl+E) pojawia się okienko [caption id="attachment_5623" align="aligncenter" width="212"]saleae - okienko eksportu saleae - okienko eksportu[/caption] Po wybraniu opcji jak na obrazku na dysku utworzony został plik z następującymi danymi - poniżej początkowy fragment: [crayon-51aeaf64a2250/] W pierwszej kolumnie jest czas mierzony w sekundach, w drugiej kolumnie jest wartość sygnału jaka się pojawiła na wejściu w tym czasie. Zaimportowałem te dane do arkusza i dodałem dwie kolejne kolumny: czas i stan. W kolumnie czas wpisałem wszędzie formułę (dla komórki C3) =1000*(A4-A3). Dzięki temu otrzymałem czas w milisekundach trwania danego stanu. Widać ponownie, że stan wysoki zawsze trwa ok 560μs, a stan niski 8640, 3800 i 1900μs. W czwartej kolumnie wpisuję regułę, które dla przerwy równej 3800μs wylicza, że to 1, a dla 1900μs wylicza, że to 0. Dla 8640μs wypisuje wartość "dystans". Oto przykładowe dane:
Time[s]SCIOczasanaliza
00
11,3582410,56
11,358808,64dystans
11,3674410,56
11,36803,81
11,371810,56
11,3723601,880
11,3742410,56
11,374801,920
11,3767210,56
11,3772803,841
Na tym poziomie analizy zauważyłem, że podczas pojedynczej transmisji 6 razy przesyłanych jest 37 bitów. Za każdym razem takich samych. Serie 37 bitów rozdzielane są "dystansami". Aby przeanalizować wartości tych bitów wykonałem następujące czynności. Najpierw wykorzystując autofiltr przeniosłem do drugiego arkusza taką paczkę 37 bitów do pierwszej kolumny. W kolejnych kolumnach zapisałem następujące formuły, które miały następujące znaczenie.
Kol.formułaznaczenie
B=1-A2odwrotny bit (nie wiem czy długa przerwa to bit czy krótka)
C=A2+2*(A3+2*(A4+2*(A5+2*(A6+2*(A7+2*(A8+2*A9))))))wartość bajtu zaczynającego się od tego bitu przy założeniu, że: długa przerwa to 1, a krótka to 0, najpierw jest najmłodszy bit a potem coraz starsze.
D=B2+2*(B3+2*(B4+2*(B5+2*(B6+2*(B7+2*(B8+2*B9))))))wartość bajtu zaczynającego się od tego bitu przy założeniu, że: długa przerwa to 0, a krótka to 1, najpierw jest najmłodszy bit a potem coraz starsze.
E=A9+2*(A8+2*(A7+2*(A6+2*(A5+2*(A4+2*(A3+2*A2))))))wartość bajtu zaczynającego się od tego bitu przy założeniu, że: długa przerwa to 1, a krótka to 0, najpierw jest najstarszy bit a potem coraz młodsze.
F=B9+2*(B8+2*(B7+2*(B6+2*(B5+2*(B4+2*(B3+2*B2))))))wartość bajtu zaczynającego się od tego bitu przy założeniu, że: długa przerwa to 0, a krótka to 1, najpierw jest najstarszy bit a potem coraz młodsze.
Dla następujących danych:
  • kanału nr 3
  • temperatury 24,1 stopnia Celsjusza
  • wilgotności 43%
tabela przedstawiała się następująco:
ABCDEF
10137118145110
016818734221
011629369186
1020946139116
0110415122233
015220344211
012622988167
1014111417778
017018598157
103522019659
1017238136119
01824716239
01425132223
0113012565190
1019362131124
01224317248
012401515240
0112013530225
016019560195
0130225120135
1014311224114
107118422629
103522019659
10145110137118
017218318237
011649137218
018217374181
1016986149106
012124343212
0110614986169
10
01
10
01
10
10
01
Na żółto zaznaczyłem te bajty gdzie widać pewne interesujące dane. W ostatniej żółtej komórce widać wilgotność, a w przedostatniej temperaturę pomnożoną przez 10. Pierwsze dwie zaznaczyłem na żółto bo to po prostu wcześniejsze dwa bajty. Że to ta kolumna to utwierdziłem się po kilku kolejnych pomiarach dla różnych wartości temperatury i wilgotności. Powstały oczywiście pytania:
  • czy na wilgotność potrzeba aż 8 bitów?  skoro jej wartości są od 0-99 to wystarczy 7.
  • na ilu bitach i w jaki sposób kodowana jest temperatura, ten jeden bajt wystarczy na temperatury od 0.0 do 25.5 stopni Celsjusza, a ma wystarczyć na jakieś -50.0 do 70.0 czyli 1200 wartości więc co najmniej 11 (w praktycznie 12) bitów
Po kolejnych pomiarach i próbach, których nie będę tu szczegółowo opisywał (było ich ok 10) doszedłem do następujących wniosków:
licznikbitywartościkomentarz
119jakieś 4 bity
20
30
41
51219losowe id
61
70
81
91
100
111
121
1300jakieś 2 bity
140
1501kanał (od 0)
161
170332temperatura
180
190
201
210
221
230
240
251
261
270
280
29025wilgotność
300
310
321
331
340
350
361
3700jakiś bit
Oto znaczenie kolejnych sekcji:
  1. jakieś 4 bity - te bity ani razu nie zmieniły swojej wartości
  2. losowe id - wg dokumentacji po każdej zmianie baterii konieczne jest ponowne synchronizacja stacji bazowej z sondą ponieważ sonda zaczyna wysyłać nowe, losowe id - to prawdopodobnie te bity
  3. jakieś 2 bity - nigdy się nie zmieniły
  4. kanał (od 0) - w sondzie można wybrać kanał, jego wartość wysyłana jest właśnie na tych dwóch bitach
  5. temperatura - zakładam, że wysyłana jest na tych 12 bitach jako liczba całkowita będąca wartością temperatury pomnożoną przez 10. Podejrzewam, że najstarszy bit to bit znaku, ale nie robiłem jeszcze testów dla temperatur ujemnych
  6. wilgotność - jest przechowywana jako liczba całkowita na tych bitach. Możliwe, że nie na 8 od 29 bitu, a tylko na 7 od 30 bitu, a bit 29 jest do czegoś innego.
  7. jakiś bit - jego wartość nigdy się nie zmieniła.
Na tym etapie postanowiłem przerwać analizę danych i zająć się budową odbiornika, który będzie bezprzewodowo je odczytywał. W przyszłości podłączę go mojego systemu monitoringu temperatury zacznę prowadzić dalsze badania.

Wysłanie samemu danych do odbiornika

Aby przetestować poprawność rozpracowanych danych postanowiłem zmontować układ do nadawania i przeprowadzić próbę nadania temperatury i wilgotności do stacji bazowej czyli udawanie sondy. Napisałem następujący programik:
[crayon-51aeaf64a22b4/]
Wszystko zadziałało właściwie od razu. Jedyny problem jaki napotkałem to odstępy pomiędzy nadawaniem kolejnych pomiarów. Okazało się, że odstęp ten jest różny na różnych kanałach i tak:
  • na kanale 1 wynosi on 50s
  • na kanale 2 wynosi on 53s
  • na kanale 3 wynosi on 56s
Dokładnie co taki okres czasu stacja bazowa spodziewa się kolejnego nadawania i oczekuje na niego przez krótki okres czasu. Prawdopodobnie aby oszczędzać baterię.

Odczyt danych

Odczyt danych okazał się najtrudniejszą częścią, a to za sprawą dużej ilości błędów. Po pierwsze kiedy sonda nie nadaje to odbiornik i tak wychwytuje "coś" z powietrza i ciągle na jego wyjściu stan się zmienia. Kiedy sonda zaczyna nadawać to odbiornik chwilę potrzebuje żeby się "dostroić" do mocy sygnału i pierwsze bity są uszkodzone często. Poza tym okazało się, że czułość odbiornika jest niewielka i już przy odległości rzędu metra liczba niedokładnych odczytów mocno rośnie.

Pierwsze podejście

Pierwsza wersja programu do odczytu wyglądała następująco:
[crayon-51aeaf64a2307/]
Nie działała ona najlepiej, o tym co poprawiłem w dalszej części artykułu.

Problemy z zasięgiem

Jak już pisałem kiedy żaden nadajnik nie nadawał odbiornik "łapał coś" i stan na wyjściu co chwila się zmieniał. Założyłem jednak, że kiedy nadajnik zacznie nadawać to odbiornik zacznie reagować prawidłowo. Pierwsza wersja programu została napisana tak, że program czeka na stan wysoki o odpowiedniej długości, a następnie odczytuje dane spodziewając się prawidłowych czasów zarówno stanów wysokich jak i niskich. Po pierwszym błędzie program przerywał odczyt i próbował zanalizować odczytane dane, a mianowicie jeżeli udało się odczytać choć jedną serię danych to następowało porównywanie odczytanych serii. Pierwsze próby robiłem nadając mój testowy sygnał z nadajnika, który zakupiłem razem z odbiornikiem. Sygnał nadawany był z niewielkiej odległości. Zauważyłem, że dane nie odczytują się do końca poprawnie. Często zamiast sześciu serii danych odczytywane było pięć serii. Przyczyną okazało się to, że kiedy nadajnik zaczynał nadawać to odbiornik tak jakby potrzebował chwili aby się do niego dostroić. Dużo gorzej było kiedy próbowałem odczytać sygnał z oryginalnej sondy, tu już przy około metrowej odległości zaczynały się spore problemy. Często nie udawało się odczytać w ogóle danych lub najwyżej jedną, dwie serie. Przyczyną jak się okazało było pojawianie się na wyjściu stanów wysokich mimo tego, że sonda nadawała stan niski. Próbowałem poprawić czułość sondy przylutowując antenkę w postaci kawałka drutu o długości około 15 cm, ale niewiele to pomogło. Wywiązała się nawet dyskusja na forum majsterkowo.pl. Jak tylko znajdę moment to popracuję nad tą antenką. Kolejnym sposobem było ignorowanie krótkich stanów wysokich, to poprawiło nieco jakość odbioru. Oto przykład wadliwie odczytanych danych: [caption id="attachment_5624" align="aligncenter" width="396"]saleae - zakłócenia w trakcie transmisji saleae - zakłócenia w trakcie transmisji[/caption] W tym momencie postanowiłem zrobić co następuje:
  • jeszcze bardziej uniewrażliwić oprogramowanie na sporadyczne błędy
  • nie przerywać pomiaru po pierwszym poważnym błędzie tylko czekać na kolejną serię danych
  • być może pewną inteligencję wprowadzić

Poprawianie jakości odczytu

Omówienie sytuacji aktualnej

Tak wygląda log z pierwszej wersji programu, który za chwilę omówię [crayon-51aeaf64a2361/] W pierwszej linii znajdują się informacje o odczycie, czyli:
  • kanał na którym nastąpił odczyt
  • odczytana temperatura
  • odczytana wilgotność
  • liczba pełnych udanych odczytów wszystkich bitów - jak pisałem wcześniej sonda nadaje 6 razy ten sam zestaw bitów w trakcie pojedynczej transmisji
Kolejne trzy wiersze zawierają informację o odczytach kolejnych bitów i tak:
  • pierwszy wiersz (lb:) zawiera informację o tym ile razy bit został prawidłowo odczytany
  • kolejny wiersz (sb:) zawiera informację o tym jakie informacje zostały odczytane - kiedy program odczytuje zero to zmniejsza tę wartość o 1, a kiedy odczytuje 1 zwiększa ją - w idealnym przypadku ta wartość jest równa tej z pierwszego wiersza lub ujemnej wartości z pierwszego wiersza
  • ostatni wiersz (b:) zawiera interpretację odczytu czyli 0, 1 lub ? jeśli interpretacja jest niejednoznaczna
W tym przypadku widać, że bity od 0 do 24 zostały odczytane 4 razy, a pozostałe bity 3 razy. Każdy bit za każdym razem został odczytany tak samo. Gdyby tak nie było i np bit 0 nie został 4 razy odczytany jako 1 tylko np raz jako 0 to wartość (sb:) nie wynosiłaby 4 tylko 2, a gdyby dwa razy jak 0 a dwa razy jako 1 to ta wartość wynosiłaby 0 i nie dałoby się powiedzieć jaką właściwie ten bit ma wartość. Kolejnych 10 wierszy, tych zaczynających się od "pre",  zawiera informacje o czasach 10 pomiarów niskich i wysokich stanów zanim rozpoczął się właściwy pomiar. Liczby w nawiasach oznaczają:
  • moment w którym zmiana została zmierzona, jest to technicznie millis() % 65536 - obcinam wartość millis() tylko do 16 bitów bo ze względu na małą pamięć nie mam gdzie przechowywać danych, ledwo się mieszczą
  • czas w jakim stan był niski
  • czas w jakim stan był wysoki
W tym przypadku wyraźnie widać, że te odczyty nie są szumem, a stanowią poprawne wartości odczytywanych bitów. Nie zostały jednak zaliczone do pomiaru. Stało się tak prawdopodobnie dlatego, że w momencie jak sonda  zaczęła nadawać to odbiornik potrzebował chwili aby się dostosować do nadawanego sygnału. Na obrazie poniżej widać jak wygląda odczyt początku transmisji. Stan wysoki na lewo od zielonego znacznika "1" to pierwszy stan wysoki nadany przez sondę. Między znacznikami "1" a "2" sonda nadawała stan niski, jednak odbiornik wychwycił kilka stanów wysokich. Są to zakłócenia z którymi mój algorytm sobie nie poradził i uznał całość za szumy. [caption id="attachment_5625" align="aligncenter" width="396"]saleae - widok na początek transmisji saleae - widok na początek transmisji[/caption] Widać też zakłócenia w dalszej części i dopiero potem (od mniej więcej 87ms) czyste dane. Kolejnych 37 wierszy zawiera informacje o odczytach kolejnych bitów w kolejnych 6 transmisjach. Liczby w nawiasach mają takie samo znaczenie jak w wierszach "pre". Tu widać, że podczas odczytu 4 serii bitów nagle nastąpiła przerwa podczas odczytu bitu nr 25. Czas stanu wysokiego jest ok, jednak czas stanu niskiego jest zbyt krótki, wynosi tylko 1292μs. Oto co się stało: [caption id="attachment_5626" align="aligncenter" width="396"]saleae - zakłócenia w trakcie transmisji saleae - zakłócenia w trakcie transmisji[/caption] Pomiędzy znacznikami "1" i "2" powinien być stan niski, jednak widać, że odbiornik wychwycił jakieś zakłócenia jedno o długości 103μs, a drugie o długości 1028μs. Aktualny algorytm zignorował to pierwsze, jednak tego drugiego już nie i uznał odczyt za błędny i przerwał działanie. Oto co postanowiłem zrobić aby algorytm lepiej działał:
  • nie przerywać całkowicie działania po pierwszym błędnym odczycie, ale czekać na kolejną transmisję (czyli przerwę o czasie 8640μs) i zaprzestać czekania dopiero kiedy zbyt długo ona nie nastąpiła.
  • jeszcze bardziej uniewrażliwić algorytm na takie pojedyncze zakłócenia.

Nie przerywanie działania

Pisząc program, który po pierwszym błędzie nie przerywa działania tylko czeka na kolejną porcję danych praktycznie główną pętlę napisałem od nowa. Oto ten program. [crayon-51aeaf64a23b8/]

Uniewrażliwienie na zakłócenia

Za to jeszcze się nie zabrałem, na poważnie, ale już całkiem nieźle to działa. Analizując program widać co już zrobiłem

Zestaw użytych elementów

Do przeprowadzenia tej pracu użyłem:
  • Arduino UNO R3 - zakupione na w sklepie internetowym nettigo.pl w zestawie startowym - oprócz samego arduino z zestawu użyłem
    • kabelki
    • płytkę stykową
  • analizator stanów logicznych saleae - jest to podróbka, ale działa

Co dalej

Następne kroki jakie zamierzam zrobić w tym temacie:
  • podpięcie układu do moje stacji monitorowania warunków w mieszkaniu i na zewnątrz. Stacja już całkiem nieźle działa, ale nie jest jeszcze gotowa na artykuł. Jeżeli interesuje Was ten temat już teraz to zapraszam na mój blog
  • Poprawienie jakości filtrowania zakłóceń
  • Zakup na nettigo innego odbiornika - może będzie bardziej czuły
  • Przerobienie programu aby na przerwaniach chodził i oszczędzał energię

Podsumowanie

Mam nadzieję, że temat Wam się spodobał i nie był zbyt długi i nużący. Jest to mój pierwszy artykuł więc będę wdzięczny za wszelkie konstruktywne uwagi na jego temat. Jeżeli ktoś miałby ochotę wspólnie ze mną rozwijać ten temat to zapraszam do współpracy. Cel na jesień/zimę to automatyka do sterowania ogrzewaniem w domu oparta między innymi o technologię z-wave. Czytaj dalej...

Viewing all articles
Browse latest Browse all 1332

Trending Articles


TRX Antek AVT - 2310 ver 2,0


Автовишка HAULOTTE HA 16 SPX


POTANIACZ


Zrób Sam - rocznik 1985 [PDF] [PL]


Maxgear opinie


BMW E61 2.5d błąd 43E2 - klapa gasząca a DPF


Eveline ➤ Matowe pomadki Velvet Matt Lipstick 500, 506, 5007


Auta / Cars (2006) PLDUB.BRRip.480p.XviD.AC3-LTN / DUBBING PL


Peugeot 508 problem z elektroniką


AŚ Jelenia Góra



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>