
Zwykle przy przeglądaniu nagromadzonych skarbów w postaci części el. przychodzą mi do głowy pomysły ich wykorzystania. Tak było i tym razem. Z jakiegoś starego projektu została mi para nadajnik/odbiornik 434MHz OOK, attiny13 i kilka DS18B20, pomyślałem że na tej bazie zmajstruję prosty bezprzewodowy termometr: nadajnik z jednym czujnikiem, który będzie można wetknąć w jakieś zacienione miejsce na zewnątrz plus, potem, jakiś odbiornik.
Już po pierwszych przymiarkach okazało się, że nawet przy bardzo okrojonych założeniach i radykalnych cięciach w sofcie kod nadajnika jednak nie chce się zmieścić do procka. Trzeba było wybrać innego µC. Po krótkich poszukiwaniach procka posiadającego pożądane funkcje (pomiar ADC napięcia odniesienia i temperatury struktury, watchdog z przerwaniem, niewielka obudowa) wybór padł na rodzinę attiny24/44/84. Z tej rodziny wybrałem t84, różnica w cenie między najmniejszym i największym prockiem w serii jest prawie żadna a większa ilość FLASH i RAM daje jednak spory komfort w programowaniu. Duży FLASH pozwolił także, oprócz zasadniczej funkcjonalności, wepchnąć trochę kodu diagnostyczno-debugowego.
W elektronicznej dłubaninie najgorszą rzeczą dla mnie są kwestie obudowy. Znalezienie odpowiedniej obudowy wśród tego co jest dostępne na rynku przypomina zwykle podróż przez senne koszmary. Co gorsze nie można zacząć konstruowania na poważnie przed jej pozyskaniem, bo PCB trzeba zrobić pod obudowę. A bez zmontowanego PCB nie można rozpocząć poważnych prac nad firmwarem. I tak wszystko leży z powodu kawałka plastiku





Mając obudowę, można było wreszcie wykonać PCB. Płytka została wykonana domowym przemysłem metodą fotochemiczną (laminat jednostronny + folia foto) i pocynowana (Bisan LB3 + kuchenka gazowa).




Początkowo zakładałem, że µC będzie taktowany wewnętrznym oscylatorem co korzystnie wpłynie na zużycie energii. Jako że urządzenie miało zostać zamontowane na zewnątrz postanowiłem sprawdzić zachowanie wewnętrznego oscylatora w niskiej temperaturze. W zamrażalniku domowej lodówki dokonałem pomiarów zmiany częstotliwości oscylatora w temperaturze poniżej zera. Pomierzyłem także częstotliwości w temp. pokojowej oraz temp. pośredniej. Na podstawie tych pomiarów wyznaczyłem funkcję zmiany częstotliwości względem temperatury. Okazało się, że wpływ temperatury na częstotliwość oscylatora jest znacznie większy (ok 2x większy) niż wykazany w nocie katalogowej. Było to trochę za dużo dla nadajnika - zastosowany algorytm kodowania ma dosyć szeroką tolerancję częstotliwości, jednak w tym wypadku niewystarczającą. Pomyślałem że firmware może korygować częstotliwość w trakcie pracy na postawie odczytanej temperatury procesora. Tak więc wyznaczyłem funkcję i zastanawiałem się nad jej oprogramowaniem...ale przypomniałem sobie, że wewnętrzny oscylator jest też czuły na zmiany napięcia zasilania. A przecież napięcie baterii z biegiem czasu będzie spadać :-/ To już było ponad moją cierpliwość. Machnąłem ręką na oszczędności i zamontowałem rezonator kwarcowy. Na szczęście, na wszelki wypadek, na PCB przewidziałem dla niego miejsce.
Po uruchomieniu układu i zmontowaniu na stykówce odbiornika przyszedł czas na testy połączenia radiowego. Początkowe testy wykazały, że połączenie jest raczej zawodne, procent utraconych pakietów był bardzo duży (na dystansie ok 10-15m przez kilka ścian z cegły, różne odbiorniki prądu wokół). Poczytałem trochę o antenach 2)(bardzo obszerny temat) i poeksperymentowałem z kilkoma. Bez większego powodzenia. Trochę mnie to zniechęciło. Potem przypadkiem przełączyłem odbiornik na zasilanie z zasilacza (wcześniej był zasilany z USB laptopa) i nagle poziom błędów transmisji radykalnie spadł do akceptowalnego poziomu

Nadajnik pracuje nieco ponad miesiąc, w tym czasie obserwowałem niezawodność łącza, i stwierdzam, że działa to zadowalająco. Zaniki zdarzają się często, ale ponieważ każdy pakiet nowych danych jest powtarzany jeszcze dwukrotnie całkowita utrata danych zdarza się dosyć rzadko. Sporadycznie zdarzają się dni w których zakłócenia powodują przerwy w odbiorze długości 0.5-1 godziny, tak jak i dni z niemal zerowymi przerwami. Przeważnie procent całkowicie utraconych pakietów to ok. 5% czyli średnio jest to ok 3 minutowa przerwa raz na godzinę. Zakładam, że temperatura zewnętrzna zmienia się dosyć powoli, przyjąłem więc, że dane odczytane do 15 minut wstecz są wciąż aktualne, a miedzy 15 a 30 minut nadal wystarczająco dobre. Uważam więc, że jakość łącza w tym przypadku jest wystarczająca.
W momencie gdy przyszedł czas na montaż nadajnika uświadomiłem sobie, że jako iż czujnik ma wisieć na kilkumetrowym kablu, przydała by się jakaś ochrona portu przed przepięciami, czego w ogóle nie uwzględniłem w konstrukcji. Na płytce nie za bardzo było miejsce na przeróbki, a nie chciałem się bawić w robienie kolejnej więc na pająka plus dużo termogluta zamontowałem dwie diody schotkego i rezystor, przy czym rezystor już się nie zmieścił i znalazł miejsce już za złączem (czyli na przewodzie)


Firmware jest napisane w jęz. C i liczy 2365 linii kodu (z komentarzami) w tym 1248 kod osób trzecich. Wykorzystano oprogramowanie obce:
Obsługa UART (tylko Tx) wg Atmel Application Note AVR305 (z własnymi modyfikacjami) 115 LOC
Biblioteka OneWire oraz DS18B20 autorstwa Martin Thomas (ta druga z dużymi modyfikacjami) 851 LOC
Biblioteka VirtualWire autorstwa Mike McCauley (mikem@airspayce.com) (z dużymi modyfikacjami) 292 LOC
Urządzenie jest zasilane baterią 3 ogniw AAA. Teoretyczne obliczenia zużycia energii (bez uwzględnienia samorozładowania) wykazały, że energii powinno wystarczyć na blisko 4,5 roku pracy. W zużyciu energii udział transmisji radiowej to 32,5% całego zużycia, konwersji wykonywanej przez czujnik - 30,6%. Konwersja jest wykonywana z pełną rozdzielczością, gdyby zmniejszyć rozdzielczość to teoretycznie czas pracy zostałby wydłużony do:
5,2 lat przy rozdzielczości 11 bitów (przy 18% udziale w zużyciu energii),
5.8 lat przy 10 bitach (9,9% udziału)
6,1 lat przy 9 bitach (5,2% udziału)
I to mniej więcej tyle na temat nadajnika.
Jeszcze tylko podsumowanie kosztów.
Części elektroniczne, laminat: 45,90 zł.
Obudowa, przewód, podstawa: 41,16 zł.
Razem 87,06.
I na koniec urządzenie przed zamontowaniem w miejscu pracy.




1) https://www.spelsberg.pl/nc/produktu/an/80490701/
https://www.jula.pl/catalog/elektryka-i-oswie...ne/puszki-laczeniowe/puszka-odgalezna-403207/
2) https://wireless.murata.com/media/products/apnotes/antenna.pdf
https://lowpowerlab.com/guide/rf-best-practices/practical-considerations/
https://www.instructables.com/id/433-MHz-Coil-loaded-antenna/
http://www.antenna-theory.com/
i inne
Dodano po 14 [minuty]:
Termometr bezprzewodowy cz. 2. Odbiornik

W tej chwili odbiornik w postaci docelowej jeszcze nie istnieje. Na teraz, na szybkiego, zmajstrowałem na bazie Blue Pilla oraz wyświetlacza od zezłomowanej Nokii 6210 odbiornik tymczasowy. Ponieważ na wyświetlaczu jest trochę miejsca na dodatkowe dane dorzuciłem też czujnik temperatury, wilgotności i ciśnienia BME280, który w konstrukcji docelowej raczej nie jest przewidziany.

Napisane firmware odbiornika jest pierwszą praktyczną, całościową aplikacją napisaną przeze mnie przy wykorzystaniu frameworka QP/C, firmy Quantum Leap. Wcześniej robiłem jakieś testy, ćwieczenia. Tak więc był to swego rodzaju poligon.
QP/C (Quantum Platform in C) wg materiałów firmowych (tłumaczenie prawie dosłowne) jest "lekkim, open soursowym frameworkiem do budowy reaktywnych aplikacji czasu rzeczywistego jako systemu asynchronicznych, sterowanych zdarzeniowo, obiektów". Szczegółowe informacje i dokumentacja są dostępne na stronach producenta: https://www.state-machine.com/products/ więc nie będę się rozpisywał a tylko napiszę o jakichś swoich wrażeniach.
Framework jest portowany na sporą ilość procesorów, RTOSów oraz systemów operacyjnych w tym mnie interesujących Cortex-M, AVR, Linuks, pełna lista dostępna pod linkiem wyżej. I już na wstępie było to dla mnie bardzo użyteczne, bo zasadniczy szkielet aplikacji przetestowałem na PC a potem na procesorze docelowym testowałem tylko integrację z modułami niskopoziomowymi.
Wielką pomocą w budowie aplikacji jest modeler QM. Można w nim opracować cały szkielet aplikacji, a więc zdefiniować zbiór automatów z której ma się składać aplikacja, zdefiniować zbiór sygnałów (eventów) służących zarówno do zmiany stanów automatu jak do komunikacji między automatami (a także niekiedy automatu z sobą samym). Na podstawie zbudowanego modelu generuje się kod źródłowy w jęz. C (lub C++). Wygenerowany kod można potem edytować "z palca" bo jest wystarczająco czytelny (w załączeniu kod dla jednego z automatów), ale lepiej tego nie robić i wszystkie zmiany wprowadzać przez QM. Obsługa modelera jest łatwa, lekka i przyjemna

Oto główne okno programu z otwartym modelem omawianego odbiornika.

Po lewej, w sekcji "Model explorer" jest drzewo z elementami modelu. W gałęzi "Events" zdefiniowane są typy różnych sygnałów. W gałęzi AOs są zdefiniowane poszczególne taski, w tym wyświetlony w środkowym oknie task "Sensor" związany z czujnikiem BME280. W gałęzi "balkonowy_rx" są szablony do generowania kodu źródłowego. W okienku "Property Editor" pojawiają się propertiesy zależne od obiektu wybranego w okienku "Model explorer", w tym wypadku jest przełącznik wstawiania w kodzie źródłowym słowników do celów debugowania automatu "Sensor".

Powyższy screen pokazuje budowę automatu "Sensor", hierarchię stanów, przejścia oraz sygnały inicjujące te przejścia. I tak sygnał SNSR_TOUT jest generowany przez prywatny timer taska (każdy task może mieć kilka timerów), a sygnały SNSR_OK i ERR są generowane z zewnątrz wobec frameworka przez driver czujnika BME280.
Przykładowy kod wygenerowany przez QM dla automatu Sensor:
Code: c
Code: c
Jak już wspomniałem framework ma liczne porty. Na poniższych screenach faza testowania programu na PC i symulowany w oknie terminala wyświetlacz LCD.




Uruchamianie jest wpomagane dedykowanymi toolsami: QSpy, QSpyView, QUTest. QSpy pozwala na obserwację wszystkich chyba operacji wykonywanych w programie na poziomie frameworka. Zakres potrzebnych informacji jest mocno konfigurowalny. QSpyView pozwala na interaktywną pracę z QSpy, np. zmianę konfiguracji czy generowanie eventów "on line". QUTest to "test harness" do zautomatyzowanych testów jednostkowych. Narzędzia posiadają obszerną dokumentację https://www.state-machine.com/qtools/index.html. Poniżej kilka screenshotów z pracy narzędzi.
Informacje emitowane przez QSpy.

Formatka generowania eventu przez QSpyView

Diagram interakcji utworzony na podstawie danych dostarczonych przez QSpy (sam początek diagramu, bo cały diagram byłby baaardzo długi).

Film z działania (odbiór danych z czujnika zewnętrznego i aktualizacja ekranu):
https://youtu.be/5OsgzFKFDh0
Kod wygnerowany przez QM został zintegrowany z kodem niższego poziomu oraz z kodem z CubeMX. Integracja z CubeMX zdecydowanie była najgorszym etapem przy pisaniu programu. Kod CubeMX jest strasznie bałaganiarski z inicjacjami poukrywanymi w dziwnych funkcjach a framework wymaga pewnego porządku i kolejności inicjowania. Szczególnie ważne jest ustawienie odpowiednich priorytetów handlerów przerwań i moment ich włączenia. Ale jakoś się udało bo odbiornik działa

Kodu źródłowego nie zamieszczam bo konfiguracja całości jest dosyć skomplikowana (przynajmniej wg mojej sposobu) ale jak ktoś bardzo by chciał to mogę wstawić.
Cool? Ranking DIY