Wyświetlacze LCD

LCD16x2

W trakcie budowy sterownika (czy to do akwarium czy jakiegokolwiek innego), który wykonuje kilka rzeczy których informacje nie są oczywiste (działa / nie działa) warto pomyśleć o jakimś sposobie odczytywania ich z Arduino. Służy do tego np. wyświetlacz LCD

Najpopularniejszym sposobem „sprawdzania” działania programu jest podłączenie Arduino pod wyświetlacz LCD. Dzięki niemu w łatwy i szybki sposób bez użycia komputera wiemy co dzieje się aktualnie z programem.

Metody odczytywania informacji z Arduino:

  • monitor szeregowy – najłatwiejszy sposób – odczyt po podłączeniu do komputera za pomocą portu szeregowego
  • diody sygnalizacyjne (jedno i wielokolorowe) – wadą jest zajmowanie kolejnych portów
  • wyświetlacze cyfrowe – rozwiązanie sprawdzające się w przypadku wyświetlania cyfr (np. temperatury)
  • moduły ethernet – pozwalające za pomocą przeglądarki (podobnie jak to jest w przypadku monitora szeregowego) wyświetlać informacje zarówno tekstowe jak i ciągli liczb – wada – trzeba mieć podłączony komputer
  • wyświetlacz LCD – chyba jedno z najbardziej optymalnych rozwiązań i najbardziej wszechstronnych. Skupmy się więc na nich.

Podłączenie wyświetlacza LCD do Arduino może odbyć się na dwa sposoby. Pierwszym z nich jest podłączenie bezpośrednie bez żadnego konwertera – minusem jest to, że zajęte zostaje 6 pinów cyfrowych.

LCD

Poniżej pokazany jest prosty kod, który pozwala na wyświetlenie informacji na wyświetlaczu 2×16 znaków. Wyświetla on prosty komunikat w pętli.
#include <LiquidCrystal.h>           //Dołączenie biblioteki
LiquidCrystal (2,1,0,4,5,6,7);       //adres wyświetlacza 
void setup() 
  {
    lcd.begin(16, 2);                //Wybieramy typ wyświetlacza (jego wielkość) 
  }
void loop() 
  {
    lcd.setCursor(0, 0);            //Ustawienie kursora na pierwszej linii i pierwszym znaku
    lcd.print("___MN-Tech.pl___");  //Wyświetlenie tekstu
    lcd.setCursor(0, 1);            //Ustawienie kursora na drugiej linii i pierwszym znaku
    lcd.print("____Test_LCD____");  //Wyświetlenie tekstu
    delay(1000);                    //opóźnienie skryptu o 1s
    //site mn-tech.pl
    //youtube https://www.youtube.com/user/mntechpl
    //facebook https://www.facebook.com/mntechpl
  }

Pomimo tego iż kod jest bardzo prosty to od razu po podłączeniu wyświetlacza z 13 pinów cyfrowych Arduino zostaje nam już tylko 7. Rozwiązaniem tego problemu jest moduł działający na magistrali I2C (IIC) który podpina się pod piny A4 (SDA – data) oraz A5 (SCL – clock) oraz GND i 5V. Dzięki takiemu rozwiązaniu całą transmisja zajmuje tylko 2 piny analogowe. Kolejne urządzenia można podpinać do tej magistrali równolegle do poprzednich.

Dodatkowo np. moduł I2C do wyświetlacza ma możliwość adresacji. Można dzięki temu podpiąć nawet 8 różnych wyświetlaczy tego samego typu. Moduły te różnią się też pomiędzy sobą modelami (PCF8547T oraz PCF8574AT). Mają one rożne adresacje. Daje to znowu kolejne adresy, które można użyć. Najłatwiejszym sposobem do znalezienia odpowiedniego adresu jest podpięcie urządzenia do arduino oraz wgranie programu do odczytania adresów podłączonych urządzeń.

Oczywiście z magistrali I2C korzystają także inne urządzenia – będą opisane w późniejszych artykułach.

Wracając więc do wyświetlacza podłączonego poprzez moduł I2C podłączenie wygląda znacznie łatwiej niż na zdjęciu powyżej.

LCD I2C

Jak widać podłączenie jest znacznie bardziej czytelne – załatwiamy sprawę 4 kablami i dodatkowo mamy wszystkie piny cyfrowe wolne. Kod do programu zmienia się w bardzo małym stopniu.

#include <LiquidCrystal_I2C.h>                   //użyte biblioteki
#include <Wire.h>                                //użyte biblioteki
#define BACKLIGHT_PIN 3                          //pin podświetlenia wyświetlacza
LiquidCrystal_I2C lcd(0x27, 2,1,0,4,5,6,7);      //adres wyświetlacza 
 
void setup()
  {
    lcd.begin(16,2); //lcd
    Wire.begin();
    lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
    lcd.setBacklight(HIGH);
  }
void loop()
  {
    lcd.setCursor(0, 0); //Ustawienie kursora na pierwszej linii i pierwszym znaku   
    lcd.print("___MN-Tech.pl___");   //Wyświetlenie tekstu   
    lcd.setCursor(0, 1);             //Ustawienie kursora na drugiej linii i pierwszym znaku   
    lcd.print("__LCD I2C 16x2__");   //Wyświetlenie tekstu 
    delay(1000);                     //opóźnienie skryptu o 1s  
    //site mn-tech.pl
    //youtube https://www.youtube.com/user/mntechpl
    //facebook https://www.facebook.com/mntechpl  
  }

Zmieniona została biblioteka (testowane na wersji 1.6.1) – biblioteki i programy można pobrać ze strony w części o wgrywaniu programu do arduino.

Aby ustawić kursor w danym miejscu i wyświetlić odpowiednie informacje funkcją lcd.print używamy komendy lcd.setCursor(x, y); gdzie x to numer znaku a y to numer wiersza.

Numeracja rozpoczyna się od 0 więc pierwszy znak w pierwszym wierszu ma numer 0,0 ostatni 15,0 itd (na przykładzie wyświetlacza 16×2). Wyświetlacz LCD mający 2 rzędy po 16 znaków ma następującą numerację:

wyświetlacz LCD 16x2

 

A co jeśli mamy wyświetlacz LCD inny niż 16×2 znaki?

Pomimo tego iż powyższy skrypt ma oznaczoną wielkość wyświetlacza na 16 znaków w 2 rzędach bez problemu działa także na większych lub też mniejszych wyświetlaczach (1×8, 4×20). Jeśli chcemy użyć wyświetlacza np. 1×8 wtedy numeracja poszczególnych pól będzie przebiegać od 0,0 do 7,0.

Problem pojawia się gdy mamy wyświetlacz LCD 4-wierszowy (np 4×20). Numeracja nie przebiega w sposób oczywisty i 3 oraz 4 rząd to w zasadzie kontynuacja numeracji wierszy 1 i 2. Dla ułatwienia została utworzona poniższa grafika gdyż samo wyjaśnienie „na sucho” jest dość zagmatwane.

wyświetlacz 20x4 znaki

Jak widać numeracja przebiega dla 1 i 3 rzędu od 0,0 do 39,0 a dla 2 i 4 rzędu od 0,1 do 39,1. Jeśli posiadacie taki wyświetlacz możecie go przetestować wgrywając do niego poniższy kod:

#include <LiquidCrystal_I2C.h> //użyte biblioteki 
#include <Wire.h> //użyte biblioteki 
#define BACKLIGHT_PIN 3 //pin podświetlenia wyświetlacza 
LiquidCrystal_I2C lcd(0x27, 2,1,0,4,5,6,7); //adres wyświetlacza 

void setup() 
  { 
    lcd.begin(16,2); //lcd Wire.begin(); 
    lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE); 
    lcd.setBacklight(HIGH);
  } 

void loop() 
  { 
    lcd.setCursor(0, 0); //Ustawienie kursora na pierwszej linii i pierwszym znaku 
    lcd.print("__ODWIEDZ___STRONE__"); //Wyświetlenie tekstu na 1 linii
    lcd.print("_TEST__WYSWIETLACZA_"); //Wyświetlenie tekstu na 3 linii
    lcd.setCursor(0, 1); //Ustawienie kursora na drugiej linii i pierwszym znaku 
    lcd.print("_____MN-Tech.pl_____"); //Wyświetlenie tekstu na 2 linii
    lcd.print("_LCD I2C 20X4 ZNAKI_"); //Wyświetlenie tekstu na 4 linii
    delay(1000); //opóźnienie skryptu o 1s
  }

Jak widać informacje były wyświetlane od góry do dołu – można to zrobić oczywiście chronologicznie (używając komend lcd.setCursor(x, y); do wybrania pozycji). Fragment odpowiedzialny już sa same wyświetlanie wyglądał by następująco:

lcd.setCursor(0, 0);                //Ustawienie kursora na pierwszej linii i pierwszym znaku 
lcd.print("__ODWIEDZ___STRONE__");  //Wyświetlenie tekstu na 1 linii  
lcd.setCursor(0, 1);                //Ustawienie kursora na drugiej linii i pierwszym znaku 
lcd.print("_____MN-Tech.pl_____");  //Wyświetlenie tekstu na 2 linii 
lcd.setCursor(20, 1);               //Ustawienie kursora na trzeciej linii i pierwszym znaku 
lcd.print("_TEST__WYSWIETLACZA_");  //Wyświetlenie tekstu na 3 linii  
lcd.setCursor(20, 1);               //Ustawienie kursora na czwartej linii i pierwszym znaku 
lcd.print("_LCD I2C 20X4 ZNAKI_");  //Wyświetlenie tekstu na 4 linii

Jak widać efekt uzyskany jest ten sam ale przejrzystość kodu jest nieporównywalnie większa. Pamiętajcie o tym, że jeśli kod zostanie poukładany w sposób przejrzysty to ewentualne poprawianie błędów czy zmienianie go będzie dużo łatwiejsze.

Rozmieszczanie rzeczy na wyświetlaczu

Układ informacji na wyświetlaczu zawsze stanowi spory problem. Wiadomo miejsce jest ograniczone i czasem nie wiadomo jak się do tego zabrać (przeważnie jak pies do jeża 🙂 ). Najlepszym rozwiązaniem jest użycie arkusza kalkulacyjnego. Robimy w nim prostokąt o wymiarach naszego wyświetlacza wpisujmy numery wierszy i rzędów i ustawiamy tekst pamiętając o tym, że każdy znak to jedna kratka. Wyświetlacz LCD mający 4 rzędy po 20 znaków ma następującą numerację:

LCD - Przykład

Jest to przykład wyjęty z mojego sterownik domowego. Dzięki prostemu poukładaniu sobie całego układu a także menu (i podmenu) w dość przejrzysty sposób wiemy gdzie ustawić kursor, żeby wszystko pasowało do siebie.

Jest to znacznie lepsze niż wgrywanie kodu po kawałku i patrzenie co się stanie. Patrząc na powyższy rysunek litera T która odpowiada za termometr jest umiejscowiona (zgodnie z opisem) na polu 9,1 a litera C na polu 35,1.

Pamiętajcie także o tym, że dopóki nie zmienicie ustawienia kursowa informacje będą się pojawiały w ciągu. Można więc ograniczać ilość zmian kursora (a tym samym wielkość skryptu) – idealnym przykładem może być wyświetlanie pH i kawałek za nim temperatury. trzeba tylko pamiętać o dodatkowych spacjach. Inaczej tekst będzie zaraz za sobą.

Informacje przedstawione w powyższym tekście są przedstawione dość skrótowo. Wystarczają w zupełności do tego, żeby umieścić na wyświetlaczu wszystkie potrzebne informacje. Więcej informacji dotyczących LCD musicie szukać na internecie. Jest tego sporo (migający tekst, przewijanie, czyszczenie wyświetlacza itp) niemniej jednak podstawowa komenda lcd.print wystarcza w 100% zwłaszcza w początkowym etapie nauki programowania.

Na koniec film z krótkim wyjaśnieniem.