Serwisy partnerskie:
Close icon
Serwisy partnerskie

Kurs Arduino odcinek 3 - moduł wyświetlacza LCD (HD44780)

W trzecim odcinku kursu zajmiemy się wyświetlaczem LCD. Oczywiście nie jest to „goły” wyświetlacz, tylko dość skomplikowany moduł zawierający scalony sterownik HD44780 lub jego odpowiednik. Jest to wyświetlacz znakowy.
Article Image
1. Kurs Arduino: wprowadzenie 2. Kurs Arduino odcinek 1 - co to jest i jak zacząć? (sprzęt, schematy, programowanie) 3. Kurs Arduino odcinek 2 - termometry: 'diodowy', pokojowy oraz 'scalony' analogowy 4. Kurs Arduino odcinek 3 - moduł wyświetlacza LCD (HD44780) 5. Kurs Arduino odcinek 4 - czujnik BME280 (pomiar ciśnienia, wilgotności i temperatury) 6. Kurs Arduino odcinek 5 - biblioteki do trzyfunkcyjnego czujnika BME280 7. Kurs Arduino odcinek 6 - wykorzystanie łącza I2C (TWI) 8. Kurs Arduino odcinek 7 - wykorzystanie łącza SPI (karty pamięci, MAX31865, MAX31855) 9. Kurs Arduino odcinek 8 - wykorzystanie czujnika dwutlenku węgla (MH-Z19) 10. Kurs Arduino odcinek 9 - wykorzystanie modułów do odmierzania czasu 11. Kurs Arduino odcinek 10 - wykorzystanie czujników temperatury (DS18B20) 12. Kurs Arduino odcinek 11 - budowa loggera (rejestratora danych) 13. Kurs Arduino odcinek 12 - rejestracja i prezentacja danych oraz obsługa karty SD 14. Kurs Arduino odcinek 13 - rejestracja danych (wykorzystanie modułu OpenLog) 15. Kurs Arduino odcinek 14 - czym zastąpić płytkę Arduino Uno? 16. Kurs Arduino odcinek 15 - budowa rejestratora (chiński klon Arduino Pro Mini) 17. Kurs Arduino odcinek 16 - problemy z kwadratowym modułem Strong 18. Kurs Arduino odcinek 17 - czujniki do pomiaru wilgotności gleby (instalacja, konfiguracja) 19. Kurs Arduino odcinek 18 - protokół MODBUS i łącze RS-485 20. Kurs Arduino odcinek 19 - wyświetlacze od podstaw (matrycowe, 7-segmentowe, MAX7219) 21. Kurs Arduino odcinek 20a - wyświetlacze matrycowe i biblioteki MD_MAX 22. Kurs Arduino odcinek 20b - przyciski i biblioteki do obsługi wyświetlaczy 23. Kurs Arduino odcinek 20c - biblioteki do obsługi wyświetlaczy graficznych 24. Kurs Arduino odcinek 21 - moduł wyświetlacza OLED 25. Kurs Arduino odcinek 22 - moduł wyświetlacza 1,3 cala 26. Kurs Arduino odcinek 23 - przygotowanie bitmap do wyświetlania 27. Kurs Arduino odcinek 24 - omówienie fontu podstawowego (Adafruit GFX) 28. Kurs Arduino odcinek 25 - font podstawowy biblioteki Adafruit GFX 29. Kurs Arduino odcinek 26 - wykorzystanie bitmapowych fontów GFX 30. Kurs Arduino odcinek 27 - polskie znaki w glcdfont.c 31. Kurs Arduino odcinek 28 - zmiana ulepszonych fontów GFX

Fotografia 1 pokazuje najpopularniejszą odmianę oznaczaną 16x2 (16 znaków, 2 linie). Fotografia 2 przedstawia niektóre inne wersje. Wszystkie wersje takich wyświetlaczy znakowych są obsługiwane w jednakowy sposób. W Arduino mamy odpowiednią bibliotekę, która znakomicie to ułatwia. Zanim ją wykorzystamy, przypomnijmy kluczowe informacje o tym jakże pożytecznym sprzęcie.

Fot.1 Wyświetlacz LCD 16x2
Fot.2 Inne wyświetlacze

Wyprowadzenia modułu pokazane są na rysunku 3. Zwykle linii D0…D3 nie wykorzystujemy, a wejście R/W na stałe łączymy do masy (bo nie korzystamy z możliwości odczytywania danych z modułu). Spośród 16 wyprowadzeń modułu zwykle 6 wykorzystujemy do przekazywania danych. W takim oszczędnościowym trybie pracy sześć (dowolnych) pinów płytki Arduino musimy połączyć z wyświetlaczem. Napięcie stałe na nóżce Vo służy do regulacji kontrastu wyświetlacza – podłączamy tam suwak potencjometru montażowego (najczęściej 10kΩ).

Rys.3 Wyprowadzenia modułu LCD

Celem tego odcinka kursu jest opanowanie obsługi wyświetlacza LCD. Jeśli go dobrze poznamy, będziemy mieć otwartą drogę do realizacji niezliczonych pomysłów. Rysunek 4 pokazuje układ połączeń wyświetlacza, jaki wykorzystałem w ćwiczeniach – wyświetlacz jest obsługiwany przez piny 2...7 Arduino, czyli przez piny portu B procesora (PB2...PB7). Wykorzystujemy też podświetlenie, a więc nóżki 15, 16 wyświetlacza. Katodę podświetlającej diody LED dołączamy do masy (GND), natomiast anodę podłączyłem do napięcia 3,3V, co dało wystarczający efekt (upewnij się tylko, czy użyty wyświetlacz ma w obwodzie podświetlenia rezystory ograniczające prąd – fotografia 5).

Rys.4 Układ połączeń wyświetlacza,
Fot.5 Rezystory ograniczające prąd

Aby łatwo dołączyć wyświetlacz do Arduino, polutowałem „interfejs” według rysunku 3, zawierający kawałek listwy goldpin, kawałek listwy „żeńskiej”, potencjometr montażowy oraz przewody – fotografia 6.

W poprzednim odcinku napisaliśmy program termometru „diodowego”, który też wykorzystamy w ćwiczeniach. Ale na razie zajmijmy się tylko obsługą modułu wyświetlacza LCD. W tym celu wykorzystamy bibliotekę LiquidCrystal, która jest zawarta w pakiecie Arduino IDE.

Na początku programu – szkicu umieścimy dyrektywę dla kompilatora (#include), która pozwoli z tej biblioteki skorzystać.

Fot.6 Wyświetlacz przygotowany do podłączenia do Arduino

Następnie w programie setup() umieścimy polecenie, dzięki któremu w programie – szkicu niejako pojawi się nasz moduł wyświetlacza pod nazwą wysw. Mówiąc fachowo (cokolwiek by to znaczyło): stworzymy obiekt typu LiquidCrystal o nazwie wysw. Wykorzystujemy tu „minimalistyczny” tryb pracy wyświetlacza, w którym wystarczy określić, które (dowolne) piny Arduino dołączone są do wyprowadzeń: RS, EN D4, D5, D6, D7. W moim przypadku wykorzystane są piny Arduino o numerach 2…7, które są kolejnymi pinami portu D procesora ATmega328P (PD2…PD7).

Biblioteka LiquidCrystal oferuje też tryby pracy wykorzystujące więcej pinów. Od razu warto nadmienić, że istnieją podobne moduły wyświetlaczy LCD ze sterowaniem szeregowym oraz „adaptery szeregowe” do klasycznych wyświetlaczy. Wtedy trzeba wykorzystać inną, „szeregową” bibliotekę, a do sterowania wystarczą dwie linie (piny) Arduino. Jak na razie wyświetlacze LCD z szeregowym interfejsem są mało popularne. Powszechnie wykorzystujemy moduły klasyczne sterowane sześcioma liniami danych według rysunku 3. Z uwagi na różnorodność wersji wyświetlaczy, trzeba poinformować program, ile znaków w linii i ile linii ma użyty wyświetlacz.

Prościutki program wyświetlający napis: EdW Kurs Arduino i sygnalizujący upływ czasu zawarty jest w poniższym szkicu 1 (A0301):

#include <LiquidCrystal.h>
const int rs=2, en=3, d4=, d5=5, d6=6, d7=7;
//i tworzymy "wyświetlacz" o nazwie wysw
LiquidCrystal wysw (rs, en, d4, d5, d6, d7);
//tworzymy licznik - deklarujemy zmienną licz
int licz = 0;
void setup() {
wysw.begin(16, 2); //konfiguracja
// jednorazowo wyświetlamy napis:
wysw.print("EdW Kurs Arduino"); }
void loop() {
// ustawiamy kursor na początku drugiej linii:
wysw.setCursor(0, 1);
//i wyświetlamy stan licznika:
wysw.print(licz);
licz++; //inkrementuj (zwiększ) licznik
delay(1); //opóźnienie 1ms
} //koniec pętli loop()

W funkcji setup() jednorazowo wyświetlamy napis, który umieściliśmy w „podwójnym” cudzysłowie.

Potem w funkcji loop() pracuje prosty licznik, zwiększający co 1ms zawartość zmiennej licz typu int. W każdym obiegu pętli przenosimy kursor na początek dolnej linii i tam wyświetlamy zawartość licznika, pozostawiając niezmieniony napis w linii górnej. Także w wyświetlaczu numeracja linii i znaków zaczyna się od zera, więc instrukcja lcd.setCursor(0, 1); przenosi nas do pierwszego znaku w drugiej linii i tam wyświetlana jest zmieniająca się zawartość licznika.

Jeśli poczekasz trochę po rozpoczęciu pracy programu, to przekonasz się, że zmienna licz typu int może też zawierać liczby ujemne i ucieszysz się, że nasz wyświetlacz we współpracy z biblioteką LiquidCrystal dobrze radzi sobie z wyświetlaniem liczb ujemnych (reprezentowanych w liczniku w kodzie uzupełnienia do dwóch – U2). Jeśli jednak wykażesz jeszcze trochę cierpliwości, przekonasz się, że przy „zmniejszaniu licznika” w dolnej linii pozostają niepotrzebne zera – „śmieci pozostałe po dużej zawartości licznika”, ponieważ aktualnie wpisywana zawartość licznika nadpisuje wcześniejszą treść wyświetlacza, nie czyszcząc wcześniejszej.

Rys.7 Schemat termometru LCD

Przy okazji ujawnia się też inna kwestia: W programie mamy opóźnienie 1 milisekundy w każdej pętli. Zliczenie od zera do 32768 powinno więc zająć trochę ponad pół minuty. Tymczasem u mnie trwało to ponad półtorej minuty (93 sekundy). A przecież wiadomo, że procesor AVR z taktowaniem 16MHz jest bardzo szybki – wykonuje 16 milionów elementarnych operacji w ciągu sekundy, czyli 16 tysięcy w ciągu 1 milisekundy. Jak z tego widać, w każdej pętli nawet prosta obsługa wyświetlacza i inne pomocnicze procedury są czasochłonne – można szacować, że trwają około 1 milisekundy, co trzeba uwzględniać w niektórych programach. I na pewno typowe procedury Arduino nie powinny służyć do odmierzania czasu. Do tych ważnych kwestii jeszcze będziemy wracać.

Fot.8 Gotowy model

A na razie wracamy do wyświetlacza znakowego LCD. Biblioteka LiquidCrystal oferuje szereg przydatnych funkcji – poleceń. Między innymi możemy wyczyścić nasz wyświetlacz instrukcją wysw.clear(); W szkicu A0301.ino masz zakomentowane to polecenie, ale gdy je odkomentujesz, wyczyszczeniu ulegnie całość, w tym „jednorazowo” wyświetlony wcześniej górny napis. Możesz we własnym zakresie poeksperymentować z tym poleceniem.

Dla nas bardzo ważne jest, że biblioteka LiquidCrystal potrafi bez problemu wyświetlić nie tylko dodatnie i ujemne liczby, ale i ułamkowe ze zmiennych typu float. Aby się o tym przekonać, wykorzystajmy prymitywny termometr diodowy z poprzedniego odcinka i fragmenty kodu z wcześniejszego szkicu A0201. Schemat termometru LCD masz na rysunku 7, a mój model na fotografii 8. Wykorzystajmy szkic 2 (też zawarty w pliku A0301.ino), w którym nasz wyświetlacz nazywaliśmy lcd.

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int zADC; // obsługa termometru
float temp; // obsługa termometru
void setup() {
lcd.begin(16, 2);
//konfiguracja związana z termometrem:
pinMode(A0, INPUT_PULLUP);
analogReference(INTERNAL); }
void loop() {
zADC = 10 * analogRead(A0);
temp = map(zADC, 5170, 4910, 210, 310);
temp = temp / 10; // temperatura
//żeby wyświetlić ujemną wartość
// odejmujemy 30 stopni:
temp = temp - 30;
lcd.clear(); //czyścimy wyświetlacz
lcd.print("Temperatura");
lcd.setCursor(0, 1); //w dolnej linii:
lcd.print("wynosi: ");
//teraz wyświetlamy temperaturę ujemną
// ze zmiennej temp typu float:
lcd.print(temp, 1);
lcd.write(223); //symbol stopnia
lcd.print('C'); //duża litera C
delay(1000); }

Wynik pomiaru zgodnie z naszymi intencjami jest ujemny (fotografia 9), termometr działa – obrazuje zmiany temperatury, choć wskazanie niewiele ma wspólnego ze skalą Celsjusza. Jeśli masz kostkę LM35, możesz na podstawie poprzedniego odcinka zrealizować jak najbardziej praktyczny termometr pokojowy (który jednak nie zmierzy temperatur ujemnych). Możesz też z powodzeniem wykorzystać inne czujniki analogowe, niekoniecznie termometry.

Fot.9 Wynik pomiaru

Już tu widać, jak genialnie proste jest stworzenie z użyciem Arduino najróżniejszych mierników i przyrządów pomiarowych:

  • Bierzemy jakiś czujnik (sensor) i uzyskujemy z niego dane.
  • Przetwarzamy te dane do potrzebnej nam postaci i umieszczamy wynik w zmiennej odpowiedniego typu.
  • Wyświetlamy wynik, dodając do niego potrzebne napisy uzupełniające.

To naprawdę genialnie proste!

Jeśli są to Twoje pierwsze doświadczenia w zakresie programowania – po prostu ciesz się, że to może być takie łatwe!

A jeżeli wcześniej próbowałeś opanować oprogramowanie wyświetlacza LCD, zapewne dziwisz się, jak to wszystko można uprościć. Jest to możliwe dzięki wykorzystaniu w Arduino inteligentnej biblioteki LiquidCrystal.

Wykorzystanie jej rzeczywiście jest łatwe, ale nawet używając tej gotowej, bardzo pożytecznej biblioteki, powinniśmy pamiętać, że dotykamy tu wierzchołka góry lodowej. Stopniowo, w artykułach cyklu „Wokół Arduino” zgłębimy także trudniejsze zagadnienia z tym powiązane, ale na razie omówmy kwestie w miarę proste, a najbardziej potrzebne w praktyce.

I tak w szkicu 2 zmodyfikuj napisy przeznaczone do wyświetlenia. Spróbujmy w górnej linii zamiast: Temperatura, wyświetlić dłuższy napis: Aktualna temperatura. Składa się on z 20 znaków (wraz ze spacją), więc cztery ostatnie zostaną „obcięte” (fotografia 10). Notujemy, że choć program zna „długość wyświetlacza” (lcd.begin(16, 2);), nie przenosi „nadmiaru” do niższego wiersza. Wiersze wyglądają na niezależne (co, jak się jeszcze okaże, nie do końca jest prawdą).

Fot.10 'Obcięty' napis

Zazwyczaj rozumnie skracamy napisy, żeby niczego nie ucinać. Ale biblioteka LiquidCrystal oferuje funkcje (metody), pozwalające przesuwać napisy na wyświetlaczu. Z przesuwaniem górnego napisu nie ma problemu. Możemy nim „kołysać w dwie strony”, na przykład za pomocą dość specyficznego programu – szkicu 3 (zawartego w pliku A0301.ino).

Jednak „kołysanie” dotyczy całej zawartości wyświetlacza, a my chcemy mieć wynik wyświetlany nieruchomo. Łatwiej to zrealizujemy, przesuwając długi górny napis tylko w lewo. Zasadniczo przy okazji przesuniemy też dolną linię, ale będziemy w niej wynik nadpisywać z odpowiednim przesunięciem, żeby wydawał się nieruchomy.

W tym celu wykorzystamy pętlę for o czterech stanach dla czterech pozycji górnego napisu. Stan licznika pętli – pozycję wykorzystamy do przesunięcia kursora na pierwsze widoczne miejsce dolnej linii i napiszemy tam wynik, by wydawał się nieruchomy. Jedno z możliwych rozwiązań zawarte jest w poniższym szkicu 4:

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int zADC; float temp; //obsługa termometru
void setup() {
lcd.begin(16,2); pinMode(A0,INPUT_PULLUP);
analogReference(INTERNAL); }
void loop() { zADC = 10 * analogRead(A0);
temp = map(zADC, 5170, 4910, 210, 310);
temp = temp / 10 – 30;
lcd.clear(); //czyścimy wyświetlacz
lcd.print("Aktualna temperatura");
lcd.setCursor(0, 1); //w dolnej linii:
lcd.print("wynosi: "); lcd.print(temp, 1);
lcd.write(223); lcd.print('C');
delay(2000);
for(int pozycja=0; pozycja<4; pozycja++){
//przesuwamy napis w lewo
lcd.scrollDisplayLeft();
//natomiast w dolnej linii
//wyświetlamy wynik "z przesunięciem"
//zależnym od pozycji górnego napisu
lcd.setCursor(pozycja + 1, 1);
lcd.print("wynosi: "); lcd.print(temp, 1);
lcd.write(223); lcd.print('C');
delay(400); } //koniec pętli for
delay(2000); } //koniec funkcji loop()

Fragment kodu występuje tu dwukrotnie i należałoby umieścić go w oddzielnej funkcji. Jeśli chcesz, zrób to jako samodzielne zadanie domowe.

Mamy satysfakcję, że w tym trzecim odcinku kursu błyskawicznie nauczyliśmy się, jak w prosty sposób wykorzystać wyświetlacz znakowy LCD. Opanowaliśmy najważniejsze umiejętności: umiemy łączyć „stałe napisy” z zawartością zmiennych. Do wyświetlacza będziemy jeszcze wracać, choćby w kwestii wyświetlania „trudniejszych znaków”, w tym polskich liter.

A na razie możemy cieszyć się i eksperymentować, wykorzystując wyświetlacz LCD, łącze szeregowe i konsolę na ekranie komputera. Już teraz możesz zrealizować mnóstwo interesujących własnych układów/projektów, rozmaicie wykorzystując cyfrowe i analogowe wejścia i wyjścia Arduino. Zachęcam do samodzielnych działań, nawet gdyby wiązały się one z kłopotami, trudnościami i błędami. Z czasem będzie ich coraz mniej.

Na koniec jeszcze jeden bardzo ważny szczegół: Odcinki naszego prostego, elementarnego kursu Arduino nie są obszerne między innymi dlatego, żeby zachęcić wszystkich do zgłębiania także trudniejszych zagadnień, zawartych w artykułach serii „Wokół Arduino”. Niezależnie od stopnia zaawansowania, nie pomijaj tych dodatkowych materiałów!

Do pobrania
Download icon Materiały do: Kurs Arduino odcinek 3 - moduł wyświetlacza LCD
1. Kurs Arduino: wprowadzenie 2. Kurs Arduino odcinek 1 - co to jest i jak zacząć? (sprzęt, schematy, programowanie) 3. Kurs Arduino odcinek 2 - termometry: 'diodowy', pokojowy oraz 'scalony' analogowy 4. Kurs Arduino odcinek 3 - moduł wyświetlacza LCD (HD44780) 5. Kurs Arduino odcinek 4 - czujnik BME280 (pomiar ciśnienia, wilgotności i temperatury) 6. Kurs Arduino odcinek 5 - biblioteki do trzyfunkcyjnego czujnika BME280 7. Kurs Arduino odcinek 6 - wykorzystanie łącza I2C (TWI) 8. Kurs Arduino odcinek 7 - wykorzystanie łącza SPI (karty pamięci, MAX31865, MAX31855) 9. Kurs Arduino odcinek 8 - wykorzystanie czujnika dwutlenku węgla (MH-Z19) 10. Kurs Arduino odcinek 9 - wykorzystanie modułów do odmierzania czasu 11. Kurs Arduino odcinek 10 - wykorzystanie czujników temperatury (DS18B20) 12. Kurs Arduino odcinek 11 - budowa loggera (rejestratora danych) 13. Kurs Arduino odcinek 12 - rejestracja i prezentacja danych oraz obsługa karty SD 14. Kurs Arduino odcinek 13 - rejestracja danych (wykorzystanie modułu OpenLog) 15. Kurs Arduino odcinek 14 - czym zastąpić płytkę Arduino Uno? 16. Kurs Arduino odcinek 15 - budowa rejestratora (chiński klon Arduino Pro Mini) 17. Kurs Arduino odcinek 16 - problemy z kwadratowym modułem Strong 18. Kurs Arduino odcinek 17 - czujniki do pomiaru wilgotności gleby (instalacja, konfiguracja) 19. Kurs Arduino odcinek 18 - protokół MODBUS i łącze RS-485 20. Kurs Arduino odcinek 19 - wyświetlacze od podstaw (matrycowe, 7-segmentowe, MAX7219) 21. Kurs Arduino odcinek 20a - wyświetlacze matrycowe i biblioteki MD_MAX 22. Kurs Arduino odcinek 20b - przyciski i biblioteki do obsługi wyświetlaczy 23. Kurs Arduino odcinek 20c - biblioteki do obsługi wyświetlaczy graficznych 24. Kurs Arduino odcinek 21 - moduł wyświetlacza OLED 25. Kurs Arduino odcinek 22 - moduł wyświetlacza 1,3 cala 26. Kurs Arduino odcinek 23 - przygotowanie bitmap do wyświetlania 27. Kurs Arduino odcinek 24 - omówienie fontu podstawowego (Adafruit GFX) 28. Kurs Arduino odcinek 25 - font podstawowy biblioteki Adafruit GFX 29. Kurs Arduino odcinek 26 - wykorzystanie bitmapowych fontów GFX 30. Kurs Arduino odcinek 27 - polskie znaki w glcdfont.c 31. Kurs Arduino odcinek 28 - zmiana ulepszonych fontów GFX
AUTOR
Źródło
Elektronika dla Wszystkich maj 2018
Udostępnij
UK Logo