Androidowy zegar Nixie (1)

Androidowy zegar Nixie (1)
Pobierz PDF Download icon
Na łamach czasopism elektronicznych oraz stronach internetowych opublikowano wiele projektów zegarków z lampami Nixie, w najróżniejszych konfiguracjach i opcjach. Były zarówno projekty oparte na popularnych mikrokontrolerach, były zegarki zbudowane na układach serii 74HC, a nawet zrealizowane na układach programowalnych. Jednak ten zegarek jest inny, ponieważ zastosowano w nim najnowsze zdobycze techniki, takie jak sensor laserowy lub sterowanie za pomocą smartfona. Rekomendacje: zegarek może być ozdobą niejednego wnętrza, a ze względu na swoją funkcjonalność może stać się nietuzinkowym prezentem.

Na tle innych, podobnych urządzeń, opisywany zegarek wyróżnia się brakiem przycisków mechanicznych, ponieważ sterowanie odbywa się za pomocą aplikacji dla systemu Android oraz laserowego czujnika zbliżeniowego. Wykorzystanie smartfona z dużym czytelnym wyświetlaczem jest o wiele wygodniejsze niż obsługa za pomocą przycisków mechanicznych oraz ładnego, aczkolwiek mało funkcjonalnego, wyświetlacza Nixie. Dodatkowo zyskujemy źródło czasu pochodzącego z sieci GSM, który będzie służył do synchronizacji zegara. Czujnik laserowy stanowi uzupełnienie interfejsu i umożliwia szybki dostęp do funkcji, takich jak wyświetlanie daty, godziny alarmu oraz zapewnia szybkie wyłączenie budzika. Rezygnacja z fizycznych przycisków daje możliwość wykonania estetycznej obudowy z pleksi lub szkła, pozbawionej otworów w widocznych miejscach. Zastosowanie skompensowanego generatora sygnału zegarowego 32 kHz umożliwia uzyskanie dobrej dokładności zegara, nawet przy niezbyt częstej synchronizacji z telefonem.

W urządzeniu zastosowano najpopularniejsze i najłatwiej dostępne w kraju lampy LC-513 produkcji zakładów Unitra Dolam o wielkości cyfr 15,5 mm. Lampy i podstawki są stosunkowo łatwo dostępne na aukcjach internetowych, więc każdy zainteresowany może wykonać zegar we własnym zakresie. Średnia trwałość lamp LC-513 jest określona na około 100 tys. godzin. Dodatkowe funkcje, takie jak: automatyczne dostosowanie poziomu jasności do warunków oświetleniowych, możliwość zaprogramowania przedziału godzin w cyklu dobowym (wtedy wyświetlacz może być wyłączony) i funkcja odtruwania katod, pozytywnie wpływają na trwałość wyświetlacza.

Budowa urządzenia

Zegar zbudowano w oparciu o dwie płytki drukowane: płytę główną zawierającą mikrokontroler oraz większość innych układów (rysunek 1) oraz płytę wyświetlacza z układem sterującym (rysunek 2). Całością steruje mikrokontroler STM32F103R8T6 (U5) w obudowie TQFP64, zawierający 64 kB pamięci Flash oraz 20 kB pamięci RAM. Wybór tego układu był podyktowany jego niską ceną oraz wewnętrznym zegarem RTC, który jest 32-bitowym licznikiem zwiększającym zawartość co 1 sekundę. Dzięki takiemu rozwiązaniu układ RTC pozwala odmierzać czas systemowy bezpośrednio w formacie UTS (Unix Time Stamp). Niestety, późniejsze wersje układów rodziny STM32 mają typowy zegar RTC zliczający w BCD, co zdaniem autora jest krokiem wstecz. Rdzeń mikrokontrolera jest taktowany wewnętrznym generatorem RC (8 MHz), natomiast licznik RTC jest taktowany za pomocą dodatkowego sygnału o częstotliwości 32 kHz, dostarczanego z generatora DS32KHZ (U1), który jest skompensowanym temperaturowo generatorem kwarcowym zapewniającym maksymalną odchyłkę czasu 1 minutę na rok oraz charakteryzującym się poborem prądu rzędu 1 mA.

Do linii portu szeregowego UART3_TX, RX dołączono popularny moduł Blue-
tooth HC-05, który zapewnia komunikację ze światem zewnętrznym. Moduł ten jest konwerterem protokołu Bluetooth RFCOMM na RS232, który od strony mikrokontrolera może być sterowany za pomocą komend AT.

Do linii PB6 i PB7 stanowiących linie SDA, i SCL układu peryferyjnego I2C1 dołączono laserowy czujnik odległości VL6180x odpowiedzialny za wykrywanie gestów. Do portu PB5 dołączono sygnał przerwania GPIO0 czujnika, który jest używany do sygnalizowania zdarzeń generowanych przez czujnik, dzięki czemu nie ma konieczności ciągłego odpytywania układu.

Linia PB8, stanowiąca wyjście 3 sygnału PWM TIM3, za pomocą filtru dolnoprzepustowego złożonego z rezystora R8 i kondensatora C15 jest dołączona do wejścia wzmacniacza audio TS4490ID (U6). Wzmacniacz ten pracuje w układzie mostkowym w klasie AB i przy zasilaniu 5 V dostarcza sygnał o mocy 1 W przy obciążeniu 8 V.

Linię PB1 dołączono do linii STBY wzmacniacza, umożliwiając redukcję poboru prądu przez układ wzmacniacza do około 10 nA w stanie nieaktywności. Wyjście wzmacniacza dołączono do niewielkiego głośniczka LD-SP-U30/8A, który jest odpowiedzialny za generowanie dźwięku alarmów. Dzięki zastosowaniu trybu PWM do generowania audio możemy w pamięci Flash mikrokontrolera zapisać bardziej „przyjazne” dla ucha dźwięki niż przy zastosowaniu typowego buzzera.

Zasilacz niskiego napięcia zrealizowano z użyciem stabilizatorów liniowych. Układ 78L05 (U4) dostarcza napięcie +5 V potrzebne do zasilania wzmacniacza audio, natomiast układ SPX1117-3.3 jest odpowiedzialny za dostarczanie napięcia +3,3 V stanowiącego zasilanie mikrokontrolera. Do linii zasilającej VBAT mikrokontrolera, oraz generatora DS32KHZ dołączono zasilanie z baterii litowej CR2032 (B1), zapewniając podtrzymanie zliczania czasu po zaniku napięcia sieciowego. Blok zasilacza wysokonapięciowego dostarczającego napięcie +165 V, do zasilania lamp LC513, zrealizowano w topologii boost z zastosowaniem kontrolera MAX1171 (U1). Układ ten charakteryzuje się pracą z częstotliwością 300 kHz, zapewnia dużą sprawność przetwarzania (rzędu 90%) oraz bardzo mały pobór prądu rzędu 300 mA w stanie bez obciążenia. Zawiera także zintegrowany sterownik zewnętrznego tranzystora N-MOSFET znacznie zmniejszający liczbę potrzebnych elementów zewnętrznych. Wyjście EXT steruje tranzystorem IRFB9N30A (Q1) o rezystancji kanału 0,45 V, napięciu wstecznym 300 V i prądzie przewodzonym 9 A. Cewka L1, dioda D1 i tranzystor Q1 stanowią fragment przetwornicy w topologii boost. Pętlę sprzężenia zwrotnego zrealizowano za pomocą rezystorów R1 i R3, natomiast napięcie wyjściowe jest filtrowane za pomocą kondensatora 680 nF/450 V (C5). Linie PA0-15, PB13-15, PC0-12, PD0-1 są używane do sterowania lampami Nixie. Za pomocą drabinek rezystorowych zostały dołączone do złączy JP1 i JP2, których użyto do połączenia płyty kontrolera z płytką wyświetlacza.

Na płytce wyświetlacza zamontowano układ TSL238T (U1) będący czujnikiem natężenia światła, który zapewnia automatyczny dobór jasności świecenia cyfr. Układ ten dostarcza sygnał wyjściowy o częstotliwości proporcjonalnej do natężenia oświetlenia, który poprzez złącze JP3 jest podawany na wejście PB0 mikrokontrolera. Choć czujnik laserowy ma zintegrowany czujnik światła dziennego, celowo zastosowano osobny czujnik umieszczony na froncie po to, aby mierzył poziom światła padający bezpośrednio na wyświetlacze. Za sterowanie elektrodami Nixie są odpowiedzialne tranzystory bipolarne NPN typu MMBTA42 o maksymalnym napięciu wstecznym 300 V i prądzie przewodzenia do 100 mA. Wyświetlacze umieszczono w specjalnych podstawkach dla lamp LC513. Pomiędzy lampami L3, L4 a L5, L6 znajdują się dwie neonówki DS1 i DS2 umieszczona jedna nad drugą. Służą one do wyświetlania dwukropka pomiędzy minutami i godzinami.

Oprogramowanie

Oprogramowanie mikrokontrolera napisano w języku C++14 za pomocą kompilatora gcc w wersji 6.2 pracującego pod kontrolą systemu operacyjnego ISIX-RTOS. Jest ono dostępne na otwartej licencji GPL. Oprogramowanie można pobrać z repozytorium znajdującego się pod adresem https://www.boff.pl/cgit/public.

Budowę firmware'u zegara przedstawiono na rysunku 3. Oprogramowanie podzielono na warstwę sterowników oraz warstwę aplikacji. Sterowniki są odpowiedzialne za obsługę: wyświetlacza Nixie, zegara RTC, czujnika laserowego, audio PWM oraz portu szeregowego.

Część aplikacyjną zrealizowano w postaci 4 wątków systemu ISIX. Wątek wizualizacji odpowiada za wyświetlanie danych na wyświetlaczu Nixie. W zależności od kontekstu jest to data, czas lub godzina alarmu. Wątek interpretacji gestów odczytuje stan czujnika VL6180 i w zależności od wykrycia odpowiednich gestów polegających na zbliżaniu ręki do czujnika i zatrzymaniu w pewnej odległości generuje zdarzenia, które są interpretowane przez wątek główny. Wykrywa on dwa rodzaje gestów: gest odczytu daty polegający na energicznym zbliżaniu ręki do czujnika i zatrzymaniu jej w odległości większej niż 5 cm oraz gest odczytu godziny alarmu polegający na energicznym zbliżaniu ręki i dotknięciu obudowy zegara.

Wątek Bluetooth jest odpowiedzialny za zarządzanie i konfigurację modułu HC-05 oraz interpretacje rozkazów otrzymywanych z aplikacji zainstalowanej na smartfonie. Po otrzymaniu stosownego komunikatu generuje on zdarzenie interpretowane przez wątek główny aplikacji.

Wróćmy do opisu warstwy sterowników. Z uwagi na to, że w projekcie przyjęto założenie płynnej regulacji jasności oraz efekt płynnego przejścia między cyframi, sterownik wyświetlacza musi każdą cyfrą sterować za pomocą sygnału PWM. W mikrokontrolerach STM32 mamy limitowaną liczbę wyprowadzeń, które mogą pełnić funkcję wyjścia sprzętowego sygnału PWM, natomiast do sterowania wyświetlaczem potrzebujemy aż 27 linii wyjściowych. Co prawda, jedynie 5 linii jest aktywnych w tym samym czasie i można pokusić się o dołączenie zewnętrznych demultiplekserów, jednak niepotrzebnie skomplikowałoby to budowę urządzenia. W związku z powyższym zdecydowano się na rozwiązanie w postaci programowego generowania sygnału PWM. Za generowanie sygnału PWM odpowiada klasa soft_pwm (plik soft_pwm.cpp/hpp), która wykorzystuje sygnał przepełnienia od układu czasowo-licznikowego T1 do wytwarzania przerwania. Licznik skonfigurowano tak, aby przerwanie było wywoływane z częstotliwością 25,6 kHz. Przy 8-bitowym liczniku PWM zapewnia to uzyskanie częstotliwości odświeżania wyświetlacza równej 100 Hz, co jest wartością wystarczającą, aby zapobiec nieprzyjemnemu migotaniu cyfr. Przerwanie odpowiedzialne za generowanie sygnału PWM jest wywoływane ze stosunkowo dużą częstotliwością i nie powinno być blokowane, dlatego zostało skonfigurowane z najwyższym priorytetem i może wywłaszczać pozostałe przerwania. Priorytet przerwania T1_OVERFLOW znajduje się również powyżej priorytetu przerwań blokowanych za pomocą rejestru BASEPRI przy wejściu do sekcji krytycznych systemu ISIX, w związku z tym wszystkie operacje związane z tym przerwaniem nie mogą wykorzystywać API systemu, a jedyną możliwością synchronizacji i komunikacji jest wykorzystanie operacji atomowych. Procedura obsługi przerwania od układu czasowo-licznikowego i najważniejsze elementy programowego generowania PWM są przedstawione na listingu 1.

Każde utworzenie nowej instancji klasy soft_pwm powoduje wywołanie konstruktora, który za pomocą zmiennej atomowej g_locked blokuje dostęp do obiektu std:list, a następnie dopisuje na koniec listy wskaźnik na nowo utworzony obiekt klasy. Jeśli przy próbie dopisania elementu lista jest pusta oznacza to, że układ czasowo-licznikowy nie został jeszcze uruchomiony. W związku z tym jest wywoływana funkcja, której zadaniem jest konfiguracja układu czasowo-licznikowego T1, aby generował przerwania z częstotliwością 25,6 kHz. Podobnie, gdy obiekt klasy soft_pwm kończy swój cykl życia, zostaje wywołany destruktor, który ustawia blokadę listy, a następnie kasuje element z listy odpowiadający temu obiektowi. Procedura obsługi przerwania tim1_up_isr_vector() jest funkcją zaprzyjaźnioną z klasą soft_pwm i cyklicznie z częstotliwością 25,6 kHz wywołuje metody isr_handler() dla wszystkich zarejestrowanych instancji klas. Wektor przerwania został zdefiniowany z dodatkowymi atrybutami nakazującymi kompilatorowi włączenie dla tej funkcji agresywnej optymalizacji.  Wykorzystanie listy obiektów podłączanych pod procedurę przerwania umożliwia elastyczne tworzenie instancji klas soft_pwm, zapewniając generowanie dowolnej liczby sygnałów PWM. Publiczne API klasy soft_pwm pokazano na listingu 2.

Wywołanie metody change_pin() z referencją do obiektu out zawierającym nazwę i numer portu GPIO powoduje płynne zmniejszenie współczynnika wypełnienia sygnału PWM poprzednio przypisanego wyprowadzenia i jednocześnie płynne zwiększenie współczynnika wypełnienia dla nowego portu. Zastosowanie takiego triku umożliwia osiągnięcie ciekawego efektu wizualnego polegającego na płynnym efekcie przejścia z jednej cyfry w drugą. Metoda level() służy do ustawienia poziomu jasności wyświetlacza, należy tutaj podać wartości w zakresie od 0 do 255.  Metoda fast umożliwia określenie, czy efekt przejścia między cyframi ma być szybki (0,1 s), czy powolny (1 s). Metoda fast ustawiana jest tylko dla sygnałów PWM odpowiedzialnych za dwukropki.

Klasa soft_pwm jest klasą usługową wykorzystywaną  przez właściwy sterownik wyświetlacza realizowany przez klasę nixie_disp (pliki nixie_disp.cpp/hpp). Sterownik wyświetlania udostępnia wysokopoziomowe API do obsługi cyfr.  Na początku tworzy on 5 obiektów klas soft_pwm odpowiadający odpowiednio cyfrom godzin, dwukropkowi oraz cyfrom minut soft_pwm m_pwm[_pwm_eof_];. Publiczne metody klasy sterownika wyświetlacza zgodne są z biblioteką strumieniową dla wyświetlaczy znakowych z lib-
foundation (listing 3).

Metoda putc() służy do wyświetlania znaku na bieżącej pozycji kursora, metoda setpos() ustawia kursor znaku na żądanej pozycji, metoda brightness() umożliwia ustawienie poziomu podświetlania, natomiast metoda clear() zeruje wyświetlacz i ustawia kursor na pozycji początkowej. Pełna zgodność z biblioteką wyświetlaczy znakowych z libfoundation umożliwia wykorzystanie przeciążonego operatora „<<”. Naturalnie, z uwagi na ograniczenia samego wyświetlacza, na pozycjach 0, 1, 3, 4 mogą być wyświetlane tylko cyfry, natomiast na pozycji 2 odpowiadającej za dwukropek interpretowane są jedynie znaki „:”, „.” „’” oraz spacja. Najciekawsze fragmenty implementacji klasy wyświetlacza przedstawiono na listingu 4.

Tablica ports jest tablicą obiektów dev::out o wymiarach 5×10 zawierającą mapowanie poszczególnych portów mikrokontrolera na odpowiadające cyfry wyświetlacza. Zadeklarowano ją jako wyrażenie stałe, znane podczas kompilacji, więc kompilator umieści ją w pamięci Flash. Klasa out przechowuje informacje o nazwie portu oraz numerze pinu w postaci prywatnego pola o wielkości jednego bajtu i zawiera metody port()/pin(), które umożliwiają zdekodowanie informacji do postaci akceptowanej przez funkcję gpio_set()/gpio_clr(). Wyświetlenie znaku na wybranej pozycji realizowane jest przez prywatną metodę handle_digit(). Działanie tej metody polega na wybraniu z tablicy odpowiedniego elementu oznaczającego numer linii GPIO na podstawie cyfry oraz pozycji, a następnie wywołaniu metody change_pin() z odpowiadającego obiektu klasy soft_pwm. Jak już wspomniano, priorytet obsługi przerwania realizującego PWM znajduje się powyżej priorytetu maskowania przerwań sekcji krytycznych systemu, zatem nie ma możliwości realizacji powiadomień np. za pomocą semaforów systemowych. Aby zapobiec wykonaniu kolejnej sekwencji przenikania cyfr poprzez niespodziewanie rozpoczęcie nowego cyklu, metoda change_pin() zwraca wartość true, gdy sterownik softpwm znajduje się w trakcie realizacji algorytmu przenikania. Jeśli wywołanie metody change_pin() nie powiodło się, wówczas podejmujemy kolejną próbę po odczekaniu 250 ms. Nie jest to rozwiązanie zbyt eleganckie, ale dzięki takiemu podejściu przerwanie realizujące PWM nie jest nigdy wstrzymywane.

Lucjan Bryndza, EP

Artykuł ukazał się w
Elektronika Praktyczna
maj 2017
DO POBRANIA
Pobierz PDF Download icon
Materiały dodatkowe

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik kwiecień 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio marzec - kwiecień 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje kwiecień 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna kwiecień 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich maj 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów