[107] Budujemy ze zrozumieniem - elektroniczny budzik cz. 1
![[107] Budujemy ze zrozumieniem - elektroniczny budzik cz. 1](/_next/image?url=https%3A%2F%2Farduino.pl%2Fimgproxy%2FhC76OStgW7m9JO0MNrqeqdb3QX1g2i2Zs30TU3Smi6I%2Ff%3Awebp%2Fw%3A1200%2FbG9jYWw6Ly8vaW1hZ2VzLzAtNjgzLzFlODRiLzA3NjgzLzAtNjgzMWU4NGIwNzY4MzI5MTAyNTY2MS5wbmc%3D.webp&w=3840&q=75)
Zegary, budziki, stopery i wszelkie wariacje na ten temat, zawsze były ulubionym projektem młodych elektroników, bo wdzięcznym w uruchamianiu, umiarkowanie skomplikowanym i przede wszystkim użytecznym – zwłaszcza jeśli zapewnimy zegarkowi kilka funkcji niedostępnych w pokładowym czasomierzu smartfona czy sprzętowym odpowiedniku ze sklepu. Dlatego najbliższych artykułach będziemy się zajmować się takim urządzeniem, ale w kilku odmianach i z udziałem różnych elementów wykonawczych, za każdym razem dogłębnie analizując każdy krok naszych działań.
I jak zwykle, mimo że bohaterem będzie zegar, nie mniej istotne będą wątki drugoplanowe. A będą to: porady warsztatowe przy dobieraniu elementów, wykorzystanie platformy wirtualnych projektów, zwiększanie dokładności zegara, zasilanie akumulatorem i pewno pojawią się inne pomysły, o których w tej chwili nie mam pojęcia. Zaczniemy więc od początku: wyboru medium wskazującego czas.

I tu można przebierać: od pięknych VFD po elektroniczny papier. Pierwsze są prądożerne i mają ograniczoną trwałość. Elektroniczny papier jest ślamazarny i nie widać go w ciemnościach. Są jeszcze Nixie, wyświetlacze z żarników i samych żarówek oraz różne dziwne retro świecidełka rodem z misji Apollo. Lecz to wszystko ma jedną wadę: potrzebuje na tyle dużo energii, że musi być zasilane z sieci. No i kosztuje majątek. Można byłoby się zastanowić nad LCD. Wyświetlaczy takich jest obecnie multum, w większości jednak jako źródło cyferek zegara nie są tak miłe jak ledy. OLED-y mają świetny kontrast, ale szybko się zużyją, jeśli będą świecić bez przerwy. Zostają więc diody świecące w postaci wyświetlaczy siedmiosegmentowych.
Te teoretycznie także nie nadają się do pracy z bateriami, ale nie do końca. Na rynku nastąpiła rewolucja, jeśli chodzi o wydajność ledów i zielone bądź niebieskie cyferblaty świecą wyraźnie już przy mikroamperach. Stosując pewien fortel możemy stworzyć zegar pracujący tylko z akumulatora – ale o tym później. Na razie skupmy się na podstawach. Na temat istoty wyświetlaczy siedmiosegmentowych pisałem już kiedyś.
Skoro wybraliśmy medium, stwórzmy sobie platformę testową, bo znając życie, to nie będzie ostatni projekt używający takich wskaźników. W zakamarkach szuflady znalazłem taką płytkę.

Ma ona tę zaletę, że wytrasowano tutaj ścieżki pod dwa podwójne wyświetlacze pracujące w multipleksie. Czyli każdy segment jest połączony z każdym segmentem sąsiada, a wspólne anody są wyprowadzone na cztery osobne wejścia.

Zamiast wyświetlaczy wlutowałem tam gniazda pod goldpiny. Dzięki temu będę mógł testować różne elementy, obserwując efekt wizualnie i przede wszystkim dobierać takie, które są wystarczająco jasne. Oczywiście taką płytkę można sobie zrobić samemu albo poświęcić na stałe płytkę stykową, krosując odpowiednie wyprowadzenia diod ze sobą. Moduł ten będzie nam służył podczas uruchamiania zegara. O wyświetlaczach multipleksowych wspominałem już kiedyś, więc samej idei nie będę przypominał, odsyłając zainteresowanych do artykułu. Powstał wtedy także szkic, raczej szkoleniowy, ale robiący co trzeba, czyli prezentujący zegar na wyświetlaczu kalkulatora z Brdy. Pożyczę sobie teraz owo dzieło, by mieć coś na początek, co nam się tutaj przyda choćby do przetestowania połączeń.

I tutaj – na chwilę odkładamy naszą płytkę testową i udajemy się na stronę Wokwi. O tym symulatorze Arduino także kiedyś pisałem, więc dziś go po prostu użyjemy. Po co? Żeby po pierwsze rozplanować sobie co gdzie podłączyć zanim zrobimy to naprawdę. A po drugie – dostaniemy gratisową dokumentację. No, może trochę infantylną, bo w postaci takiego obrazka, ale takie dziś mamy standardy. Poza tym lepsza taka niż żadna, a jak znam życie, niewielu zmusza się do narysowania schematu, nawet tak prostego, ale jednak przydatnego, zwłaszcza po jakimś czasie, gdy coś się nam rozłączy i będziemy się zastanawiać skąd się urwało.
Wokwi oferuje sporo elementów: oprócz samej platformy, także wyświetlacz, drobnicę i możliwość pracy z bibliotekami. Toteż wszystko ładnie ruszyło i zegarek mierzył czas – choć tylko na ekranie komputera.
#include <TimeLib.h> // To jest biblioteka obsługi zegara.
const byte segmentA = 5; // Adresy portów kolejnych segmentów: od A do G oraz dwukropek.
const byte segmentB = 6;
const byte segmentC = 9;
const byte segmentD = 10;
const byte segmentE = 11;
const byte segmentF = 12;
const byte segmentG = 13;
const byte dwukropek = 3;
const byte wspolne1 = A0; // Adresy portów wspólnych wyprowadzeń kolejnych wyświetlaczy.
const byte wspolne2 = A1;
const byte wspolne3 = A2;
const byte wspolne4 = A3;
const byte pstryczekGodzina = 4; // Adres pstryczka zmiany godzin.
const byte pstryczekMinuta = 7; // Adres pstryczka zmiany minut.
const byte tablica[11] = {
B1000000, // 0, Tablica zawierająca wzorce znaków wyświetlacza siedmiosegmentowego.
B1111001, // 1, Schemat: G-F-E-D-C-B-A
B0100100, // 2
B0110000, // 3
B0011001, // 4
B0010010, // 5
B0000010, // 6
B1111000, // 7
B0000000, // 8
B0010000, // 9
B1111111, // spacja
};
byte x; // Zmienna pomocnicza.
void setup() {
pinMode(segmentA, OUTPUT); // Deklaruj porty kolejnych segmentów wyświetlaczy.
pinMode(segmentB, OUTPUT);
pinMode(segmentC, OUTPUT);
pinMode(segmentD, OUTPUT);
pinMode(segmentE, OUTPUT);
pinMode(segmentF, OUTPUT);
pinMode(segmentG, OUTPUT);
pinMode(dwukropek, OUTPUT);
pinMode(wspolne1, OUTPUT); // Deklaruj porty wspólnych wyprowadzeń kolejnych wyświetlaczy.
pinMode(wspolne2, OUTPUT);
pinMode(wspolne3, OUTPUT);
pinMode(wspolne4, OUTPUT);
pinMode(pstryczekGodzina, INPUT_PULLUP); // Deklaruj porty pstryczków jako wejścia podciągnięte wewnętrznie do wysokiego stanu.
pinMode(pstryczekMinuta, INPUT_PULLUP);
setTime(23, 59, 57, 01, 01, 2000); // Ustaw przykładowy czas.
digitalWrite(dwukropek, HIGH); // Włącz dwukropek.
}
void loop() {
wyswietl(); // Wyświetl czas.
if (digitalRead(pstryczekGodzina) == LOW) { // Jeśli wciśnięto pstryczek zmiany godzin, to...
x = hour(); // Pobierz aktualną godzinę.
x++; // Zwiększ jej wartość.
if (x > 23) { // Jeśli przekroczono maksymalną legalną wartość, to...
x = 0; // Zeruj jej wartość.
}
setTime(x, minute(now()), 0, 01, 01, 2000); // Ustaw nową wartość godzin.
while (digitalRead(pstryczekGodzina) == LOW) {} // Czekaj, aż pstryczek pozostanie puszczony.
}
if (digitalRead(pstryczekMinuta) == LOW) { // Jeśli wciśnięto pstryczek zmiany minut, to...
x = minute(); // Pobierz aktualną minutę.
x++; // Zwiększ jej wartość.
if (x > 59) { // Jeśli przekroczono maksymalną legalną wartość, to...
x = 0; // Zeruj jej wartość.
}
setTime(hour(now()), x, 0, 01, 01, 2000); // Ustaw nową wartość minut.
while (digitalRead(pstryczekMinuta) == LOW) {} // Czekaj, aż pstryczek pozostanie puszczony.
}
}
void wyswietl() { // Procedura wyświetlająca czas.
x = minute() % 10; // Młodsza cyfra minut.
segmenty();
digitalWrite(wspolne4, HIGH);
wygas();
x = minute() / 10; // Starsza cyfra minut.
segmenty();
digitalWrite(wspolne3, HIGH);
wygas();
x = hour() % 10; // Młodsza cyfra godzin.
segmenty();
digitalWrite(wspolne2, HIGH);
wygas();
x = hour() / 10; // Starsza cyfra godzin.
if (x == 0) { // Wyświetl spację, jeśli godzina < 10
x = 10; // Pod adresem dziesiątym znajduje się spacja.
}
segmenty();
digitalWrite(wspolne1, HIGH);
wygas();
}
void segmenty() { // Zaświeć segmenty według wzorców z tablicy.
digitalWrite(segmentA, bitRead(tablica[x], 0));
digitalWrite(segmentB, bitRead(tablica[x], 1));
digitalWrite(segmentC, bitRead(tablica[x], 2));
digitalWrite(segmentD, bitRead(tablica[x], 3));
digitalWrite(segmentE, bitRead(tablica[x], 4));
digitalWrite(segmentF, bitRead(tablica[x], 5));
digitalWrite(segmentG, bitRead(tablica[x], 6));
}
void wygas() { // Wyłącz wszystkie wyświetlacze.
delayMicroseconds(2500); // Opóźnienie - dobierz, by nie było widać mrugania, a jasność była wystarczająco duża
digitalWrite(wspolne1, LOW);
digitalWrite(wspolne2, LOW);
digitalWrite(wspolne3, LOW);
digitalWrite(wspolne4, LOW);
}
Wobec oryginalnego projektu usunąłem pozycje sekund, bo zdecydowałem się zbudować zegar czteropozycyjny. No i należało odwrócić logikę, bo tam mieliśmy wyświetlacz ze wspólną katodą, natomiast dzisiejszym semistandardem są wyświetlacze ze wspólną anodą. W praktyce wszystkie LOW zamieniamy na HIGH i na odwrót. Niezależnie także te, które współpracują z klawiaturą, gdyż na płytce testowej założono inwertery i tam „wciśnięte” oznacza podanie wysokiego stanu. Tu – jak widać – wciśnięcie oznacza zwarcie do masy.
Pytanie – jeśli mamy dowolność, czym się kierować przy podłączaniu elementów? Już wyjaśniam. Zero i jedynkę zawsze zostawiamy do wykorzystania jak już nam nic nie zostanie. Oczywiście można z tych pinów zrobić jakiś pożytek, ale podczas programowania Arduino winny być niepodłączone do niczego. To znaczy można do nich podłączyć na przykład klawiaturę i nie ruszać jej podczas wgrywania programu. Lecz skoro i tak nie wykorzystam zasobów w pełni, zostawię te wejścia wolne.
Płytka edukacyjna TME posiada klawiaturkę podłączoną między innymi do pinów czwartego i siódmego. Dla wygody zarezerwuję je do tych celów. Na pin drugi wstawiono piszczek, więc niech sobie tam będzie. Z pewnych względów diodę dwukropka chcę mieć podłączoną osobno, na wyjście PWM. Posadzę ją więc na pinie trzecim. Reszta – tu już mamy pełną dowolność, ale żeby był porządek, segmenty wstawię na wolne piny cyfrowe, a wspólne anody na piny analogowe, które będą pracować jako wyjścia cyfrowe.
Tak więc po stworzeniu takiej układanki i skompilowaniu kodu, powinniśmy uzyskać działający model wirtualny. Trzeba przyznać, że trochę to pochłania mocy i i7 Intela nieco buczy wiatraczkiem. Dalszy ciąg prac możemy robić tu albo już na modelu rzeczywistym. Na tym etapie przeniosę się w świat prawdziwy. Po stworzeniu klona, ale już prawdziwego i pozamienianiu wspomnianych LOW i HIGH w bloku sterowania klawiatury całość ruszyła dokładnie jak model z komputera – a więc mamy już działający zegar i możemy śmiało przetestować całe wiaderko wyświetlaczy, które przecież każdy elektronik chomikuje w skrytości ;) Ale o tym napiszę w kolejnym artykule.