
Po kilku miesiącach pracy wreszcie jest! Teraz możecie pytać, która godzina!
Pomysł projektu powstał, kiedy przez cztery dni autor podróżował po kraju. Kody QR są bardzo popularne z wielu powodów. Sprzedawcy uznają, że są one bardzo praktyczne i żądają umieszczania ich wszędzie, gdzie się da – pomimo tego, że nikt z nich nie korzysta.
Prawdziwym kłopotem z kodami QR jest konieczność używania sprzętu do przetworzenia ich na informacje, które mogą być odczytane przez człowieka. Dlaczego więc, zamiast kodu QR, nie umieszczać adresu internetowego – czy nawet nazwy firmy, gdyż dzisiaj każdy wie, jak używać wyszukiwarki?
Więc dlaczego powstał ten zegar? Autor uważa, że klasyczny zegarek naręczny jest najwygodniejszym, dokładnym i uniwersalnym narzędziem do wskazywania czasu. Jakakolwiek próba modyfikowania ich podnosi ich cenę i utrudnia odczyt godziny. Obydwie te „funkcje” zawarto w prezentowanym projekcie. Ponadto, zegar ten jest kwintesencją ironii kodów QR – udogodnienia technologicznego, które wcale nie jest dogodne. Zamiast wprost odczytać czas, musimy mieć skaner kodów, który z pewnością sam będzie też umożliwiał odczyt godziny. Właśnie dlatego powstał ten zegar.
Celem było stworzenie przyciągającego, samodzielnego zegara biurkowego lub naściennego, który wyświetla aktualny czas w formie kodu QR. Jest to duże wyzwanie, ponieważ doba ma 1 440 minut – to tyle właśnie kodów trzeba by było przechowywać w – skądinąd – obszernej pamięci. Dlatego też zegar nie korzysta z zapisanych kodów, a generuje je w locie.
Część sprzętowa
Pomijając fakt, że projekt płytki drukowanej jest dosyć skomplikowany, to schemat urządzenia jest całkiem prosty:

Zaprojektowanie płytki nie było nawet możliwe w darmowej wersji programu Eagle, autor musiał zakupić licencję:

Ze względu na wysoki stopień skomplikowania i wielkość płytki autor zdecydował się zlecić jej wykonanie, korzystając z usług jednej z chińskich fabryk płytek drukowanych. Przygotowanie projektu kosztowało $73, natomiast koszt jednej płytki był niższy od 5 dolarów. Gotowe płytki prezentują się następująco:

Niewielkim zaskoczeniem były jedynie niepokryte solder-maską przelotki:

Punkty, w których następuje jedynie połączenie ścieżek na różnych warstwach płytki są zwykle zakryte, co chroni przed ewentualnymi zwarciami. Jednakże, korzystając z Eagle’a, należy pamiętać, że typowe ustawienie nie obejmuje pokrycia przelotek solder-maską. Na szczęście ta „niedogodność” okazała się dla autora pomocna.
Dużym wyzwaniem była także konstrukcja wyświetlacza. Autor potrzebował matrycy diodowej o wymiarach 21x21 pikseli, z ramką o szerokości 1 px dookoła. Początkowym pomysłem było zastosowanie pojedynczych diod i zakrycie ich maskownicą – projekt takowej powstał nawet w Google SketchUp:

Autor, wiedząc o możliwości zastosowania gotowych matryc, obawiał się jednak, że skaner kodu QR może nie działać poprawnie, jeśli punkty świetlne miałyby okrągły kształt. Udało mu się jednak zdobyć matryce o kwadratowych pikselach, wykorzystujące czerwone i zielone diody LED. Autor, będąc przekonanym, że matryca z białych diod LED i o kwadratowych pikselach jest niedostępna, zdecydował połączyć diody czerwoną i zieloną, co skutkuje pomarańczową barwą wyświetlanych kodów.
Okazało się jednak, że biała matryca LED jest dostępna – ba, jest nawet sporo tańsza. Jednakże projekt płytki był już oddany do realizacji i było za późno na wprowadzenie zmian.
Wykorzystane matryce mają wymiary 8x8 pikseli, używając więc 9 autor uzyskał pole do wyświetlania o wielkości 24x24 piksele. Kody QR „zajmują” rozmiar 21x21 pikseli + 1 piksel ramki, więc jeden rząd i jedna kolumna pozostają niewykorzystane. Jednak dodatkowe diody okazały się pomocne, kiedy w wykorzystywanych rzędach jedna z nich się przepaliła.
Jednym z ciekawych, potencjalnych problemów z dużymi matrycami diod LED jest spójność barw. Diody, w zależności od terminu, kiedy opuszczają fabrykę, mogą różnić się nieznacznie barwą – choćby ze względu na niedostateczną precyzję wytwarzania czy zanieczyszczenia.
Autor przekonał się o tym, kiedy zamontował na płytce jedną matrycę z innej serii, zakupioną wcześniej do testów:

Różnica kolorów jest naprawdę subtelna, lecz na dobrym monitorze można dostrzec, że diody w lewym, górny rogu są nieco jaśniejsze, niż pozostałe. O wiele większy problem stanowiło wymontowanie jaśniejszej matrycy – ponieważ były one dokładnie do siebie dopasowane, zakończyło się to radykalnym rozwiązaniem:

Na szczęście sama płytka drukowana nie ucierpiała. Po zamontowaniu matryc z jednej serii problem został wyeliminowany:

Idealnym rozwiązaniem byłoby oczywiście sterowanie każdą diodą z osobna i wykorzystanie rejestrów przesuwnych. Takie rozwiązanie, ze względu na koszty i konieczność użycia 55 rejestrów, jest kompletnie nieopłacalne, choć byłoby wygodne ze względu na przerzucenie zapamiętywania stanów diod przez zewnętrzne układy i zwolnienie z tego zadania mikroprocesora.
Jednakże sama konstrukcja matryc była sporym utrudnieniem – producent, chcąc ograniczyć ilość wyprowadzeń, zastosował multipleksowanie – dla każdego rzędu wyprowadzono anody diod, a dla kolumn – ich katody.
Maksymalny prąd znamionowy dla diod wynosi 30 mA prądu stałego, lecz wartość ta może być zwiększona, jeśli diody sterowane są sygnałem o niskim wypełnieniu. W swoim rozwiązaniu autor stosuje maksymalne wypełnienie 12,5% i rezystory dobrane tak, by płynący prąd nie przekraczał wartości znamionowej.
Wyświetlanie sterowane jest za pomocą portów PB0-PB2 (służą do wyboru jednej z 8 linii połączonych z katodami diod, wymuszając na nich stan niski). W tym samym czasie piny PD2, PD5 oraz PD7 służą do wpisywania danych do rejestrów przesuwnych połączonych z anodami diod. Autor wykorzystał 3 linie danych, aby przyspieszyć operację wyświetlania.
Regulacja jasności odbywa się z pomocą wyprowadzenia ~OE. Poprzez podanie stanu wysokiego wszystkie diody zostają wyłączone. Szybka zmiana stanów na tym wyprowadzeniu pozwala dostosować jasność świecenia. Do wyprowadzenia tego należy przyłączyć rezystor podciągający – czego autor nie przewidział – aby uniknąć wyświetlania przypadkowego wzoru w czasie włączania zegara.
Zegar jest zasilany z zasilacza 5 V DC. Problemem były duże nieścisłości czasu w okresie nawet krótkiej,
8-godzinnej pracy. Przyczyna leżała w ogromnych – wynoszących nawet 2 wolty! – wahaniach na linii zasilania, wywołanych szybkim załączaniem i wyłączaniem diod.

Konieczne było zastosowanie dużych kondensatorów elektrolitycznych na zasilaniu, co wyeliminowało kłopot – dokładność odmierzania czasu wzrosła do 3 ppm.
Początkowo autor zamierzał wykorzystać procesor ATMega48, lecz 4k pamięci były niewystarczające do zaimplementowania generatora kodów QR. Na całe szczęście, dzięki zgodności wyprowadzeń, możliwe było zastosowanie procesora ATMega328.
Procesor taktowany jest wewnętrznym oscylatorem, zewnętrzny rezonator wykorzystywany jest jedynie do odmierzania czasu.
Na poniższych zdjęciach można obejrzeć gotowy, zmontowany zegar:


Oprogramowanie
Generowanie kodów QR nie jest kwestią łatwą, a – jak wspomniano – przechowywanie 1 440 kodów dla każdej minuty doby wymagałoby ogromnej pamięci (około 600k bez stosowania kompresji). Także do ich generowania wymagane jest zaangażowanie sporej ilości wymyślnych operacji matematycznych, które znacznie podnoszą odporność na błędy. Stosując właściwe ustawienia, można wygenerować kod, którego spora część będzie usunięta, a i tak zostanie poprawnie odczytany. Wskazuje to na wysoce skomplikowany i złożony proces.
Autor w swoim programie wykorzystał wiedzę zaprezentowaną w poradniku na stronach Thonky.com. Wszystkie opisane kroki muszą być wykonane, aby wygenerować kod o rozmiarze 21x21 pikseli w wersji 1, umożliwiający kodowanie znaków alfanumerycznych. Kod pozwala przechowywać 16 znaków tekstu (wyłącznie drukowane litery), liczb lub kilku symboli.
Szersze zrozumienie kodów umożliwia rzecz jasna definiująca je norma – ISO 18004 – lecz jej wersja drukowana to koszt ponad 200 dolarów.
Podstawowy schemat definiujący powstawanie kodów QR pokazuje poniższy obrazek:

Jest on na tyle skomplikowany, że autor zrezygnował ze szczegółowego opisu rozwiązań i udostępnił kod procesora odpowiedzialny za generowanie kodu.
Po kompilacji i uruchomieniu program pobiera 16 znaków i generuje poprawny kod QR. Autor, nie napotkawszy błędów dla generowania kodu dla ciągu znaków „HELLO WORLD” stwierdził, że błędy pojawiają się w przypadku kodowania innych tekstów – na przykład ciąg „HI LAUREN „ był kodowany poprawnie, podczas gdy „HI LAUREN” (bez spacji na końcu) – już nie. Kodowanie QR skutecznie „szyfruje” dane wejściowe, więc nawet bardzo podobne podstawy generowania kodu skutkują zupełnie różnymi wynikami. Autor nie obiecuje, że jego kod jest wolny od innych błędów.
Na procesorze ATMega328 taktowanym z częstością 8 MHz wygenerowanie kodu zajmuje około 7 sekund (10 sekund przy jednoczesnym odświeżaniu matrycy) – co w przypadku zmiany kodu co minutę nie jest długim okresem czasu – ale z punktu widzenia czasów wykonywania typowych operacji przez procesory z rodziny AVR trwa bardzo, bardzo długo.
Pozostałe
Ponieważ samo generowanie kodu i obsługa wyświetlacza zajmują bardzo dużo czasu, autor starał się, by prawie wszystkie inne funkcje były realizowane sprzętowo.
Ściemnianie diod realizowane jest automatycznie. Fototranzystor przyłączony jest do jednego z wejść przetwornika A/C procesora. Wartość konwersji sczytywana jest w regularnych odstępach, a odpowiednia jasność określana jest z pomocą tablicy przeglądowej. Przetwornik dokonuje konwersji na końcu operacji odświeżania ekranu, a dane odczytuje na jej początku.
Jasność kontrolowana jest dzięki szybkiemu przełączaniu stanów na wejściu ~OE rejestru. Steruje tym sprzętowy generator PWM procesora, którego wyjście (pin OC0A) połączono bezpośrednio z pinem ~OE. Dzięki temu jedyne, co jest konieczne, to ustalenie właściwego trybu pracy Timera0. Timer0 zaczyna od wartości 0 (diody włączone) zliczanie, i w momencie osiągnięcia wartości zgodnej z zapisaną w tabeli, na wejście ~OE podawany jest stan wysoki, wyłączający diody. Licznik zlicza do 255 i proces rozpoczyna się od nowa. Dzięki temu sterowanie jasnością za pomocą regulacji wypełnienia praktycznie nie jest realizowane programowo. Zmiana jasności odbywa się za pomocą zmiany wartości w rejestrze OCR0A.
Timer1 z kolei odpowiada za odświeżanie matrycy. Początkowo odświeżanie miało być stałe i następować w momencie przepełnienia licznika – jednak Timer1 jest 16-bitowy i od resetu do przepełnienia mijało za dużo czasu. Autor wykorzystał wartość zapisywaną do rejestru OCR1A – jeśli ilość zliczeń jest jej równa, następuje odświeżenie matrycy. W czasie odświeżania diody są wygaszane, aby zapobiec wyświetlaniu „duchów” na matrycy.
Wykorzystanie 16-bitowego timera umożliwia jeszcze jedno – a mianowicie takie ustalenie szybkości odświeżania, aby kod był widoczny przez ludzkie oko, a niemożliwy do odczytania przez jakikolwiek skaner… Na szczęście w ostatecznej wersji oprogramowania autor zrezygnował z tego „udogodnienia”…
Timer2 służy do odmierzania czasu, ze względu na niezależność jego taktowania od taktowania reszty obwodów procesora. Timer2 taktowany jest oscylatorem 32,268 kHz i 2E15 zliczeń odpowiada jednej sekundzie. Timer2 został tak skonfigurowany, że generuje przerwanie co 256 zliczeń. Ponadto, dzięki preskalerowi ustalonemu na wartość CLK/256 kod przerwania realizowany jest co 65 535 zliczeń, więc co każde 2 sekundy. Także ponieważ generowanie kodu zajmuje 7-10 sekund, kod dla nowej minuty generowany jest przed jej rozpoczęciem.
Do ustalania czasu autor wykorzystał – wyjątkowo! – przyjazny dla użytkownika tryb. Po uruchomieniu zegarka konieczne jest ustalenie czasu za pomocą przycisku i wyświetlanych na matrycy znaków. Po 10 sekundach braku interakcji z zegarem układ wychodzi z trybu ustawiania czasu, kolejne 10 sekund zajmuje wygenerowanie kodu.
Na poniższym nagraniu można obejrzeć pracujący zegar:
Podsumowanie
Na stworzenie tego projektu autor poświęcił sporo czasu – i jest bardzo zadowolony z rezultatów. Ciekawym rozwiązaniem jest możliwość połączenia zegara z komputerem za pomocą pinów TX/RX i wyświetlanie dowolnego kodu.
Ponieważ procedura generowania kodu QR jest opracowana, można pokusić się o dodanie prostego kalendarza w formacie „HH:MMAM mm/dd/rr”, co mieści się w zakresie 16 znaków możliwych do „zaszyfrowania” w kodzie.
Autor także myśli nad stworzeniem większego zegara – w środku kodu QR mógłby być wyświetlany zegar analogowy. Dzięki dużym możliwościom korekcji błędów w trakcie odczytywania kodu bez problemu jego niewielka część mogłaby być poświęcona na wskazywanie czasu w „klasyczny” sposób.
Więcej szczegółów na temat projektu oraz pliki projektu można znaleźć na stronie źródłowej.
Cool? Ranking DIY