Prolog
Dziś wielki dzień, poniewaz postanowiłem po wielu obietnicach danych dawno temu- opisać projekt Synchro – zegarka na rękę z wyświetlaczem widmowym.
Jak zapewne wielu z Was wie – uwielbiam nietuzinkowe podejście i inne spojrzenie na pewne sprawy. Znajduje to także odzwierciedlenie w moich projektach.
Na youtube wielokrotnie możemy się natknąć na filmy z wyświetlaczami widmowymi, nazywanymi także POV displays (ang. Persistence of Vision). Działanie takich wyświetlaczy opiera się na zjawisku bezwładności wzroku i tzw. powidoku.
Uznałem, że działanie tych urządzeń jest niesamowite i postanowiłem sam podjąć próbę budowy takiego. Różnica polega na tym, że mój wyświetlacz POV umieszczony miał być w zegarku na rękę. A największe wyzwanie- w rozmiarach tego zegarka. Musi być on oczywiście mały.
Pierwsze próby rozpocząłem od wytrawienia wstępnej płytki wielkości płyty CD i użycia sporego silnika od wentylatora. Celem było napisanie szkicu programu, który będzie w stanie wyświetlić jakąś prostą grafikę czy wskazówkę. Od tego miało się zacząć.
Rozdział 1: Program
Najważniejszym wyzwaniem przy pisaniu szkicu było odpowiednie obliczenie czasów. Tarcza się obraca i powinna wyświetlać wzkazówkę. A więc zapalać odpowiednie diody w odpowiednim momencie i na określony czas. Mikrokontroler nie ma pojęcia nawet o tym, że się kręci, a co dopiero z jakąś prędkością. Zacznijmy więc od początku.
Mamy tarczę i na niej rząd 7 diod. Przyjmijmy, że chcemy wyświetlić wskazówke minutową, która wskazywać będzie 15 minut-> musi więc być skierowana w prawo. A to oznacza, że MCU musi zapalić wszystkie diody w momencie, kiedy wskazówka będzie się znajdować w pozycji 90 stopni od pionu.
Problemy jakie się pojawiają, są dwa:
- MCU musi wiedzieć, kiedy tarcza będzie ustawiona w takiej pozycji
- MCU musi wiedzieć, na jaki czas ma zapalić te diody – musi to być krótka chwila, nie dłuższa niż 1/60 czasu potrzebnego na pełen obrót tarczy.
Postanowiłem te problemy rozwiazać następująco. Po pierwsze, zamontowałem na płytce transoptor odbiciowy KTIR0711S. Jest to prosty komponent składający się z diody IR oraz odbiornika IR ustawionych w jedną stronę.
Do nieruchomiej częsci silnika przymocowałem kawałek drutu z blaszką, która pełniła rolę lusterka. Tarcza sie obracała- blaszka tkwiła nieruchomo. A odbiornik IR podłączyłem do MCU (mikrokontrolera) – odebranie sygnału (odbicie światła od blaszki) miało wywołać przerwanie zewnętrzne – w tym momencie MCU przerywał to, co aktualnie robi i mógł dodać jeden obrót do puli. Wiedział też, w którym momencie tarcza znajduje się w pozycji, którą roboczo nazwiemy sobie pozycją „0”.
Dobrze. Czyli teraz wiem, kiedy tarcza znajduje się w pozycji 0, oraz mogę zliczać obroty. Żeby policzyć czas jednego obrotu tarczy, potrzebuję jeszcze odmierzyć sobie jakiś stały odcinek czasu. Skonfigurowałem więc jeden z timerów MCU, żeby tykał co 1 sekundę, i co 1 sekundę wywoływał przerwanie synchroniczne.
Teraz MCU zliczając przerwania od transoptora pomiędzy przerwaniami timera, jest w stanie policzyć sobie, ile obrotów zrobił w ciągu sekundy.
Teraz wiem już, z jaką prędkością obraca się tarcza. Ile czasu powinna się zatem świecić wskazówka? Oczywiście 1/60 czasu obrotu.
Zbudowanie programu oparło się o framebuffer. Żeby program był przejrzysty, utworzyłem tablicę dwuwymiarową o rozmiarze 7×60.
7 dlatego, że tyle mam diod.
60 dlatego, że tarcza powinna mieć taką rozdzielczość obrotową dla dokładnego wyświetlania minut oraz sekund.
RTC- zegar czasu rzeczywistego aktualizował tablicę, natomiast funkcje odpowiadające za wyświetlanie -odczytywały ją.
Grafika poniżej przedstawia tarczę zegarka wzkazującą 12:15, oraz graficzne zobrazowanie, jak wygląda tablica przechowująca taką godzinę.
W momencie wykrycia pozycji „0” ustawiona zostaje flaga startu i zegarek rozpoczyna odczyt tablicy i sekwencję wyświetlania.
Przyjmijmy, że odczytane z przerwań obroty wynoszą 25rps(25 obrotów na sekundę). Zatem czas jegnego obrotu to 40 ms. dzielimy to na 60 i otrzymujemy ~0,67 ms. To jest czas wyświetlania jednej kolumny, na przykład wskazówki, czy indeksu godziny.
MCU koryguje ten czas raz na sekundę, w trakcie rozpędzania. Kiedy już osiągnie docelową prędkość obrotową, przechodzi w tryb korekcji. Kiedy poszczególne klatki nakładają się na siebie- wydłuża czas. Kiedy obraz nie jest dociągany do pełnego obrotu- czas jest wydłużany. To pozwala na znacznie szybsze i dokładniejsze określenie czasu wyświetlania kolumny.
Funkcja wyświetlająca sekwencję ma dość ciekawą postać:
//displaying matrix void matrixDisplayCcw() { if (startFlag == 1) { getTime(); matrixWriteMarkers(); matrixWriteTime(hours, minutes, seconds, 1); adcRead(); matrixWriteState(); startFlag = 0; ALL_OFF ; for (int i = 59; i >= 0; i--) { //for each from 60 column repeat:(i are column number) for (int j = 0; j <= 6; j++) { //for each pixel repeat:(j are row number) if (screenMatrix[j][i] == 1) { //in case of 1 in matrix pixel, turn on LED turnOn(j); } //end if if (startFlag == 1) { //if EXTI occurs //columnTime--; //decrease columnTime- means, that columnTime is too long. columnTime = columnTime - 100 / rpt; break; //and exit loop. Will be started in next run. } delayUs(columnTime); } //end for ALL_OFF ; //turn off all LEDs } //end for matrixWriteTime(hours, minutes, seconds, 0); //reload full array takes too log time matrixClearState(); } else { columnTime++; //^if startFlag isn't on instantly after display cycle means that column time are too short. } } //end function
Dodatkowo oprogramowałem ADC i dodałem wyświetlanie stanu baterii w formie pierścienia.
Rozdział 2: hardware
W międzyczasie powstały dwie wersje płytek już zegarkowej wielkości, z czego druga z nich została wyprodukowana w chinach w ilości kilkudziesięciu sztuk.
Niestey okazało się, że transoptor był złym pomysłem. W świetle dziennym jego praca była zakłócana. W kolejnej wersji użyłem czujnika Halla oraz magnesów.
W urządzeniu wykorzystałem MCU STM32l041, z serii low power, dzięki czemu zegarek w trybie uśpienia pobiera minimalną ilość prądu, wymaganą tylko do podtrzymania czasu. Jest zasilany ze stabilizatora liniowego LDO TC1185.
użyty silnik został wycięty z wentylatora SUNON 25x25x6mm, Jest to silnik BLDC o mocy 0.34W, z łożyskiem magnetycznym. Został wysterowany za pośrednictwem tranzystora MOSFET.
Pozwala on na ok 2h pracy w trybie force, kiedy zegarek obraca się nieustannie, oraz ok 500 uruchomień w trybie ondemand(włacza się tylko na 12 sekund),
Ładowarka nie jest zintegrowana z płytką. To często używany przeze mnie układ tp4056, z prądem ograniczonym do 250mA.
W projekcie użyte zostały 2 akumulatory li-po o pojemności 120mAh każdy, połaczone równolegle.
Cały montaż mechaniczny zegarka opiera się o klejenie na hotglue. Od spodu nalezy przykleić akumulatory, oraz silnik, a następnie dokleić silnik do płytki podstawki z magnesami.
Rozdział 3: obsługa
Synchro posiada dwa tryby pracy- force oraz ondemand. Można je przełaczyć przytrzymując oba przyciski naraz. Zegarek sygnalizuje zmianę trybu potrójnym mrugnięciem wszystkich diod.
Aby ustawić zegarek, należy wcisnąć przycisk SET. Ustawia się po kolei po jednej cyfrze:
- dziesiątki godzin
- Jedności godzin
- Dziesiątki minut
- jedności minut
- zerowanie sekundnika
Ustawianie poszczególnych cyfr odbywa się w trybie binarnym. Dodajemy wartość za pomocą przycisku WAKE, natomiast za pomocą SET przechodzimy do następnej wartości. Na grafice poniżej przedstawiłem w jaki sposób zegarek wyświetla cyfrę 5:
Jeżeli zegarek pracuje w trybie force i poziom naładowania spadnie poniżej 10%, automatycznie przechodzi w tryb ondemand, aby uniknać odcięcie akumulatora i zresetowanie godziny.
Kiedy coś go zatrzyma, np nasza ręka albo mankiet koszuli- automatycznie się usypia, niezależnie od wybranego trybu pracy.
Rozdział 4: Obudowa
Ze względu na delikatny charakter urządzenia, pojawiła się potrzeba zaprojektowania obudowy. W prototypach używałem w tym celu klatki polutowanej z miedzianego drutu:
Do wersji seryjnej zaprojektowałem klatkę która można wydrukować w 3D:
Zegarek prezentuje się w niej następująco:
Epilog
Tak oto zakończył się projekt synchro. Sama nazwa to skrót od SYNchronized display CHROnometer.
Oczywiście udostępniam Wam kod źródłowy, projekt, płytki, rysunki klatki a także zarys podstawki.
Zegarek nie jest praktyczny. Główne wady to czas jaki mija od momentu wybudzenia, do momentu wyświetlenia godziny. Ale nie taki miał być 🙂
Miał zwracać uwagę i być oryginalny- i taką rolę spełnia perfekcyjnie- Juz przywykłem do tego, ze jestem zaczepiany w sklepie czy kawiarni 🙂
A oto film przestawiający pracę zegarka:
Oczywiście cały projekt można pobrać z mojego githuba, link poniżej:
github.com/bartoszp1992/spinner.git
Ramzes
Kilka słów o autorze:
Bartosz „Ramzes” Pracz jest z wykształcenia humanistą, z zawodu konstruktorem elektroniki w branży oświetlenia LED, a z pasji programistą systemów wbudowanych z kilkoma większymi i mniejszymi projektami w portfolio. Oprócz pisania programów lubi także pisać dla Was ciekawe artykuły, oraz uczyć elektroniki wszystkich tych, którzy wykazują chęć rozwoju w tym kierunku. Prowadzący zajęć z podstaw elektroniki oraz programowania mikrokontrolerów ARM (STM32) oraz AVR (arduino). Jego pozostałe zainteresowania to webmastering, motoryzacja (w szczególności silniki i mechanika), jazda motocyklem, czytanie książek i jazda na łyżwach 🙂