Dzisiaj przedstawię krótko kolejną nakładkę na Arduino UNO, a mianowicie D1Robot/Iduino LCD Keypad Shield, który jak sama nazwa wskazuje, na pokładzie ma wyświetlacz ciekłokrystaliczny 2x16 oraz pięć (sześć, jeśli liczymy RESET) przycisków podłączonych na GPIO. Shield ten pozwala w prosty sposób stworzyć interfejs użytkownika dla naszej instrukcji, ponieważ oferuje zarówno wejście (przyciski), jak i wyjście (wyświetlacz). W sam raz na dobry początek z Arduino, niekoniecznie R4.
LCD Keypad Shield DFRobot
Keypad shield występuje pod różnymi nazwami, z tego co widziałem niektóre są oznaczone Iduino, inne DFRobot, a jeszcze inne D1Robot. Moduł można kupić bardzo tanio, z Chin nawet za 10 zł, ale wtedy czekamy długo na przesyłkę, natomiast z naszego kraju około dwa razy drożej (płacimy za przesyłkę):
Wbrew pozorom moduł ten nie jest skomplikowany, nie ma tu żadnego specjalnego sterowania wyświetlaczem przez I2C, wszystko idzie normalnie na GPIO:
Poniżej krótki opis modułu od jednego z jego producentów:
No i schemat:
Tutaj należy zwrócić uwagę na jedną rzecz - przyciski są podłączone na jeden pin ADC. Działa to w ten sposób, że rezystory na przyciskach tworzą dzielnik napięcia a my odczytując napięcie z tego dzielnika jesteśmy w stanie określić, który z przycisków musi być zwarty, minusem tego rozwiązania jest to, że wciskać możemy tylko jeden przycisk w danym momencie.
Można zauważyć, że to jest to samo co byśmy mieli jakbyśmy podłączyli wyświetlacz kabelkami, to po prostu ułatwia nam połączenia... ale przecież o to w shieldach chodzi, prawda?
Hello World Menu
Zacznijmy od prostego przykładu pokazującego działanie LCD i przycisków. Można by go pisać samemu - ale po co? Jesteśmy w świecie Arduino, to prawie wszystko jest gotowe:
https://github.com/mich1342/D1RobotLCDKeypadShieldArduinoUno/blob/master/KeypadExample.ino
Kod:
Kod: C / C++
Rozważmy jego działanie:
Kod: C / C++
Powyższy fragment kodu to uruchomienie LCD poprzez konstruktor klasy LiquidCrystal.
Kod: C / C++
Powyższy fragment odczytuje wartość z ADC i sprawdza w którym przedziale ona się znajduje, w ten sposób określane jest który przycisk jest wciśnięty.
Kod: C / C++
Powyższy kod inicjuje wyświetlacz w trybie 2x16, ustawia na nim kursor oraz drukuje pierwsze teksty, a po krótkim opóźnieniu czyści go i wyświetla kolejny napis.
Kod: C / C++
Powyższy kod wykonuje się już w pętli i wyświetla bieżący czas na pierwszym wierszu wyświetlacza, a na drugim przycisk, który my wciskamy.
Kompilujemy i wgrywamy - wszystko oczywiście działa:
Lepsze zdarzenia przycisków na ADC
Pokazany kod obsługi przycisków na pinie ADC jest bardzo prosty i zrozumiały, ale też jest bardzo prymitywny. Nie obsługuje on tworzenia zaawansowanych zdarzeń takich jak moment wciśnięcia przycisku, jak jego zwolnienie oraz stan trwającego wciśnięcia. Moglibyśmy takie zdarzenia dodać ręcznie, ale tu też mamy gotowca:
https://github.com/dxinteractive/AnalogMultiButton
AnalogMultiButton oferuje nam właśnie takie zdarzenia, tylko trzeba najpierw ją skonfigurować pod nasz dzielnik rezystorowy. W tym celu tworzymy prosty sketch odczytujący wartości z ADC:
Kod: C / C++
Wypisujemy wartości dla każdego z przycisków:
- brak - 1014
- select - 722
- left - 484
- up - 134
- bot - 311
- right - 0
Wpisujemy je do tablicy wziętej z przykładów AnalogMultiButton:
Kod: C / C++
To w zasadzie tyle, ale ja dla przejrzystości przygotowałem jeszcze drugą tablicę (napisów w stylu C, łańcuchów znaków) aby móc drukować na ekran co się dzieje. Oto cały mój przykład:
Kod: C / C++
Odpalmy to i wciśnijmy na próbę SELECT:
Biblioteka poprawnie wykrywa zdarzenia, najpierw raz jest wciśnięcie przycisku (press event), potem jego stan jest jako wciśnięty (held down), a potem przycisk zostaje zwolniony, więc mamy raz zdarzenie release. Dodatkowo biblioteka pozwala mierzyć jak długo przycisk był wciśnięty i zwolniony, co umożliwia nam tworzenie jeszcze bardziej zaawansowanych systemów sterowania.
Warto tez zwrócić uwagę na to, że zdarzenia "pojedyncze" wywoływane są raz, więc nie ma problemu z drganiem styków.
Prosty przykład głównego menu - część 1
Mamy już lepszą obsługę przycisków i mamy też możliwość wyświetlanie tekstu. Pora zrobić nieco lepsze menu, powiedzmy, dla jakiegoś konfiguratora parametrów.
Postawmy sobie następujące założenia:
- klawisze góra/dół przełączą opcje menu
- strzałka pokazuje bieżącą opcję
- menu się przewija do góry i w dół, ale tylko gdy jest to potrzebne (gdy cofamy o jedno pole, to sie nie przewija)
Zacząłem od wpisania do kodu opcji menu, osobno jako enumerator i osobno ich nazwy do wyświetlania:
Kod: C / C++
Potem przygotowałem zmienne, a mianowicie dwie pozycje:
- pozycja menu gdzie jest wyświetlane
- pozycja menu która jest wybrana
Przypominam, ze względu na dynamikę przesuwania to są osobne zmienne.
Kod: C / C++
Potem podpiąłem się pod zdarzenia przycisków:
Kod: C / C++
Została jeszcze funkcja odświeżaja ekran. Tam się odbywa cała magia:
Kod: C / C++
Funkcja sprytnie sprawdza, czy wybrana pozycja wykracza poza wyświetlany margines i tylko wtedy przesuwa cały ekran. Inaczej przesuwa się tylko kursor. Oto efekt:
Prosty przykład głównego menu - część 2
Mamy już przesuwanie kursorem góra-dół, pora dodać edycję zmiennych.
Najpierw może dodajmy dwie funkcje, które dadzą nam do nich dostęp:
Kod: C / C++
Jedna funkcja pozwala pobrać wartość zmiennej dla danej pozycji z menu, a druga pozwala do niej dodać wartość. Odejmowanie zrealizujemy jako dodawanie ujemnej wartości. Teraz trzeba zmodyfikować wyświetlanie tak, by brać pod uwagę wartości pozycji. Przygotowałem funkcję która wyświetla daną pozycję a potem jej dwa razy użyłem:
Kod: C / C++
Wywołanie:
Kod: C / C++
No i zostało przechwycić zdarzenia przycisków. Tutaj chcemy łapać dwa zdarzenia:
- początkowo wciśnięcie klawisza (zmiana pojedyncza)
- powtórzenia klawisza, dopóki jest on wciąż trzymany (szybka zmiana wartości)
Na szczęście AnalogMultiButton to wszystko wspiera:
Kod: C / C++
Demonstracja:
Podsumowanie
Bardzo wygodny shield. To takie okno na świat dla Arduino. Oczywiście działa też z R4, ale to chyba nie jest żadne zaskoczenie.
Przykładów użycia też było mnóstwo i łatwo było z tą nakładką wystartować, chociaż od połowy tematu pokusiłem się już o napisanie własnego prostego menu. Może komuś z początkujących się przyda, a może ktoś go ulepszy...
W razie problemów bądź potrzeby rozwinięcia kodu chętnie pomogę.
Czy ktoś korzysta z tego lub podobnego shielda? Zapraszam do komentowania. A może ktoś umieści zdjęcie swojej konstrukcji?
Fajne? Ranking DIY Pomogłem? Kup mi kawę.
