Od paru miesięcy śledzę z wypiekami stronę majsterkowo.pl, ale dopiero kilka tygodni temu kupiłem swój pierwszy zestaw startowy Arduino Uno w firmie Nettigo. W kolejnym tygodniu biegałem już niemal codziennie do paczkomatu, odbierać drogocenne, słodko grzechoczące kartoniki, pełne sensorów, potencjometrów, tasiemek, rezystorów, wyświetlaczy i przeróżnego elektronicznego złomu, który teraz zalega każdy zakamarek mojego biurka i niecierpliwie czeka na swoją kolej.
Chwilę później okazało się, że moja stara lutownica pistoletowa nadaje się w zasadzie głownie do niczego i nieodzownym było doposażenie warsztatu w kilka innych niespodziewanie niezbędnych narzędzi. A wszystko tylko po to, by po ciężkim dniu pracy pośród gęstych i słodkawych oparów kalafonii oddawać się swej nowej pasji. Ale wystarczy tego barwnego wstępu, reasumując: wydaje mi się, że dojrzałem by podzielić się z Wami swymi nowo nabytymi doświadczeniami. A jak mi wyjdzie, to się jeszcze okaże. No to przejdźmy do rzeczy.
Zepsuł mi się zegar. Taki niespecjalnie ładny i niespecjalnie dokładny, więc nie było mi go jakoś szczególnie żal, ale wiadomo: bez zegara – jak bez ręki. Żona wiecznie narzeka, że potyka się o kable z tego mojego nowego hobby i wszędzie po kątach znajduje ukradkiem wypluwane kawałki izolacji, to pomyślałem sobie: hola hola, może w końcu się przyda moja pasja?
Wymyśliłem sobie początkowo zegar z dużą matrycą LED, taką przynajmniej 32×16, ale pooglądałem ceny, momentalnie posiwiałem i zdecydowałem się na wersję ULTRA-ECONO. Postanowiłem sklecić matrycę z dwóch kostek TC12-11HWA. Matryca ta posiada 5×7 diód, ale po ustawieniu dwóch matryc poziomo uzyskujemy matryce 14×5. Z szybkich szkiców na kartce w kratkę wynikło, że spokojnie wystarczy do wyświetlenia 4 cyfr w formacie 3×5:
Kiedy przyszły wyczekiwane matryce, spotkała mnie pierwsza niespodzianka. Nigdzie nie znalazłem jak oznaczony jest pin nr 1. Ani w dokumentacji producenta, ani na samej matrycy nie ma żadnego oznaczenia! Oglądałem je chyba z 10 minut z każdej strony. Absolutnie nic. Pomyślałem: ZMIERZĘ! I jak zacząłem mierzyć to okazało się, że wyprowadzenia zrobione są tak sprytnie, że obojętnie jak odwrócimy matrycę w pionie, to 1 zawsze będzie na dole po lewej. Nie wierzycie??? Sprawdźcie sami.
Oto moja po partyzancku polutowana matryca:
Trzyma się to wszystko kupy dzięki sztywnym kablom ze skrętki, które umieściłem poprzecznie (wspólna katoda).
Na zdjęciu pewnie niektórzy dociekliwi wypatrzą niechlujnie przyczajoną diodę. Na wyświetlaczu zabrakło miejsca na “mrugający sekundnik”, więc postanowiłem dorobić swój :D będzie o nim jeszcze za chwilę. Na razie zapominamy że istnieje.
Matryca 14×5 jak łatwo policzyć wymaga 14 linii do sterowania kolumnami (szyna danych), oraz 5 linii do sterowania wierszami (szyna adresowa).
Aż 19 pinów?? Zdawałoby się, że to za dużo jak na nasze małe Arduino. Nic bardziej mylnego! Zwiększymy sobie ilość wyjść używając ośmiobitowych rejestrów przesuwnych 74HC595. W tzw. “internetach” można znaleźć wiele przykładów użycia tego i innych rejestrów wraz z Arduino, więc nie będę się tutaj wielce rozwodził nad zasadą jego działania. W skrócie: działa tak, że podajemy mu bajt (8 bitów) na szynę szeregową (kolejno), a po zamknięciu zatrzasku (latch), układ wystawia nam podany bajt na wyjście równoległe – czyli osiem pinów.
Do komunikacji szeregowej z rejestrem potrzebujemy 2 piny + 1 pin(zatrzask), co pozwala nam tylko trzema pinami sterować poziomem 8 wyjść. Oczywiście dzieje się to nieco kosztem szybkości, ale to już osobna historia. Potrzebujemy 19 wyjść, więc użyjemy trzech układów 595. W zestawie startowym z Nettigo, dostałem jeden egzemplarz, który zdążyłem już nieco powyginać, więc musiałem niezwłocznie dokupić. Oczywiście od razu zrobiłem zapas licząc w duchu, że kiedyś poskładam większą matrycę :)
Nasze trzy układy 75HC595 łączymy kaskadowo. Co to oznacza? W normalnej sytuacji do sterowania trzema układami 595 potrzebowalibyśmy 3 wyjść szeregowych (6 pinów) i wspólnego zatrzasku. Cóż za niepotrzebne marnotrawstwo pinów! Z pomocą przyjdzie nam tajemnicza nóżka Q7′ układu 74HC595. Podłączamy ją do wejścia kolejnego rejestru i otrzymujemy rejestr 16 bitowy sterowany tylko jednym wejściem szeregowym!
Jak to działa?
Pierwszy bit podany na wejście układu ustawia się na wyjściu o numerze Q0. Po podaniu kolejnego bitu bit z pozycji Q0 przesuwa się na Q1, a nowy wskakuje na Q0. Kolejne bity podawane na wejściu układu wyskakują kolejno na wejście Q0, przesuwając wszystkie na wyższych pozycjach o jeden. Po podaniu 8 bitów mamy zapełnione wszystkie pozycje naszego rejestru, jeżeli jednak nie zamkniemy w tym momencie zatrzasku, tylko podamy kolejne bity to w drobnym uproszczeniu bit z pozycji Q7 “wyskoczy” nam na pozycję Q7′. Stąd możemy go “zabrać” do następnego układu na wyjście Q0. I tam znów będzie kolejno przesuwany, aż do zapełnienia wszystkich rejestrów które połączymy w kaskadę i/lub zamknięcia zatrzasku. Uff… a miałem nie opowiadać jak działa rejestr przesuwny. Wszystkich znudzonych “wyjadaczy” przepraszam.
A oto schemat:
(wykonano w programie FRITZING)
Poniżej mój gotowy układ sterownika matrycy:
Najmocniej przepraszam za brak sesji z “making of”, ale na pomysł wpisu wpadłem już po ukończeniu pierwszej (mam nadzieję) wersji projektu.
Znowu wyjadacze moga przeskoczyć do następnego akapitu, ale szybkie wyjaśnienie dla takich nowicjuszy jak ja. Matryca nie świeci cały czas jak monitory LCD. Zapalane są kolejne wiersze lub kolumny matrycy, w bardzo krótkich odstępach czasu. Bezwładność ludzkiego oka powoduje że widzimy stały obraz. Trochę jak w starych kineskopach CRT, ale tylko trochę. I podobnie będzie w naszym wypadku. Tutaj wybrałem zapalanie kolejnych wierszy.
I tu kolejna – prócz ceny – zaleta małej matrycy. W każdym cyklu zapalane jest maksymalnie 14 diód. Gdybym miał matrycę o szerokości 32, obawiam się, że prąd który mogę “wyciągnąć” z rejestru, do zasilenia wiersza mógłby nie wystarczyć do zapalenia wszystkich 32 diód. Musiałbym zastosować kluczowane tranzystorem osobne zasilanie poszczególnych wierszy (i ogólnie takie rozwiązanie byłoby zgrabniejsze, wiem). Ale w małej matrycy gdzie mamy 14 diód – nawet przy zasilaniu z Arduino poprzez USB, wyświetlacz jest całkiem czytelny, choć widać różnicę jasności pomiędzy wierszami w których jest zapalonych więcej lub mniej diód. Przy podłączeniu zewnętrznego zasilacza różnice są prawie niezauważalne. Więc nie będziemy się bawić w kluczowanie tranzystorem.
Sterowanie matrycą będzie przebiegało w następujący sposób:
W każdym cyklu do rejestrów przesyłamy 3 bajty danych, nazwijmy je sobie L P i W z których dwa (L P) ustawiają piny rejestrów podłączonych do kolumn wyświetlaczy, odpowiednio lewego i prawego, a trzeci bajt (W) ustawia wyjścia rejestru w taki sposób, że zwiera do masy (ustawia logiczne zero) odpowiedni pin dla wiersza który właśnie zapalamy (oto i znowu nasza wspólna katoda!).
Nasze trzy rejestry ośmiobitowe dają nam 24 wyjścia z 19 potrzebnych. Dla wygody samej konstrukcji płytki wykorzystałem tylko najbardziej znaczące bity rejestru, czyli dla bajtów L i P gdzie potrzebujemy tylko po 7 linii do kolumn odrzuciłem wyjście Q0, a dla rejestru adresowego (5 wierszy) odrzuciłem wyjścia Q0,Q1,Q2.
Przykładowy cykl danych dla napisu “DATA” dla wszystkich pięciu wierszy:
1 2 3 4 5 6 |
lewy prawy wiersz L P W = 11000100 11100100 11110111 = 196 228 247 L P W = 10101010 01001010 11101111 = 170 74 239 L P W = 10101110 01001110 11011111 = 174 78 223 L P W = 10101010 01001010 10111111 = 170 74 191 L P W = 11001010 01001010 01111111 = 202 74 127 |
Widać jak wędruje nam “zero” w rejestrze W :)
No to najwyższy czas podłączyć nasze cacko do Arduino.
Podłączamy:
- PIN 2 -> zegar
- PIN 3 -> szyna danych
- PIN 4 -> zatrzask
nie zapominając o:
- +5V -> +5V
- GND -> GND
i próbujemy załadować poniższy kod:
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 |
#define DANE 3 #define ZEGAR 2 #define ZATRZASK 4 void setup() { pinMode(DANE, OUTPUT); pinMode(ZEGAR, OUTPUT); pinMode(ZATRZASK, OUTPUT); } void loop() { digitalWrite(ZATRZASK,LOW); shiftOut(DANE,ZEGAR,MSBFIRST,247); shiftOut(DANE,ZEGAR,MSBFIRST,228); shiftOut(DANE,ZEGAR,MSBFIRST,196); digitalWrite(ZATRZASK,HIGH); delay(1); digitalWrite(ZATRZASK,LOW); shiftOut(DANE,ZEGAR,MSBFIRST,239); shiftOut(DANE,ZEGAR,MSBFIRST,74); shiftOut(DANE,ZEGAR,MSBFIRST,170); digitalWrite(ZATRZASK,HIGH); delay(1); digitalWrite(ZATRZASK,LOW); shiftOut(DANE,ZEGAR,MSBFIRST,223); shiftOut(DANE,ZEGAR,MSBFIRST,78); shiftOut(DANE,ZEGAR,MSBFIRST,174); digitalWrite(ZATRZASK,HIGH); delay(1); digitalWrite(ZATRZASK,LOW); shiftOut(DANE,ZEGAR,MSBFIRST,191); shiftOut(DANE,ZEGAR,MSBFIRST,74); shiftOut(DANE,ZEGAR,MSBFIRST,170); digitalWrite(ZATRZASK,HIGH); delay(1); digitalWrite(ZATRZASK,LOW); shiftOut(DANE,ZEGAR,MSBFIRST,127); shiftOut(DANE,ZEGAR,MSBFIRST,74); shiftOut(DANE,ZEGAR,MSBFIRST,202); digitalWrite(ZATRZASK,HIGH); delay(1); } |
TADAM!!!
I znowu kilka słów wyjaśnienia:
Może nie wszyscy wiedzą, do czego służy polecenie:
shiftOut(pin_danych,pin_zegara,kolejność_bitów,bajt).
Wysyła ono szeregowo bajt, na pinach podanych jako pierwsze dwa argumenty. Czyli dokładnie to czego potrzebujemy aby “naładować” nasze rejestry. Parametr trzeci może mieć dwie wartości: MSBFIRST lub LSBFIRST. Oznaczają one odpowiednio: najbardziej znaczący bit pierwszy lub najmniej znaczący bit pierwszy. Czyli upraszczając: czy podajemy bity kolejno od lewej czy prawej strony.
Jak już jesteśmy przy kolejności, to pewnie zauważyliście, że kolejne bajty podaję w odwrotnym szyku niż wcześniej podałem. Szynę danych podłączyłem do rejestru L (lewy wyświetlacz). Potem kaskadowo R i W. Czyli aby po podaniu trzech bajtów w rejestrze W mieć adres wiersza, musimy podać go jako pierwszy, a zawartość lewego wyświetlacza jako ostatni bajt.
I tutaj triumfalnie powraca nasza doklejona dioda! Podłączyłem jej anodę (przez rezystor 220R) do niewykorzystanego wyjścia Q0 rejestru pierwszego (L – lewy wyświetlacz) a katodę do wiersza 4 w rejestrze trzecim (W – wiersz).
(wykonano w programie FRITZING)
Teraz zamieniając tylko jedną liczbę w naszym kodzie (202 na 203 w ostatnim wysyłanym bajcie) zapalamy sekundnik! Proste i bez wykorzystania dodatkowych pinów z Arduino.
Oczywiście wyświetlanie i odświeżanie w ten sposób zawartości wyświetlacza byłoby niezwykle uciążliwe, więc zanim zabrałem się za dalsze lutowanie, postanowiłem przygotować dedykowaną bibliotekę, która do minimum uprości sterowanie wyświetlaczem. Wykorzystamy do tego przerwania zegarowe i sprzętowy interfejs SPI Arduino.
Ale to ze względu na późną porę, będzie tematem kolejnego wpisu. Oczywiście o ile ten pierwszy spotka się z Waszą aprobatą. Na zachętę wrzucam dwa malutkie zdjęcia gotowego prototypu.
Pozdrawiam i zapraszam do komentowania.
Gratuluję wpisu. Wprawdzie z uwagi na późną porę nie wczytałem się specjalnie, ale podoba mi się Twój styl ;)
No no, dziękuje. Wpis robiony późna porą i już zauważyłem dwa błędy w schemacie. Poprawię popołudniu, może do tego czasu nikt nie zauważy ;)
Ja nie zauważyłem ;) Ale jeżeli nie masz nic przeciwko, zmienię później ikonę wpisu, bo na obecnej mało co widać i nie zachęca zbytnio do klikania ;)
Śmiało zmieniaj – bo jakoś dziwnie się skaluje. Nie wiem tez jak zmienić sobie avatar – nie znalazłem nigdzie.
A co do błędów – dobrze że nie zauważyłeś ;) dioda sekundowa jest podpięta katodą do złej linii (wg opisu powinno być do A4), oraz pomyliłem kolejność kaskadowego łączenia rejestrów – adresowy jest w środku.
Avatar zmieniasz w zewnętrznym serwisie Gravatar.
schemat poprawiony ;)
Bardzo fajnie napisany artykuł i zachęca do myślenia :) Ale trochę za mało kodu dla początkujących bo z tego co napisałeś to ktoś początkujący nie zrobi zegara tylko będzie umiał wyświetlać coś na wyświetlaczu.
Przydało by się uprościć o zdefiniowanie liter i cyfr tak jak zrobiono to tutaj http://www.instructables.com/id/Make-a-24X6-LED-matrix/?ALLSTEPS
Kodu mało, bo to dopiero część pierwsza! Tematem części drugiej ma być właśnie głownie kodowanie (nie ukrywam – mój konik). Przygotowałem dedykowaną bibliotekę do obsługi tego wyświetlacza i opowiem o tym jak. A przynajmniej zamierzam ;)
Aha, no to spoko :) W takim razie życzę głównej i czekam na więcej ;)
Hmm … nic dodać nic ująć ;P jedynie brakuje komentarzy w samym kodzie. Ułatwiają późniejszą modyfikację no i początkującym mogą wiele pomóc ;]
No i wielki plus za taśmę wielokolorową do podłączenia matryc ;D
W tym kodzie akurat niewiele jest do komentowania – wszystko co mogło budzić wątpliwości opisałem pod kodem, w kolejnej – drugiej – części będzie głównie kod i obiecuje, że zadbam o komentarze :)
Jaką lutownicę na początek wziąłeś? Czy mimo wszystko z pistoletowej korzystasz?
Kupiłem stację lutowniczą, xytronic LF-369D. I w sumie jestem zadowolony. Grzeje się szybko, pamięta ostatnio ustawioną temperaturę. Musiałem tylko dokupić węższy grot i pistolet odszedł w zapomnienie. Użyłem go może dwa razy do zrobienia dziury w obudowie.
Zawsze myślałem że takie majsterkowanie to trudna sprawa ale z tego co widzę to może sobie to zrobić każdy, no każdy kto dysponuje odpowiednią ilością czasu i zapału. Sam przystąpiłem do tego zadania trochę niepewnie ale gdy zauważyłem że wszystko zaczyna układać się w jedną całość, gdy zaczyna działać nabrałem pewności. Taka amatorska zabawa w majsterkowicza jest od czasu do czasu potrzebna aby się rozluźnić.
tak ale ja bym zastosował mniejsze te diody w ekranie czy jak się to tam nazywa dla lepszej widoczności,są za duże
zegar stoi wysoko na półce mniejszy wyświetlacz byłby nieczytelny. On wcale nie jest taki wielki, może tak to wygląda na zdjęciach, ale diody maja tylko po 3mm średnicy.
Dlaczego diody a nie wyświetlacze 7 segmentowe?
po pierwsze dlatego, że trudniej i więcej możliwości.
a po drugie, to w planach jest tetris na większej matrycy, więc przecieram szlaki ;)
http://allegro.pl/art-matryce-led-5×8-38x61mm-red-2058bh-b-arduino-i3088646962.html Bedzie dobra matryca ? Pomijam ze 5×8, bo moge odstep miedzy godzina a minuta zwiekszyc i bylby tam sekundnik (w sensie dwukropek migajacy). A co poradnika to superr xd ;)
bardzo fajne tylko mam kilka pytań czy można by było zrobić taki zegar żeby tylko pokazywał godzinę i ile by kosztowało zrobienie go.
Projekt tak mi się spodobał że postanowiłem sam zmontować taki zegarek. Twój artykuł świetnie wszystko opisuje i jest świetnym uzupełnieniem mojej znikomej wiedzy o elektronice, ale jednego nie mogę dojść. Jak podłączyć matryce do układu ? Jak je połączyć ze sobą ?
Please help…