
Zapraszam na krótki test i demonstrację użycia popularnych modułów wyświetlacza 7-segmentowego opartych na TM1637. Uruchomię taki moduł najpierw z Arduino, a potem bez użycia żadnej biblioteki, na koniec również pokażę alternatywną, eliminującą zbędne opóźnienia bibliotekę przeznaczoną do sterowania tymi modułami.
Zakup układu
Może tym razem temat zaczniemy od kwestii finansów. Ile kosztuje ten moduł?
Tym razem poszukiwania zrealizowałem na polskim serwisie aukcyjnym.

Można kupić zarówno samą kość, nawet za 2.5zł, jak i gotowe moduły.
Moduł 4-cyfrowy kosztuje jakieś 6zł, a 6-cyfrowe moduły są za ponad 15zł:

Przesyłka też będzie kosztować około 10 zł, chyba, że ma się wykupione darmowe przesyłki, z których sam na tym portalu korzystam. Niestety obowiązują dopiero od około 40/45zł kwoty zamówienia, więc coś jeszcze trzeba do koszyka włożyć.
Trochę teorii...
A raczej krótka lektura noty katalogowej. Na początek witają nas wyprowadzenia układu, ale mamy gotowy moduł, więc to nam nie jest potrzebne:

Układ potrafi też obsługiwać klawiaturę, ale nasze moduły tego nie wspierają.
Wyprowadzenia:

6 gridów, 8 segmentów.
Czyli 6 cyfr 7-segmentowych z np. dodatkową kropką lub z dwukropkiem.
Te CLK, ACK, brzmią trochę jak I2C, ale...

Niestety I2C to nie jest. Nie ma nawet wspieranego adresowania układów, czyli nie można (tak jak by można było w I2C) na jedną magistralę podłączyć kilku urządzeń. Słabo.
Przykładowa aplikacja:

Przyciski są podłączone do specjalnych portów K2 i K1, czyli nie odbierają nam wyświetlaczy. Warto będzie rozważyć wykorzystanie tego w przyszłosci, choć tutaj tego nie opiszę. Tych przycisków też jest dość dużo, więc można by zrobić na tym ładną klawiaturkę.
Parametry użytych wyświetlaczy (prąd na segment, itd.) są w nocie katalogowej.
Przykład w Arduino
Większość popularnych modułów już posiada ogólnodostępne, darmowe biblioteki do Arduino. Tak jest i w tym przypadku. Wszystko na Githubie:
https://github.com/avishorp/TM1637
Bibliotekę można też znaleźć w kreatorze bibliotek Arduino i dołączyć automatycznie.
Oto pełny przykładowy kod z tej biblioteki:
Code: cpp
Ale całość można nieco uprościć.
Code: cpp
Konstruktor TM1637Display bierze dwa argumenty - indeks pinu CLK i DIO. Funkcja setBrightness ustawia poziom jasności (od 0 do 15) oraz włącza segmenty (true by je włączyć, false wyłączyć).
Wartość dziesiętną pokazuje showNumberDec.
Oprócz tego mamy dostęp bezpośrednio do segmentów (funkcja setSegments) oraz możliwość wyświetlenia liczby z kropką (funkcja showNumberDecEx). Funkcja setSegments oferuje argumenty, za pomocą których można dostać się do wybranego znaku (np. zaktualizować tylko dwa znaki na pozycjach 4 i 5), pierwszy argument to indeks pierwszego znaku, a drugi to ilość znaków.
Przykład "na piechotę"
Protokół wyświetlacza jest znany i opisany w nocie katalogowej:



Zgodnie z protokołem, aby wysłać write data to display register najpierw musimy nadać:
Code: c
Potem, po stop i ponownym start nadajemy komendę ustawienia rejestru do którego zapisujemy, czyli:
Code: c
Z 4 najmłodszymi bitami ustawionymi na adres pierwszego znaku, który aktualizujemy. Zazwyczaj będzie to 0.
Potem nadajemy kolejne bajty (dane segmentów).
Na koniec chcemy nadać display control ze stanem On/Off (bit 3) oraz poziomem jasności (bity 2, 1 i 0):
Code: c
Wpisując to w kod otrzymujemy:
Code: c
Uzupełniając, powstawanie danych trzeciej komendy już opisywałem (bit on/off oraz 3 bity poziomu jasności), powstaje ona tak:
Code: c
Zostają jeszcze nasze 3 pomocnicze funkcje, czyli warunek startu, stopu oraz wysyłanie bajtu.

Zaczynamy od stanów wysokich, potem DIO przechodzi w stan niski, jak również i zegar.
Code: c
Potem, dla każdego bitu, ustawiamy jego wartość na DIO, a ona jest odczytywana przez układ w momencie rosnącego zbocza CLK (czyli jak CLK przechodzi ze stanu false na true, niskiego na wysoki).
Code: c
Potem, kontynuując funkcję wysyłania bajtu, mamy:
Code: c
Zegar wykonuje kolejny cykl. Pin DIO wchodzi w tryb wejścia. To jest ten moment, który na diagramie jest oznaczny jako The chip is automatically lowered at ACK low level (pomiędzy opadającym zboczem 8-go cyklu zegara i zakończeniem 9-go cyklu zegara). Czekamy moment i odczytujemy wartość z DIO. To jest odpowiedź ACK. Na jej bazie można sprawdzić, czy układ odpowiada. Potem DIO wraca do trybu wyjścia.
Na koniec wracamy do stanów wysokich.
Code: c
To tyle. Oczywiście, nie zdefiniowałem tu rzeczywistych map segmentów które są wymagane by poprawnie wyświetlić cyfry, ale to można już zrobić we własnym zakresie.
Prędkość komunikacji
Problem braku rzeczywistego I2C już omawiałem, ale niestety to nie jest jedyna niemiła niespodzianka tutaj. Po zaglądnięciu do źródła TM1637Display.cpp widzimy, że kod komunikacji usłany jest delay'ami (a dokładniej tam: bitDelay), domyślnie 100us. Jest to na tyle dużo, że warto coś z tym zrobić. Sam w moim kodzie (zacytowanym powyżej) trochę eksperymentowałem ze zmniejszaniem tych opóźnień, ale w sieci też jest gotowe na to rozwiązanie:
https://github.com/cphouser/TM1637-no-delay
Biblioteka TM1637-no-delay zaimplementowana jest bez użycia funkcji takich jak delayMicroseconds. Posiada interfejs pozwalający odświeżyć wyświetlacz bez blokowania pętli zdarzeń. Wymaga dodatkowego wywoływania funkcji update co 100us.
Poniżej przykład użycia tej biblioteki (skopiowany z ich Githuba):
Code: c
Po dokładne wymagania co do timingu należy zajrzeć do noty katalogowej.
Mały problem z kolejnością setSegments
Na koniec chciałbym dać jeszcze małą uwagę/przestrogę co do ustawiania segmentów. Nie wiem, czy to jest częsty problem, ale w moim przypadku cyfry wyświetlacza były tak podłączone, że wysłanie do niego kodów znaków w tej kolejności:
1 2 3 4 5 6
Skutkowało wyświetleniem:
3 2 1 6 5 4
Aby to naprawić, trzeba albo fizycznie przepiąć połączenia GRID (jak na schemacie umieszczonym wyżej w tym temacie), albo programowo remapować segmenty poprzez tablicę:
Code: c
Indeksy w C/CPP itd zaczynamy od 0.
Galeria efektów
Niezbyt wiem co można tu pokazać. Chyba najlepiej zacząć od kontroli poziomów jasności:

Klasyka, odliczanie:

Test cyfr:

Podsumowanie
Przed bliższym zapoznaniem moduł wydawał się być bardziej atrakcyjny. Po dokładniejszym poznaniu jego działania uznałem, że jest nieco gorszy niż myślałem. Nie powinieniem narzekać, bo i tak kupiłem go na prośbę kolegi z Ukrainy, aby móc dla niego go uruchomić na BK7231N, ale naprawdę nie rozumiem, czemu producent nie użył w tym wyświetlaczu normalnego I2C. Możliwość użycia jednej linii komunikacyjnej (no dobra, dwóch linii - SDA i SCL) dla wielu urządzeń jest naprawdę bardzo przydatna, a co by producentowi to jedno więcej odebranie bajtu zmieniło? I czemu ta komunikacja jest taka wolna? Dobrze, że w sieci są gotowe biblioteki dla niego pod Arduino, zarówno w wersji blokującej jak i tej bez opóźnienień.
Czy korzystał ktoś z tego wyświetlacza w projektach? A może ktoś zna równie tani moduł, ale z interfejsem I2C?
Cool? Ranking DIY