Tutaj pokażę, jak stworzyłem i przetestowałem sterownik lampy LED sterowanej PIR (z czujnikiem światła) dla OpenBeken - wszystko bez dostępu do fizycznego urządzenia. Ten temat obejmie cały proces rozwoju: od koncepcji, przez symulację, po automatyczne testowanie. Niezależnie od tego, czy uczysz się, jak dodać sterownik OBK, czy po prostu dopiero poznajesz firmware, ten samouczek pokazuje, jak możesz szybko napisać i przetestować własny sterownik, używając tylko symulatora OBK i self testów.
Zobaczysz, jak symulować wejścia GPIO, takie jak ruch i poziomy oświetlenia otoczenia, jak udostępniać elementy sterujące sterownika za pośrednictwem interfejsu internetowego HTTP oraz jak zweryfikować prawidłowe zachowanie za pomocą testów jednostkowych.
Ostrzeżenie: ten temat jest samouczkiem / przewodnikiem programistycznym dla OBK i wymaga podstawowej wiedzy z zakresu programowania w języku C, podstawowa wiedza na temat OBK również będzie pomocna!
Ogólny pomysł na sterownik i używany sprzęt
Poniższy sterownik PIR będzie działał na lampie LED, która ma czujnik ruchu (wartość logiczna) z kontrolowaną czułością (poprzez PWM) i czujnik światła (ADC). Sterownik PIR powinien mieć dwa tryby sterowania, pierwszy ręczny, który po prostu ignoruje wszystkie czujniki i pozwala użytkownikowi kontrolować go, oraz tryb automatyczny, który wykorzystuje wejście ruchu, wejście ADC i ustawienia zdefiniowane przez użytkownika (czas włączenia i margines światła), aby włączyć światło. Światło jest włączane tylko wtedy, gdy występuje ruch, a otoczenie jest wystarczająco ciemne - nie powinno być włączane w ciągu dnia.
Przykładowy szablon urządzenia OBK (przesłany mi przez użytkownika posiadającego to urządzenie):
Kod: JSON
Piny 8 i 9 służą do sterowania światłem CW, więc można je zignorować. Dla nas liczy się pin 6, który jest wejściem danych PIR, pin 23, który jest wejściem czujnika światła i pin 26, który służy do ustawiania czułości PIR.
Krok 1 - Konfiguracja środowiska
OpenBeken może być uruchomiony bezpośrednio na platformie Windows z wirtualnym symulatorem urządzenia . Wszystkie wymagane zależności są dostępne do pobrania w repozytorium symulatora . Po prostu otwórz projekt MSVC (zaktualizuj go, jeśli wolisz nowszy MSVC):
Następnie powinieneś być w stanie zarówno zbudować, jak i debugować port OBK Windows:
Możesz umieścić punkt przerwania w dowolnej funkcji zawartej w porcie Windows i będziesz mógł zbadać wartości zmiennych, stos itp. Oczywiście nie obejmuje to kodu specyficznego dla platformy, ale jest to oczekiwane przez projekt.
Można również uzyskać dostęp do symulowanej strony urządzenia i narzędzia schematu:
Krok 2 - Wstępny szkic sterownika
Teraz nadszedł czas, aby zacząć pisać sterownik. Omówiłem już podstawową procedurę sterownika w osobnym temacie, więc po prostu podam do niego link poniżej:
[English] Jak utworzyć niestandardowy sterownik dla OpenBeken z kompilacjami online (nie jest wymagany toolchain)
[Polish] Jak stworzyć niestandardowy sterownik dla OpenBeken z kompilacjami online (nie jest wymagany toolchain)
Sterownik może zasadniczo mieć funkcje szybkiego i wolnego tikowania (powolne tikowanie jest wywoływane "co sekundę", ale wkrótce będzie można je dostosować), funkcję inicjowania, zamykania, a także może odbierać wywołania zwrotne zmiany kanału i odświeżania strony HTTP, które można wykorzystać do niestandardowego interfejsu użytkownika.
Krok 3 - Pierwszy projekt sterownika
Tak więc, jak pokazano w poprzednim tutorialu , zacząłem od wpisu drv_main.c:
Kod: C / C++
Następnie przygotowałem stuby funkcji:
Kod: C / C++
Funkcje Init i OnEverySecond powinny być oczywiste, jedna jest wywoływana przy starcie, a druga cyklicznie - co sekundę. Funkcja HTTP page jest bardziej interesująca - zapewnia dostęp do statycznego HTML (jeśli bPreState wynosi 1) oraz do dynamicznego stanu HTML, który jest odświeżany co sekundę (jeśli bPreState wynosi 0). Statyczny HTML powinien być używany do strony konfiguracyjnej z danymi wprowadzanymi przez użytkownika, a sekcja dynamiczna może być używana do wyświetlania bieżących informacji o stanie sterownika.
Kod: C / C++
Dołączyłem również nagłówki funkcji, w tym zmienne flash do odczytu i zapisu stanu.
Zacznijmy więc od funkcji init. W tym przypadku potrzebujemy tej funkcji, aby automatycznie znaleźć pasujące kanały dla urządzenia PIR, a także przywrócić ustawienia z flashvars:
Kod: C / C++
Ten sterownik zakłada, że użytkownik ustawił wymagane role pinów i / lub typy kanałów i używa tylko pierwszego kanału / pinu, który spełnia wymagania. Powinno to wystarczyć na początek, bardziej konfigurowalną wersję można wykonać później.
Następnie rozważmy obsługę strony HTML, która służy do tworzenia interfejsu konfiguracyjnego i wyświetlania bieżącego stanu PIR:
Kod: C / C++
To wywołanie zwrotne zarówno tworzy stronę HTML, jak i odbiera dane z przesłanego formularza HTML za pośrednictwem funkcji http_getArg. Parametry są później zapisywane w zmiennych flash, więc są trwałe między ponownymi uruchomieniami.
Na koniec zaimplementowałem logikę PIR, która jest odświeżana co sekundę:
Kod: C / C++
Powyższa logika jest dość prosta. W trybie automatycznym sterownik najpierw testuje poziom światła w otoczeniu. Następnie sprawdzany jest PIR. Jeśli otoczenie jest jasne i występuje ruch, wówczas światło jest włączane, a timer jest ustawiany na wartość początkową. Następnie timer jest odliczany i jeśli się skończy, dioda LED zostanie wyłączona. To wystarczy dla podstawowej funkcjonalności PIR.
Krok 4 - Testowanie konfiguracji sterownika ręcznie
Jest to dość oczywisty krok, ale wciąż warto o nim wspomnieć. Podczas tworzenia sterownika bardzo łatwo jest przetestować go bezpośrednio w systemie Windows. Wystarczy uruchomić symulator i uzyskać dostęp do strony OBK na IP komputera, domyślnie używając portu 80. Port można zmienić za pomocą wiersza poleceń, jeśli chcesz uruchomić wiele urządzeń OBK w tym samym czasie.
W ten sposób mogę uzyskać to:
Mogę umieścić punkty przerwania w kodzie sterownika, aby zobaczyć, co się stanie:
I może ustawiać stany na symulowanych GPIO poprzez zwarcie ich do masy lub zasilania (lub za pomocą przycisku):
(oczywiście schemat jest uproszczony, nie powinieneś próbować tworzyć takiego obwodu w rzeczywistości).
Może to być pomocne przy testowaniu i zabawie, zwłaszcza że Simulator obsługuje również Home Assistant, ale jest jeszcze lepsze rozwiązanie...
Krok 5 - Dodanie autotestów podczas programowania
Automatyczne testowanie OpenBeken zostało krótko opisane tutaj . Mechanizm ten znajduje się w katalogu src/selftest. W tym przykładzie rozważmy kod selftest_pir.c, który możemy później wywołać z głównego programu wywołującego test:
Kod: C / C++
Powyższy kod najpierw ustawia wymaganą konfigurację GPIO i kanałów, a następnie uruchamia sterownik. Po uruchomieniu sterownika, podstawowa konfiguracja PIR jest wykonywana za pomocą symulowanych pakietów HTTP - jest to to samo, co przeglądarka użytkownika wysyła po przesłaniu formularza HTML:
Kod: C / C++
Na koniec symulowany jest również stan IO - zarówno odczyt ADC (poziom światła), jak i stan ruchu (boolean). Następnie testowane jest początkowe zachowanie sterownika PIR.
Kod: C / C++
Sterownik PIR powinien włączyć diodę LED, gdy tylko zostanie wykryty ruch i nie ma wystarczającego oświetlenia otoczenia. Tak więc, LED_GetEnableAll powinien zwrócić 1. Poniższy test spowoduje asercję, jeśli dioda LED nie zachowuje się zgodnie z oczekiwaniami.
Następnie symulujemy ciągły ruch:
Kod: C / C++
Dla pewności - zanim ruch zniknie:
Kod: C / C++
Następnie, po symulowanym oczekiwaniu dłuższym niż czas włączenia diody LED, dioda LED powinna się wyłączyć. To również zostało przetestowane.
Na koniec testujemy jeszcze jeden scenariusz - co jeśli jest ruch, ale otoczenie jest na tyle jasne, że nie potrzebujemy diody LED?
Kod: C / C++
Światło powinno zgasnąć w tym przypadku i tak, robi to zgodnie z oczekiwaniami.
Co by się stało, gdyby wystąpił błąd w sterowniku?
Teraz, dla dobra prezentacji, rozbijmy logikę naszego sterownika. Przeniosłem odliczanie else wewnątrz bloku "isDark", więc teraz czas spada tylko wtedy, gdy nie ma światła:
To sprawia, że zachowanie sterownika jest nieprawidłowe - dioda LED nie zgaśnie, jeśli jest włączona, gdy zaczyna się dzień.
Teraz uruchomiłem autotesty i tak, wykryły problem;
Asercja zawodzi i deweloper od razu wie, że coś złego stało się ze sterownikiem. Nie zapominajmy, że te same testy są uruchamiane na Githubie, więc nawet zewnętrzne commity (pull requesty) są również sprawdzane.
Podsumowując, w ten sposób mogę szybko i łatwo rozwijać sterowniki dla OBK. Dzięki mechanizmowi portu/symulatora Windows mogę:
- szybko uruchamiać i testować funkcje bezpośrednio na PC
- symulować proste obwody i stany GPIO za pomocą narzędzia "schematic editor"
- debugować zachowanie OBK w efektywnym debugerze MSVC (umieszczać punkty przerwania, sprawdzać wartości zmiennych, sprawdzać pamięć)
- automatyczne testowanie zachowania OBK przy każdym zatwierdzeniu/uruchomieniu za pomocą autotestów
- podłączenie OBK do HA bez konieczności posiadania fizycznego urządzenia (symulator obsługuje MQTT przez LWIP).
z Oczywiście takie podejście nie jest w stanie w pełni zastąpić testowania na fizycznym urządzeniu, ponieważ część kodu jest zależna od platformy i urządzenia, ale nadal stanowi świetny punkt wyjścia do szybkiego rozwoju i walidacji sterowników OBK, przynajmniej jeśli nie są one mocno skoncentrowane na mechanizmach per-platformowych, takich jak przerwania lub DMA ...
PS: Sterownik PIR został już przetestowany przez naszego użytkownika na fizycznym urządzeniu i podobno działa dobrze, choć prawdopodobnie jeszcze go poprawię w najbliższych dniach .
Fajne? Ranking DIY Pomogłem? Kup mi kawę.