Zegar słowowy – word clock

Zegar słowowy – word clock

Witam Was w moim kolejnym wpisie na majsterkowie.

Tematem dzisiejszego wpisu będzie… zegar. Tak, wiem – mam coś z zegarami, delikatnie licząc w ciągu ostatniego roku zrobiłem chyba ze 4. Ale nic na to nie poradzę :P

Tak jak w przypadku mojego poprzedniego zegara, ten również będzie wyświetlał aktualną godzinę w bardzo nietypowy sposób. Zegar ten będzie pokazywał zdanie (w języku angielskim), które odczytane powie nam, która jest godzina. Na początku zaprezentuję Wam zdjęcie, które dawno temu znalazłem w Internecie, a które zainspirowało mnie do budowy niniejszego zegara.

vinylclock

Zegar oparty będzie oczywiście o mój ulubiony mikrokontroler ATmega328, z wgranym bootloaderem Arduino i zaprogramowany przy pomocy Arduino IDE. Za podświetlenie konkretnych słów na froncie zegara odpowiadać będą odpowiednio umieszczone białe paski LED zasilane napięciem stałym 12V. Będą to standardowe paski z taśmy, z możliwością cięcia co 3 diody (5 cm).

Prąd pobierany przez pojedynczy, 5 centymetrowy segment jest ograniczany przez rezystor SMD o oznaczeniu 151 (czyli o rezystancji znamionowej 150Ω). Z prawa Ohma łatwo policzyć, że dla napięcia 12V, spadku napięcia na trzech białych diodach (typowo ~3V na jednej) i rezystancji 150Ω pobór prądu pojedynczej sekcji wyniesie (12V-3*3V)/150Ω=0,02A=20mA. Niektóre słowa (ze względu na ich długość) podświetlane będą 6 diodami. Segmenty na taśmie połączone są ze sobą równolegle, więc z pierwszego prawa Kirchhoffa wiemy, że dwa segmenty pobiorą 40mA prądu.

Problematyczne, z punktu widzenia sterowania z poziomu mikrokontrolera zasilanego napięciem 5V, jest sterowanie paskami zasilanymi napięciem 12V. Można by oczywiście wykorzystać do tego celu tranzystory, jednak ze względu na sporą liczbę pól, którymi trzeba sterować (jak łatwo policzyć na powyższym zdjęciu na wyświetlaczu znajdują się 22 słowa + ja w swojej realizacji chcę dołożyć dodatkowe 4 pola, o których powiem później) – nasza płytka zawierałaby prawie tylko tranzystory.

Z pomocą przyjdą nam dwa proste układy. Pierwszy z nich to rejestr przesuwny. Większość z Was zapewne wie, „z czym to się je”, ale dla niewtajemniczonych dwa słowa komentarza. Za wikipedią:

Rejestr przesuwający – zwany też (nieprawidłowo) rejestrem przesuwnym, to rejestr zbudowany z przerzutników połączonych ze sobą w taki sposób, iż w takt impulsów zegarowych przechowywana informacja bitowa jest przemieszczana (przesuwana) do kolejnych przerzutników.”

Ups, człowiek uczy się całe życie – dobrze, niech będzie rejestr przesuwający. Jak w praktyce działa taki rejestr? Wykorzystany przez nas rejestr SIPO (Serial Input, Paralell Output – wejście szeregowe, wyjście równoległe)  CD4094BC posiada trzy linie wejściowe i 10 linii wyjściowych.

srpinout

Linie wejściowe to linia danych (DATA), linia zegarowa (CLOCK), zatrzask (STROBE) oraz pin o samo tłumaczącej się nazwie OUTPUT ENABLE, natomiast linie wyjściowe to w rzeczywistości 8 wyjść równoległych (Q1-Q8), oraz dwie linie (Q’s oraz Qs) o której więcej opowiem za chwilę.

W jaki sposób wykorzystywane są dane z tych pinów? Wyciągamy sobie tabelę prawdy z datasheetu i analizujemy.

srtt

Po pierwsze widzimy, że stan niski na pinie OUTPUT ENABLE powoduje przejście wszystkich wyjść rejestru w stan wysokiej impedancji.

Po drugie, podawanie informacji na piny wejściowe (DATA,CLOCK) przy niskim stanie wejścia STROBE nie spowoduje żadnej zmiany w układzie. Takie rozwiązanie pozwala wybrać nam, do którego rejestru chcemy „mówić” w danym momencie, dzięki czemu do jednej magistrali możemy podłączyć wiele rejestrów i niezależnie nimi sterować.

Po trzecie, gdy wejścia STROBE oraz OUTPUT ENABLE są w stanie wysokim, oraz na linii zegarowej wykryte zostanie zbocze narastające (przejście ze stanu niskiego do wysokiego) stan linii danych jest próbkowany (zapisywany) i (zgodnie z nazwą urządzenia) następuje przesunięcie. Co przesuwamy? Przesuwamy stany 8 wyjść urządzenia, tak że stan, który został pobrany z linii DATA zostaje przepisany na wyjście Q1, stan, który dotychczas był na wyjściu Q1 przechodzi na wyjście Q2, ten z Q2 na Q3 i tak dalej. Dzięki temu, po 8 cyklach zegara możemy mieć całkowicie nowe dane na wyjściach rejestru.

A co stało się z danymi, które były tam dotychczas? Wspomniałem o dodatkowych wyjściach Qs oraz Q’s. Te dwa wyjścia sprawiają, że rejestry przesuwające są tak popularne – stan tych wyjścia jest niejako pamięcią „9 bitu” – przy wpisaniu nowych danych, na to wyjście przechodzi stan, który dotychczas był na ostatnim wyjściu.

Co w tym rewolucyjnego? Podłączając to wyjście jako WEJŚCIE linii danych (DATA) kolejnego rejestru dane, które dotychczas były „gubione” – teraz zostaną przepisane do drugiego rejestru! Dzięki temu (w przypadku dwóch rejestrów 8 bitowych) wykorzystując dwie linie mikrokontrolera sterujemy 16 wyjściami! A nic nas nie powstrzymuje przed dalszym łączeniem ze sobą rejestrów – do drugiego możemy podłączyć trzeci, do trzeciego czwarty itd. Oczywiście należy przy tym pamiętać o czasie propagacji danych. Jeżeli podłączymy pojedynczy rejestr to aktualizacja wszystkich stanów jego wyjść zajmie nam 8 cykli zegara, ale jeżeli podłączymy takich rejestrów 8, to będziemy już potrzebowali tych cykli 64.

Należałoby jeszcze wyjaśnić różnicę pomiędzy pinami Qs a Q’s. Różnica ta jest bardzo subtelna – dotychczasowy stan z pinu Q8 zostaje przepisany do Qs przy narastającym zboczu linii zegara, a do Q’s – przy zboczu opadającym.

Ale dobrze, bo miały być tylko dwa słowa. Drugim z układów pomocniczych będzie scalony zestaw 8 tranzystorów w układzie Darlingtona. Kolejna trudna nazwa, kolejne dwa słowa komentarza.

Tym razem nie będę się aż tak rozwlekał, a więc w żołnierskich słowach – układ Darlingotna składa się z dwóch (lub więcej) tranzystorów połączonych ze sobą w następujący sposób (rysunek za wikipedią):

darlington

Takie połączenie pozwala na sterowanie sygnałami o dużych wartościach prądu przy podawaniu na bazę pierwszego tranzystora bardzo małego prądu. Prościej się nie da, jeżeli kogoś interesują zjawiska fizyczne i wzory, to odsyłam do wikipedii: http://pl.wikipedia.org/wiki/Uk%C5%82ad_Darlingtona

Wspomniane przeze mnie układy „pomocnicze” będą ze sobą połączone w taki sposób, że wyjścia rejestru przesuwającego będą wchodziły na bazę tranzystorów w układzie Darlingtona. Zastosujemy tranzystory NPN, a więc paski LED będą stale podłączone do napięcia zasilania 12V, natomiast to, które z nich będą zapalone będzie zależało od tego, które zostaną zwarte do masy przez układy Darlingtona.

Po przejrzeniu dostępnych układów Darlingtona wybrałem układy ULN28003APG, głownie ze względu na fakt, iż posiadają one 8 zestawów tranzystorów (dzięki czemu jeden ULN będzie przypadał na jeden rejestr przesuwający), a nie jak większość ULNów – 7.

Wystarczy tych opisów, czas na schemat układu:

schemat wordclock v2

Na schemacie, oprócz rzeczy oczywistych (mikrokontroler, stabilizator napięcia, rejestry, ULNy) widać także m.in. układ fotorezystora, oraz wtyczkę Jack. Spieszę z wyjaśnieniami.

Układ fotorezystora służyć będzie oczywiście do detekcji aktualnej jasności otoczenia, co w połączeniu z możliwością sterowania wyjściami rejestrów przesuwnych przy pomocy sygnału PWM podawanego na pin OUTPUT ENABLE pozwoli na dostosowywanie oświetlenia zegara.

Wtyczka Jack natomiast służyć będzie do sterowania zegarem. Przystępując do realizacji tego projektu planowałem umieścić w zegarze moduł Bluetooth w celu umożliwienia sterowania zegarem (przestawianie godziny, dostosowywanie jasności podświetlenia itp.), jednak ze względu na ceny modułów Bluetooth ostatecznie zarzuciłem to rozwiązanie.

Już miałem umieszczać na schemacie przyciski, gdy przypomniałem sobie, że po starej karcie telewizyjnej ostał mi się pilot, wraz z odbiornikiem (oczywiście na podczerwień). Pilot podłączany był do karty telewizyjnej właśnie przy pomocy złącza microJack, stąd jego obecność w projekcie. Jedyną trudnością było dojście do tego, w jaki sposób należy podłączyć poszczególne sygnały (+5V, GND oraz DATA) do wtyczki microJack. Na szczęście z pomocą przyszli nieocenieni użytkownicy elektrody, dzięki którym wiem, że sygnały należy podłączyć tak jak zaprezentowałem to na schemacie. Wyjaśnienia może wymagać podłączenie sygnału IR_CHECK – gniazdo microJack, które zakupiłem posiada dwa piny podłączone do końcówki wtyczki, co pozwala na wykrycie, czy wtyczka jest umieszczona w gnieździe. Postanowiłem wykorzystać to w swoim projekcie. Jako, że na końcówce wtyczki podawany jest sygnał +5V pin ten jest zwarty przez rezystor o dużej wartości (10kΩ) do masy układu. Odczytanie stanu pinu IR_CHECK w sytuacji, gdy wtyczka będzie niepodłączona da odczyt „0”, a gdy wtyczka będzie podłączona – „1”.

3 gniazda opisane jako „wyprowadzenia przyszłościowe” służą, jak sama nazwa wskazuje potencjalnemu przyszłościowemu rozwojowi projektu – rozważam dodanie do obudowy zegara dookoła diody (prawdopodobnie czerwone), które będą służyły jako sekundnik. Prawdopodobnie w tym celu powstanie kiedyś płytka drukowana, która będzie podłączona do tej przy pomocy tych pinów.

Płytka drukowana obwodu została wykonana przy pomocy termo transferu – po raz pierwszy użyłem w tym celu specjalnie zakupionej laminarki (popularna Lervia) zamiast żelazka. BARDZO polecam ten sposób – o ile z żelazkiem zawsze wychodziły mi jakieś niedociągnięcia, to tutaj nie ma o tym mowy – wszystko wychodzi pięknie za pierwszym podejściem.

IMG_20140127_195655

 

IMG_20140127_202020 - Kopia

Schemat płytki:

plytka wcv2

schemat płytki EAGLE [pdf]

Od razu chciałbym zaznaczyć – płytkę można by oczywiście dość mocno zmniejszyć – nie zrobiłem tego, ponieważ niniejszy projekt jest moją drugą wersją tego zegara, a wersja pierwsza miała płytkę tego właśnie rozmiaru i w obudowie zegara mam już przygotowane otwory montażowe pod płytkę w takim rozmiarze.

Przy użyciu bardzo ciekawego pluginu do programu EAGLE, pozwalającego na eksport płytki do programu Sketchup stworzyłem model 3D płytki, który pozwala z jednej strony sprawdzić, czy różne elementy płytki nie będą ze sobą kolidowały, a z drugiej – stworzyć np. taką animację procesu jej powstawania. Jeżeli będzie zainteresowanie tym tematem to mogę stworzyć jakiś artykuł opisujący z czym i jak to się je.

W celu dopełnienia części „fizycznej” projektu musiałem jeszcze stworzyć obudowę zegara. Nie będę się tutaj za bardzo rozwodził – myślę, że zdjęcia lepiej wyjaśnią cały proces niż opis słowny.

2013-01-11 01.36.54

2013-01-14 18.14.47

 

2013-01-14 18.45.40

 

2013-01-14 21.48.51

 

2013-01-15 00.19.02

 

IMG_20140129_002916

 

IMG_20130128_221656

 

IMG_20130130_170344

Obudowa wykonana jest w zdecydowanej większości z pleksiglasu (obudowa zewnętrzna, ścianki oddzielające poszczególne sekcje), jedynym elementem nie pleksiglasowym jest tył (element, na którym zamontowana jest płytka drukowana i do którego z drugiej strony przyklejone są paski LED) – został on wykonany z płyty pilśniowej pozyskanej z odzysku (oryginalnie płyta ta stanowiła tylną ściankę jakiejś starej szafki).

Największym wyzwaniem w budowie obudowy był front zegara. Pierwszy powód to konieczność umieszczenia na nim napisów, które podświetlone utworzą pożądany efekt. Front zegara został przeze mnie zaprojektowany w Corelu, a następnie wycięty w pobliskiej firmie poligraficzno/reklamowej na ploterze w czarnej folii samoprzylepnej. Usługa kosztowała mnie jakieś 20zł (łącznie z kosztem folii), co uważam za niezłą cenę. Drugi powód to pewna problematyczność z zamontowaniem frontu zegara. Z jednej strony musi to być zamocowane estetycznie, a z drugiej strony musi istnieć możliwość zdjęcia frontu w celu ewentualnej wymiany pasków LED/poprawienia jakiś połączeń. Ostatecznie zdecydowałem się na zrobienie z odpadków pleksi czegoś na kształt kątowników, które z jednej strony przyklejone są od tyłu do frontu zegara, a z drugiej przykręcane są do obudowy przy pomocy śrubek. Dokładniejsze zdjęcie tego rozwiązania:

IMG_20140129_002853

W tym momencie pozostało „tylko” stworzyć program do obsługi zegara. Program będzie składał się z paru głównych części, które muszą współpracować ze sobą.

Po pierwsze – obsługa magistrali I2C w celu uzyskiwania informacji od układu RTC.

Po drugie – obsługa magistrali SPI w celu podawania danych na rejestry przesuwające.

Po trzecie – obsługa fotorezystora oraz podawanie sygnału PWM sterującego jasnością wyświetlacza.

I po czwarte – obsługa pilota na podczerwień.

Pierwsze dwie części będą stosunkowo proste ze względu na fakt, że obsługa magistrali I2C (lub, zamiennie TWI) oraz SPI jest zaimplementowana w atmedze sprzętowo. W Arduino istnieją dwie klasy, które służą do obsługi tych magistral. W przypadku magistrali I2C klasa ta to „Wire” (http://arduino.cc/en/reference/wire), a w przypadku SPI – klasa „SPI” (http://arduino.cc/en/Reference/SPI). Ich obsługa jest naprawdę prosta i bardzo dobrze opisana na stronie Arduino przy pomocy prostych przykładów.

Część trzecia ograniczy się do odczytu wartości z przetwornika ADC, a następnie zmapowaniu jej na wartość, która zostanie podana przez PWM na odpowiedni pin (połączony z pinem OUTPUT_ENABLE rejestrów przesuwających).

Część czwarta została zrealizowana przeze mnie od podstaw. Mogłem oczywiście zastosować jedną z wielu gotowych bibliotek do Arduino pozwalających na odczytywanie kodów z pilotów na podczerwień, ale jako, że żadna z bibliotek nie spełniała do końca moich założeń, oraz ze względu na fakt, że zawsze lubiłem wyzwania – postanowiłem napisać obsługę pilota od podstaw. Kod obsługi jest licznie opatrzony komentarzami, przedstawię wobec tego tylko ogólną zasadę działania.

Zanim opiszę jak dokonałem implementacji, napiszę może jaki protokół implementuję. Pilot, który wygrzebałem z szuflady okazał się nadawać komunikaty w protokole NEC. Protokół ten jest szeroko opisany w Internecie, przytoczę tylko parę charakterystycznych cech:

– ramka danych (cała) zawsze trwa tyle samo czasu
– zarówno adres urządzenia nadającego (pilota) jak i przesyłany rozkaz jest nadawany dwukrotnie – raz normalnie, a raz zanegowany
– bit „0” od bitu „1” rozróżniany jest przez czas trwania stanu niskiego – bit „0” to stan wysoki przez 560us z następującym stanem niskim o czasie 560us, a bit „1” to 560us stanu wysokiego, po którym następuje 1690us stanu niskiego

(oczywiście stan niski i wysoki to określenia umowne – stan niski to brak nadawania, a stan wysoki – ciągłe nadawanie sygnału o częstotliwości 38kHz)

Najważniejsza część kodu wykonywana jest w przerwaniu timera, które wywoływane jest co ok. 25ms. Procedura przerwania sprawdza jaki jest aktualny stan odczytany z odbiornika i (w przypadku gdy aktualny stan jest różny od poprzedniego) zapisuje czas trwania poprzedniego stanu do tablicy. Procedura liczy także odebrane stany i po odebraniu odpowiedniej ilości, wystawia flagę informującą o odebraniu całego komunikatu.

Po „zauważeniu” tej flagi przez program wywoływana jest funkcja, która ma za zadanie na podstawie tablicy zawierającej czasy poszczególnych stanów na linii odczytać zawarty w przekazie komunikat. Funkcja sprawdza najpierw każdy stan, czy odpowiada on standardom protokołu (wszystkie wartości przyjęte są z 20% tolerancją). Jeżeli odebrane czasy są faktycznie ramką protokołu NEC – następuje ich odczytanie, a następnie dwustopniowa weryfikacja. Pierwszą sprawdzaną rzeczą jest poprawność komunikatu – dzięki faktowi, iż adres i rozkaz jest nadany najpierw normalnie, a potem zanegowany – odpowiednie porównanie tych wartości pozwala sprawdzić, czy dane nie zostały przekłamane przez jakieś zakłócenia. Drugim stopniem weryfikacji jest nadawca komunikatu – program odrzuca wszystkie komunikaty w standardzie NEC, które nie pochodzą z mojego pilota (który przedstawia się adresem 0xC0). Ostatecznie – funkcja zwraca odczytany rozkaz, który jest następnie interpretowany przez program.

Ostateczny kod programu, opatrzony obszernymi komentarzami przedstawia się następująco:

Zamieszczam także filmik prezentujący pracę zegara. Wgrany jest tutaj program, w którym jedna minuta została przyspieszona do 1 sekundy, co pozwala zaobserwować dokładnie w jaki sposób wyświetlany jest czas na zegarze.

https://www.youtube.com/watch?v=UmP2rT1qSX8

Ocena: 4.24/5 (głosów: 103)

Podobne posty

39 komentarzy do “Zegar słowowy – word clock

Odpowiedz

anuluj

Masz uwagi?