[145] Praktyczny wyświetlacz z czterema przewodami cz. 1
Ostatnio wpadła mi taka rzecz do ręki i jak się okazało, wyświetlacz ten jest bardzo wygodny, bo wymaga tylko czterech przewodów do działania. Portale sprzedażowe zalało właśnie takimi wyświetlaczami. Występują w trzech grupach: czterocyfrowe z dwukropkiem – jak w zegarku, z kropkami – jak w kalkulatorze i sześciocyfrowe. Wyświetlacz jak wyświetlacz, mało to ich? Lecz ten ma trzy konkretne zalety. Po pierwsze: rynek nimi zalało – jak mówiłem, a to znaczy że można śmiało w nie zainwestować i gdy trzeba będzie jutro kupić kolejny, nie znikną tak po prostu z dnia na dzień. Po drugie – kosztują pięć złotych. To akurat normalna cena dla czterech cyferek, ale po trzecie – z drugiej strony przylutowano układ scalony będący interfejsem, który w prosty sposób połączy nam owo cudo z Arduino tylko dwoma liniami sygnałowymi. Tak więc potrzeba czterech przewodów (razem z zasilaniem), co redukuje plątaninę kabli, zajętość portów i jeszcze kosztuje owo pięć złotych. Na dodatek mamy biblioteki w prosty sposób wyświetlające liczby, sterujące jasnością, a jak będzie trzeba, możemy wyświetlić cokolwiek. Zamówiłem więc sobie cztery takie cyferblaty i dziś się nimi pobawię.

TM1637 nazywa się układ znajdujący się z tyłu, który odpowiada za atrakcyjność wyświetlacza. Może on sterować sześcioma siedmiosegmentowymi zespołami z kropkami oraz matrycą klawiatury z 16 przyciskami.

Układ możemy oczywiście kupić solo i wyrzeźbić sobie własny wyświetlacz, lecz cała frajda polega na tym, że całość jest oferowana już w komplecie w kilku konfiguracjach. Co ciekawe, producenci zupełnie zlekceważyli opcję klawiatury, podobnie jak programiści oferujący biblioteki. Ale jeśli ktoś by potrzebował – da się wykorzystać.
Bohater naszego artykułu zawiera cztery cyferki i tylko jedną kropkę dziesiętną, która jest tu dwukropkiem. Na krawędź wysunięto cztery goldpiny (choć nie gold dosłownie), więc połączenie z Arduino Uno na płytce edukacyjnej TME jest śmiesznie proste. Co ciekawe, w systemie można używać tych wyświetlaczy jednocześnie więcej – aż się skończą piny. Cyfry okazały się świecić na czerwono na tyle jasno, że w warunkach przyciemnionego pokoju ustawiłem jasność minimalną, a i tak było to zbyt wiele. Zawsze jednak można dołożyć jakiś filtr czerwony. Na początek nawiążmy z wyświetlaczem kontakt, niech się coś pojawi.
Jak wszystko, co idealne, idealne nie jest. Wydawałoby się, że to jakieś I2C, a tu bieda – ani adresów, ani kompatybilności. Innymi słowy, dialog z wyświetlaczem trzeba uprawiać na piechotę. Na szczęście wielu już ten język opanowało, a organizacja Arduino rekomenduje bibliotekę TM1637Display. Obsługuje czterocyfrowe wersje i wprowadza kilka poleceń. Tutaj skorzystamy z dwóch, ale po kolei.
#include <TM1637Display.h> // Biblioteka obsługująca układ TM1637
TM1637Display display(3, 4); // Deklarowanie portów wyświetlacza: CLK, DIO
void setup() {
display.setBrightness(0); // Ustawianie jasności: od zera do 15
}
void loop() {
for (int x = -999; x < 10000; x++) { // Utwórz pętlę: od -999 do 9999
display.showNumberDecEx(x, 0); // Wyświetl liczbę (-999...9999), 64 - dwukropek.
delay(100); // Opóźnienie.
}
}Najpierw importujemy bibliotekę, którą trzeba ściągnąć wcześniej z zasobów wydanych oficjalnie. Następnie deklarujemy ten konkretny wyświetlacz, nadając mu nazwę i określając piny dla linii zegara i danych. Można takich wyświetlaczy zadeklarować więcej, nadając im różne nazwy. Na początku zmniejszyłem jasność do zera, co wcale nie wygasza wyświetlacza, tylko wprowadza wypełnienie równe 1/16 poziomu maksymalnego. W pętli głównej będziemy odliczać od -999 do 9999, bo taki zakres wyświetlacz może pokazać za pomocą prostego polecenia showNumberDec. Kolejna linia wyświetla liczbę, która jest zwiększana w pętli, zwiększając ją 10 razy na sekundę. Jeśli chcielibyśmy zobaczyć dwukropek, należy drugą z liczb ustawić na 64 – zaświeci się on mam wówczas. Stąd wersja alternatywna polecenia, z literami Ex na końcu, która obsługuje kropki i dwukropki.

Po kompilacji ujrzymy przykładowy stoperek. Możemy zmienić kształt wybranych cyfr, edytując plik biblioteki z rozszerzeniem cpp, ale chyba widoczne tu zadowolą większość. Skoro wszystko działa, czas na jakąś praktyczną realizację urządzenia z takim wyświetlaczem. Postanowiłem przebudować miernik migawek i lamp błyskowych, o którym pisałem niedawno. Wykorzystując Arduino Nano czy Mini, za kilkanaście złotych możemy zbudować kompletne urządzenie, używając jedynie czterech przewodów. Ale na razie uruchomię układ z płytką edukacyjną, pozostawiając przed chwilą zestawianą konfigurację i dodając fototranzystor ze wspomnianych artykułów.
#include <TM1637Display.h> // Biblioteka obsługująca układ TM1637
TM1637Display display(3, 4); // Deklarowanie portów wyświetlacza: CLK, DIO
volatile unsigned long openingMoment = 0; // Moment otwarcia migawki.
volatile unsigned long closingMoment = 0; // Moment zamknięcia migawki.
volatile bool isMeasuring = false; // Flaga - ustawiona, jeśli trwa pomiar.
const byte phototransistorPort = 2; // Adres portu fototranzystora (2 albo 3)
const byte colon[4] = { 0, 128, 0, 0 }; // Tablica dwukropka.
void setup() {
pinMode(phototransistorPort, INPUT); // Deklaruj port fototranzystora jako wejście.
display.setBrightness(15); // Ustawiaw jasność wyświetlacza (0...15)
display.setSegments(colon); // Prześlij na wyświetlacz zawartość powyższej tablicy.
attachInterrupt(digitalPinToInterrupt(phototransistorPort), interrupt, CHANGE); // Włącz przerwania z portu fototranzystora.
}
void loop() {
if (closingMoment > 0) { // Jeśli pomiar jest zakończony...
unsigned long exposureTime = closingMoment - openingMoment; // Policz czas migawki.
if (exposureTime < 1000000UL) { // Jeśli czas migawki jest krótszy od sekundy...
display.showNumberDecEx((1000000UL / exposureTime), 0, false, 4, 0); // Wyświetl czas migawki w formie fotograficznej.
} else { // Jeśli czas migawki jest równy sekundzie lub dłuższy...
display.showNumberDecEx((exposureTime / 10000), 64, false, 4, 0); // Wyświetl czas migawki z dwoma miejscami po przecinku (dwukropku).
}
closingMoment = 0; // Wyzeruj licznik dla kolejnego pomiaru.
}
}
void interrupt() {
if (digitalRead(phototransistorPort) == LOW) { // Jeśli migawka została otwarta...
if (!isMeasuring) { // Jeśli nie było mierzenia...
openingMoment = micros(); // Wpisz stan micros do zmiennej momentu otwarcia migawki.
isMeasuring = true; // Włącz flagę mierzenia.
}
} else { // Jeśli migawka została zamknięta...
if (isMeasuring) { // Jeśli było mierzenie...
closingMoment = micros(); // Wpisz stan micros do zmiennej momentu zamknięcia migawki.
isMeasuring = false; // Wyłącz flagę mierzenia.
}
}
}I znowu ideą program różnić się nie będzie jakoś znacząco. Także w przerwaniach mierzymy czas otwarcia migawki, wykorzystując zmienną systemową micros. Jednak zamiast dużego wyświetlacza mamy tylko cztery cyfry z dwukropkiem i trzeba jakoś przeorganizować wizualizację danych. Pozbądźmy się więc wyświetlania w mikrosekundach – bo nie ma dla tej wartości miejsca. Będziemy ukazywać czasy w systemie fotograficznym. Dla tych, które są krótsze od sekundy, będzie się pojawiać wartość mianownika, jak w aparatach. Dla dłuższych czasów – pierwsze dwie pozycje to sekundy, dwie ostatnie – setne jej części. Wykorzystamy dwukropek, by tę wartość przedzielić i jednoznacznie ukazać różnicę między wartościami krótszymi. A ponieważ nie mamy tutaj przecinków, możemy przejść z wartości zmiennoprzecinkowych na liczby naturalne. Takie obliczenia są znacznie szybsze.
A teraz konkretnie: na wstępie pojawiła się tablica colon (dwukropek). Użyjemy tu kolejnej funkcji związanej z biblioteką, wyświetlanie dowolnej treści. Coś takiego można uzyskać za pomocą setSegments i ciągu czterech bajtów, adresujących konkretne segmenty. Dwukropek to najstarszy bit drugiego bajtu. Wyświetlimy go zaraz po resecie, co będzie znaczyło oczekiwanie na pierwsze pstryknięcie aparatem.
W głównej pętli zaczynamy od ustalenia czasu naświetlania fototranzystora w mikrosekundach. Stanie się to, jeśli pomiar będzie zakończony. I teraz jeśli wartość ta jest mniejsza od miliona, wyświetlimy wynik miliona podzielonego przez czas migawki. Funkcję tę widzieliśmy w poprzednich szkicach, ale doszły tu jeszcze dodatkowe argumenty. Pierwszym więc jest liczba, przypomnę: od -999 do 9999. Drugim – wyświetlenie przecinka, jeśli wstawimy tu 64 albo jego brak, przy zerze. Jeśli trzecia oznacza prawdę, pojawią się zera znaczące, jeśli fałsz – będą tam puste miejsca. Czwarta to liczba cyfr na wyświetlaczu, a piąta – pozycja startowa. Zbędnych danych nie trzeba podawać, ale podobno ich podanie przyspiesza działanie funkcji.
Natomiast jeśli zmierzony czas jest równy sekundzie lub ma wartość dłuższą, dzielimy ową wartość przez 10 tysięcy i wyświetlamy, włączając tym razem dwukropek, w ten sposób dostając jeszcze dodatkowy – wizualny podzielnik przez sto. Mamy więc pomiar tych czasów z dokładnością do setnej części sekundy, a zakres do 100 sekund. A co będzie, gdy ów czas przekroczymy? Zginie pozycja setek. Wypadałoby więc wstawić tutaj pułapkę i wyświetlić jakiś symbol przekroczenia zakresu, ale tak długich czasów tym mierzyć nie będziemy, więc tak to zostawiłem. Jeśli ktoś chce mieć elegancko, niech sobie dopisze jeszcze jeden warunek.
No właśnie, dokładność powyżej sekundy jest wystarczająca, ale poniżej bardzo marna i zwiększa się ona dopiero przy migawkach rzędu jedna kilkudziesiętna sekundy. Naprawmy to w kolejnym artykule.















































































































