Witam, to mój pierwszy wpis na majsterkowie, choć czytam stronę regularnie od czasów, gdy była jeszcze na starym adresie i przyznam, że nie raz skorzystałem z ciekawych pomysłów Użytkowników :)
Z zawodu jestem informatykiem i zawsze chciałem mieć zegar binarny (oprócz tego zbudowanego na lampach nixie, ale i na niego czas przyjdzie ;)), ale jakoś nigdy nie znalazłem takiego, który by spełniał moje oczekiwania, a przy tym nie kosztował kroci.
Jako że na gwiazdkę otrzymałem Arduino UNO Starter Kit , to i zacząłem coś na nim robić. Później dokupiłem inne zabawki do tego i w końcu wpadłem na pomysł, aby zrealizować jakiś konkretny projekt. Wybór padł właśnie na zegar binarny. Przedsięwzięcie wydawało się proste i w sumie takie też było. Zanim przejdziemy do meritum sprawy, wyjaśnię zasadę działania zegara binarnego.
Na początku chciałem zaznaczyć, że z uwagi na fakt, iż ma być to prosty zegar binarny, bez zbędnych komplikacji w postaci ekspanderów czy też rejestrów, będzie on wyświetlał godziny i minuty, bez sekund, z uwagi na ograniczoną liczbę wejść/wyjść na Arduino UNO/mini. Dodam także możliwość wyświetlania daty w postaci miesięcy i dni.
Zasada działania
Zdecydowałem się na zegar, który będzie wyświetlał godzinę w kodzie BCD (ang. Binary-Coded Decimal czyli dziesiętny zakodowany dwójkowo), z uwagi na prostsze rozszyfrowanie godziny:)
Wygląda to mniej więcej tak:
Godziny Minuty Sekundy
——- ——- ——-
8 | 0 0 1
4 | 0 0 1 1 0
2 | 0 0 1 1 0 0
1 | 1 0 1 1 0 1
============================
dziesiętnie: 1 0 : 3 7 : 4 9
czyli jak widać, żadnej filozofii nie ma. Do zapisu godzin, minut i sekund wykorzystuje się po dwie kolumny – jedną na wartość dziesiątek, a drugą na jedności. Wiersze zaś stanowią potęgi cyfry 2 (jak to się odbywa w systemie binarnym): 2^0, 2^1, 2^2 oraz 2^3, co nam daje odpowiednio 1, 2, 4 oraz 8. Następnie sumujemy cyfry w kolumnach i możemy już odczytać godzinę :) Może to trochę zagmatwane, ale na przykładzie zaraz szybko się wyjaśni, że jednak nie.
Przykład:
Trochę kropek i co z nich wyczytać? Ano godzinę, minuty i sekundy. Zaczynamy od lewej strony.
Dwie pierwsze kolumny dają nam godzinę. W kolumnie dziesiątek godziny zapalone jest jedynie dolne kółko, które reprezentuje wartość 1. W kolumnie jedności godziny podświetlone jest kółko dolne – wartość 1 oraz czwarte od dołu, którego wartość to 8. Po zsumowaniu mamy wartość jednostki godziny 9. Pełna godzina zatem to 19.
Analogicznie rozprawiamy się z minutami. W kolumnie dziesiątek sumujemy 1 i 2 co nam daje 3, a w kolumnie jednostek nie mamy nic, czyli 0. W sumie mamy minut 30.
Ostatnie dwie kolumny to sekundy. W kolumnie dziesiątek mamy 4, a w jednostkach 6, czyli 46.
Pełna godzina rozszyfrowana z kilkunastu kółeczek to: 19:30:46.
Czy aby na pewno dobrze policzyliśmy? Sprawdźmy:
No i zgadza się, mówiłem, że to banalne:)
Znamy teorie czas na praktykę
Co nam będzie potrzebne:
- Arduino, ja użyłem do prototypowania UNO a do samego zegara Mini Pro
- zegar czasu rzeczywistego RTC na I2C
- diody LED, ja użyłem 13 niebieskich matowych 5 mm oraz 10 czerwonych, także 5 mm
- rezystorki, użyłem 23 rezystory 150 Ohm
- ramka na zdjęcie, użyłem takiej o wymiarach 10 cm x 15 cm
- obudowa uniwersalna, użyłem o wymiarach 7,5 cm x 6 cm
- płytkę uniwersalną o wymiarach 6cm x 4cm
- kable
- gniazdo do zasilacza
- zasilacz, użyłem 5 V 1000 mA
- zadrukowana folia, który nam posłuży za cyferblat zegara oraz kopia na papierze
- sklejka, mdf, płyta paździerzowa, z panelu podłogowego o wymiarach takich jak tył ramki na zdjęcie
- opcjonalnie płytka stykowa do prototypowania oraz kable do niej
- konwerter USB – RS, ja się wyposażyłem w model PL2303 Prolific oraz zmontowałem kabelek do niego
- gniazda na goldpiny
Prototyp na płytce stykowej
Zanim zaczniemy lutowanie i składanie całości, warto sprawdzić, czy nasz projekt będzie działał, tak jak sobie założyliśmy. Arduino, RTC, płytka stykowa, garść kabelków, diody, rezystory i łączymy wszystko w jedno według schematu:
U mnie wyglądało to tak:
Kod programu
Kod programu nie jest skomplikowany. Musimy pamiętać o dorzuceniu bibliotek <Time.h> oraz <DS1307RTC.h> do katalogu libraries w miejsu instalacji aplikacji Arduino.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
#include <Time.h> #include <Wire.h> #include <DS1307RTC.h> #include <Timer.h> int munit,hunit, dayit, monthit; void TimeLED () { munit = minute()%10; hunit = hour()%10; //minutes units if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) { digitalWrite(1, HIGH);} else { digitalWrite(1,LOW);} if(munit == 2 || munit == 3 || munit == 6 || munit == 7) {digitalWrite(2, HIGH);} else {digitalWrite(2,LOW);} if(munit == 4 || munit == 5 || munit == 6 || munit == 7) {digitalWrite(3, HIGH);} else {digitalWrite(3,LOW);} if(munit == 8 || munit == 9) {digitalWrite(4, HIGH);} else {digitalWrite(4,LOW);} //minutes if((minute() >= 10 && minute() < 20) || (minute() >= 30 && minute() < 40) || (minute() >= 50 && minute() < 60)) {digitalWrite(5, HIGH);} else {digitalWrite(5,LOW);} if(minute() >= 20 && minute() < 40) {digitalWrite(6, HIGH);} else {digitalWrite(6,LOW);} if(minute() >= 40 && minute() < 60) {digitalWrite(7, HIGH);} else {digitalWrite(7,LOW);} //hour units if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) {digitalWrite(8, HIGH);} else {digitalWrite(8,LOW);} if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) {digitalWrite(9, HIGH);} else {digitalWrite(9,LOW);} if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) {digitalWrite(10, HIGH);} else {digitalWrite(10,LOW);} if(hunit == 8 || hunit == 9) {digitalWrite(11, HIGH);} else {digitalWrite(11,LOW);} //hour if(hour() >= 10 && hour() < 20) {digitalWrite(12, HIGH);} else {digitalWrite(12,LOW);} if(hour() >= 20 && hour() < 24) {digitalWrite(13, HIGH);} else {digitalWrite(13,LOW);} } void DateLED() { monthit = month()%10; dayit = day()%10; //days units if(dayit == 1 || dayit == 3 || dayit == 5 || dayit == 7 || dayit == 9) { digitalWrite(1, HIGH);} else { digitalWrite(1,LOW);} if(dayit == 2 || dayit == 3 || dayit == 6 || dayit == 7) {digitalWrite(2, HIGH);} else {digitalWrite(2,LOW);} if(dayit == 4 || dayit == 5 || dayit == 6 || dayit == 7) {digitalWrite(3, HIGH);} else {digitalWrite(3,LOW);} if(dayit == 8 || dayit == 9) {digitalWrite(4, HIGH);} else {digitalWrite(4,LOW);} //days if((day() >= 10 && day() < 20) || (day() >= 30 && day() < 40) || (day() >= 50 && day() < 60)) {digitalWrite(5, HIGH);} else {digitalWrite(5,LOW);} if(day() >= 20 && day() < 40) {digitalWrite(6, HIGH);} else {digitalWrite(6,LOW);} if(day() >= 40 && day() < 60) {digitalWrite(7, HIGH);} else {digitalWrite(7,LOW);} //months units if(monthit == 1 || monthit == 3 || monthit == 5 || monthit == 7 || monthit == 9) {digitalWrite(8, HIGH);} else {digitalWrite(8,LOW);} if(monthit == 2 || monthit == 3 || monthit == 6 || monthit == 7) {digitalWrite(9, HIGH);} else {digitalWrite(9,LOW);} if(monthit == 4 || monthit == 5 || monthit == 6 || monthit == 7) {digitalWrite(10, HIGH);} else {digitalWrite(10,LOW);} if(monthit == 8 || monthit == 9) {digitalWrite(11, HIGH);} else {digitalWrite(11,LOW);} //months if(month() >= 10 && month() < 20) {digitalWrite(12, HIGH);} else {digitalWrite(12,LOW);} if(month() >= 20 && month() < 24) {digitalWrite(13, HIGH);} else {digitalWrite(13,LOW);} } void DateNOLED() { digitalWrite(0,LOW); digitalWrite(1,LOW); digitalWrite(2,LOW); digitalWrite(3,LOW); digitalWrite(4,LOW); digitalWrite(5,LOW); digitalWrite(6,LOW); digitalWrite(7,LOW); digitalWrite(8,LOW); digitalWrite(9,LOW); digitalWrite(10,LOW); digitalWrite(11,LOW); digitalWrite(12,LOW); } void setup() { setSyncProvider(RTC.get); pinMode(1, OUTPUT);pinMode(2, OUTPUT);pinMode(3, OUTPUT);pinMode(4, OUTPUT);pinMode(5, OUTPUT); pinMode(6, OUTPUT);pinMode(7, OUTPUT);pinMode(8, OUTPUT);pinMode(9, OUTPUT);pinMode(10, OUTPUT); pinMode(11, OUTPUT);pinMode(12, OUTPUT);pinMode(13, OUTPUT); } void loop() { TimeLED(); delay(60000); for (int i=0; i<5; i++) { DateLED(); delay(300); DateNOLED(); delay(300); } } |
Zanim wrzucimy nasz kod na Arduino musimy ustawić czas. Aby to zrobić klikamy w oprogramowaniu Arduino – Plik->Przykłady->DS1307RTC->SetTime, a następnie wgrywamy kod na Arduino. Od tej pory możemy się cieszyć aktualnym czasem.
Na początku deklarujemy zmienne munit (która będzie jednostkami minut), hunit (jednostki godzin), dayit (jednostki dni), monthit (jednostki miesięcy). Dziesiątki dni, miesięcy, godzin oraz minut wyciągniemy bezpośrednio z biblioteki.
Następnie mamy funkcję TimeLED, w której oprócz definicji wartości munit i hunit mamy zdefiniowane przedstawienie czasu, sterując diodami poprzez sygnały wysokie na wyjściach/wejściach cyfrowych. Nie ma za bardzo co się tutaj rozpisywać, bo jest to po prostu reprezentacja wartości dziesiętnej cyfry na wartość binarną.
Dalej jest funkcja DateLED, która jest identyczna z powyższą, tyle tylko że dotyczy daty zamiast czasu.
Kolejna funkcja do DateNOLED, która po prostu wygasza wszystkie diody sygnałem niskim.
Funkcja loop wyświetla nam czas i datę, a robi to w ten sposób, że czas wyświetlany jest w sposób ciągły, ale co 60 sekund, wyświetlana jest data, która się pojawia pięć razy migając.
No i to byłoby tyle jeśli chodzi o kod :)
Wrzucamy kod na Arduino zarówno UNO jak i mini Pro i sprawdzamy. Jeśli działa nam na Uno to podłączamy mini Pro i sprawdzamy.
Meritum sprawy – projekt
Skoro udało nam się to zrobić na płytce stykowej, to czas abyśmy przeszli do właściwego projektu. Do niego oprócz tego co widoczne na powyższych rysunkach, potrzebne nam będą diody do podświetlenia napisów “godziny”, “minuty” oraz “1”, “2”, “4” oraz “8”, aby łatwiej się odczytywało godzinę.
Schemat:
Na początku warto narysować i wydrukować nasz cyferblat. Jedną kopie w postaci papierowej oraz na folii, ale o tym później. Ja zdecydowałem się na taki układ, jak ten zaprezentowany poniżej. Dodatkowo dla ułatwienia w miejsce napisów godzina, minuty oraz cyfr: 8,4,2,1 wrzuciłem kółka, aby łatwiej się wierciło.
Na początek potrzebna nam będzie płytka mdf/drewniana/paździerzowa, z której wycinamy prostokąt o wymiarach naszej ramki. Mój miał 10cm na 15cm i wykonałem go z płyty mdf, która miała 5mm grubości, co jest o tyle ważne, że nie diody nie wystają poza nią. Następnie przyklejamy do płytki nasz cyferblat i wiercimy w odpowiednich miejscach otwory. Nie wygląda przyjemnie, co?
Następnie wkładamy w otwory diody: niebieskie dla wartości czasu oraz czerwone dla podświetlenia napisów i zakrzywiamy nóżki, aby było łatwo je połączyć.
Kolejną czynnością jest lutowanie wspólnych katod oddzielnie dla diod niebieskich i czerwonych. Później do każdej anody lutujemy rezystor, a dodatkowo diody czerwone łączymy równolegle.
Następnie do każdej anody niebieskiej diody lutujemy kabelek (im więcej kolorów mamy tym lepiej) a katody diod niebieskich wszystkie razem do jednego kabelka. Do czerwonych diod potrzebujemy dwa kable: do wspólnych katod i wspólnych anod.
PS. Wiem, że dałem ciała z kolorami kabli, ale w moim podręcznym pęczku brakło podstawowych barw ;p
Kiedy mamy już wszytko polutowane na płycie, to możemy połączyć obudowę uniwersalną z plecami ramki na zdjęcia. Ja je połączyłem przy pomocy wkrętów do drewna, bo takowe miałem. Następnie w obu tych rzeczach wyciąłem na środku taki otwór, ażeby dało się przezeń przeciągnąć kable. Do tego celu, tradycyjnie użyłem wiertarki i nawierciłem po obwodzie kwadratu otwory, a następnie wyłamałem wnętrze. Nie wygląda to pięknie ale i tak tego nie widać.
Dalej wiercimy otworek w obudowie uniwersalnej i mocujemy w nim gniazdo do zasilacza.
Kiedy mamy już gotową tą część, możemy przejść do polutowania Arduino pro mini i zegara czasu rzeczywistego, a właściwie gniazd goldpinowych (aby dało się w przyszłości zdemontować obie rzeczy) do nich do płytki uniwersalnej, a następnie dolutowanie do niej kabelków od diod.
Mając już prawie wszystko polutowane, musimy zasilić nasze Arduino oraz diody do podświetlenia. Ja w Arduino użyłem wejść VCC i GND (tych samych, które są wykorzystywane przez podłączenia USB), z uwagi na fakt zasilania napięciem 5V. Gdyby było wyższe trzeba byłoby skorzystać z pinów RAW i GND. Zatem połączamy kabelek z VCC oraz anod diod podświetlających do plusa gniazda zasilacza oraz GND i katod do minusa w gnieździe. Testujemy, działa i przechodzimy dalej.
Teraz możemy już zamknąć obudowę i przykręcić plecki ramki na zdjęcia do naszej płyty mdf. Użyłem do tego celu wkrętów do drewna o długości 10 mm. Należy pamiętać, aby pomiędzy obiema powierzchniami zostawić odległość kilku milimetrów. Następnie obie płyty po obwodzie, aby nie było szpary obwijamy czarną izolacją i całość prezentuje się już całkiem nieźle.
Teraz pozostaje nam tylko dołączenie cyferblatu wydrukowanego na folii. Mała uwaga odnośnie tego zabiegu. Zanim znalazłem pożądany efekt (taki, aby diody za bardzo nie prześwitywały przez z część folii) trochę się nakombinowałem. Dlatego też rada dla Was, abyście drukując taką folię na drukarce laserowej, przedrukowali ją kilka razy. U mnie pięciokrotne przedrukowanie dało pożądany efekt.
Wkładamy folię na szybę, dokładamy resztę doń i mamy już gotowy zegar. Prawda że łatwe? :)
Osobiście efekt mojej pracy przypadł mi do gustu i spodobał się rodzinie i znajomym. Pewnie przy włożeniu odrobiny więcej wysiłku, zrobicie to bardziej estetyczniej i lepiej, ale tak jak wspomniałem ten wykonany przeze mnie mnie odpowiada :)
Ten zegarek tak spodobał się mojej małżonce, że zapewne oddam jej go, a sobie zrobię coś podobnego, ale już bardziej złożonego, z większą ilością funkcjonalności: sekundy, może budzik, może beeper, może na diodach rgb? Wszystko zależy od tego ile znajdę czasu, o który coraz trudniej.
Na koniec chciałem podziękować.
Przede wszystkim Wam, czytelnikom, że dotrwaliście do końca i przeczytaliście moje wypociny.
Następnie mojej żonie, która wykonała projekt tarczy zegarka oraz zawsze mnie wspiera w moich wariactwach.
Dalej koledze Adamowi, do którego zawsze można zwrócić się z problemem i pomaga.
No i tacie, który jest elektrykiem/elektronikiem z zamiłowania i zawodu, więc żaden problem dla niego straszny nie jest.
Czekam na Wasze komentarze i pytania :)
Bardzo ładny projekt i bardzo estetyczne wykonanie.
Niestety oceniłem na piątkę przed zalogowaniem się jako Autor, także nie miałem okazji skorzystać ze swojego decydującego prawa głosu, ale jestem spokojny o losy tego wpisu :)
Sebastian zna się na zegarach, skoro mówi że jest ok, to jest ok ;)
Opis dobry, zdjęcia dobre i schemat nie jest kolorowanką. Kwestia koloru diod jest oczywiście kwestią indywidualną, chociaż do niebieskich pałam szczerą nienawiścią. Ale to kosmetyka.
Ja mam odwrotnie, tam gdzie mogę pcham niebieskie diody ;p
A ja mam pytanie w sprawie około zegarowych w Arduino. Czy próbował ktoś z was stworzyć odbiornik radiowego wzorca czasu – chodzi mi o tą radiową synchronizację czasu z Niemiec(?)?
z synchronizacji radiowej nie korzystałem, ale tu na majsterkowie możesz przeczytać artykuł w którym synchronizuję zegar z wzorcem internetowym
Mam pytanie: mój RTC z eBaya przyspiesza o ok. sekundę na godzinę. Muszę go więc cofać o kilka minut co około tydzień. Żyję z tym, ale mnie to trochę denerwuje ;) Zaobserwowaliście takie coś u siebie?
Prawda, też to zauważyłem. Będę musiał pokombinować z odjęciem tych dodatkowych sekund ;/
Five na start za to, że jest to zegar binarny :) Też się zbieram do budowy jednego… ponad rok temu był projekt w Elektronice Praktycznej lub Elektronice dla Wszystkich na Atmega8.
Nie wiem czy czegoś nie pokręciłem. ale chyba 3 dioda w kolumnie dziesiatek godzin jest nie potrzebna
Jeśli chodzi Ci o te obrazki, na których wytłumaczona jest zasada działania, to faktycznie, zbędna jest tam trzecia dioda :)
Świetny pomysł! Tylko jeśli chodzi o utykanie Arduino w takim projekcie… to ma być raczej instalacja stała, a Arduino jest z założenia układem do prototypowania, cena też nie zachęca do zamykania go na stałe w jednym urządzeniu, w którym sprawdziłby się równie dobrze o wiele prostszy układ… chętnie przeczytałbym rozwinięcie o przygotowanie docelowej płytki i odzyskanie Arduino ze środka. ;)
Kto bogatemu zabroni? :P
Sam z lenistwa często wsadzam całe Arduino do projektów. Teoretycznie plan mam zawsze taki, że później wsadzę tam sam µC, ale najczęściej na planie się kończy. No chyba, że zabraknie mi Arduino (mam 3), to wtedy skądś wyciągam i wrzucam tam samego procka ;)
No jeśli to jest jedynie odkładanie w czasie wymiany Arduino na dedykowaną płytkę (do momentu, kiedy Arduino będzie Ci znowu potrzebne), to jestem w stanie Ci to wybaczyć. ;)
Naprawdę 23 zł to dużo za odpowiednik arduino pro mini? Nie trzeba brechtać się z bootloaderem, robieniem obstawy dla samej atmegi. Dostajemy płyteczkę, którą umieszczamy w projekcie i nic nas to nie boli :) Jak się arduino zepsuje albo będzie potrzebne gdzieś indziej to siup z gniazd golpinowych i po sprawie :)
Dla laika takiego jak ja to jest wygodniejsze :)
23 zł? Wow, potaniało to wszystko, aż miło. :3
Czy Arduino będzie “pamiętało” wgrany wcześniej do niego przez USB program? Bo jak widzę zasilanie idzie tu z sieci, a nie z komputera?
Jedno pytanie, a która dioda jest która?
Może nie dokładnie, ale chciałbym wiedzie np. z portu D1 to którą diodą jest.