2.6. LCD ekrani
Što je LCD?
Kada kroz tekuće kristale protječe električna struja, oni mijenjaju svoj položaj. To utječe na način na koji svjetlo prolazi kroz njih.
Svjetlo prvo prolazi kroz prvi sloj polariziranog stakla, zatim kroz poravnate tekuće kristale koji zakreću svjetlo pod određenim kutom. Drugi sloj polariziranog stakla tada ili propušta to uvrnuto svjetlo ili ga blokira, ovisno o kutu zakreta.
Preciznim upravljanjem električnom strujom na različitim dijelovima (ili pikselima) tekućih kristala, LCD može selektivno propuštati ili blokirati svjetlo na određenim područjima. Tako nastaju slike, brojevi ili tekst koje vidiš na ekranu.
LCD 1602 – 16 stupaca i 2 reda
LCD 1602 je karakterni LCD zaslon koji standardno prikazuje 16 znakova u 2 reda. Unutra se nalazi matrica točkica (tipično 5×8 točkica po znaku) te upravljački čip (HD44780‑kompatibilan) koji pretvara naredbe i podatke iz mikrokontrolera u prikaz znakova na ekranu. Zaslon ima vlastitu video-memoriju (DDRAM) gdje se čuva koji se znak prikazuje na kojoj poziciji, kao i posebnu memoriju (CGRAM) za korisnički definirane znakove.
Klasični 1602 koristi paralelno sučelje: više podatkovnih linija (4 ili 8 bitova) plus kontrolni pinovi (RS, E, eventualno RW) izravno su spojeni na Arduino. U 8‑bitnom načinu šalje se cijeli bajt odjednom, dok se u 4‑bitnom načinu isti bajt šalje u dva dijela (dva nibblea), čime se štede pinovi, ali je komunikacija nešto sporija.
Danas se često koristi 1602 s I2C adapterom – malom pločicom na poleđini LCD‑a – koja pretvara serijsku I2C komunikaciju (SDA/SCL) u upravljanje paralelnim pinovima zaslona, pa umjesto desetak vodiča trebamo samo četiri (VCC, GND, SDA, SCL).
Paralelna veza ili I2C veza?
Paralelna veza:
- Više fizičkih vodiča (obično 6–10 signala + napajanje).
- Brza i jednostavna na razini protokola, ali zauzima velik broj Arduino pinova.
- U Arduino kôdu se standardno koristi biblioteka LiquidCrystal s definiranim pinovima za RS, E i D4–D7.
I2C veza:
- Samo dvije komunikacijske linije (SDA – podaci, SCL – sat), koje se mogu dijeliti s više uređaja.
- Svaki I2C uređaj ima jedinstvenu adresu na sabirnici; LCD modul s adapterom ima svoju I2C adresu koja se navodi u konstruktoru biblioteke.
Za radionicu koristimo LCD 1602 s I2C adapterom jer štedi pinove, pojednostavljuje ožičenje i omogućava nam da se usredotočimo na rad s tekstom i animacijama, a ne na šumu žica.
I2C (Inter‑Integrated Circuit) je serijski komunikacijski protokol koji koristi dvije linije: SDA (Serial Data) za podatke i SCL (Serial Clock) za takt. Na istoj sabirnici može biti jedan master (npr. Arduino) i više slave uređaja (LCD, senzori, memorija), a razlikuju se po I2C adresi koju master šalje na početku komunikacije.
Osnovni koraci prijenosa su:
- Master generira start uvjet (SDA nisko dok je SCL visoko), šalje adresu slave uređaja i informaciju radi li se čitanje ili pisanje.
- Slave potvrđuje prijem (ACK) i potom se šalju ili primaju bajtovi podataka, svaki ponovno potvrđen ACK signalom.
- Na kraju master šalje stop uvjet (SDA pušta na visoko dok je SCL visoko), čime završava komunikacijska sesija.
LiquidCrystal_I2C biblioteka – mogućnosti
LiquidCrystal_I2C je Arduino biblioteka za upravljanje HD44780‑kompatibilnim LCD zaslonima preko I2C sabirnice. Kod stvaranja objekta navodimo I2C adresu, broj stupaca, broj redaka i veličinu znaka, npr.:
LiquidCrystal_I2C lcd(0x27, 16, 2);.
Najvažnije mogućnosti:
begin()– inicijalizacija zaslona; mora se pozvati prije ostalih operacija.clear()ihome()– brisanje ekrana i pomicanje kursora na početak.
-print()/write()– ispis tekstova i znakova, kompatibilno s Arduino Print klasom.setCursor(col, row)– pozicioniranje kursora na određeni stupac i red.- Upravljačke funkcije:
display(),noDisplay(),cursor(),noCursor(),blink(),noBlink(),scrollDisplayLeft(),scrollDisplayRight(),autoscroll(),noAutoscroll(). backlight()inoBacklight()(odnosnosetBacklight()) – upravljanje pozadinskim osvjetljenjem.
-createChar(index, uint8_t[] pattern)/load_custom_character()– definicija vlastitih (custom) znakova u CGRAM memoriji.
Time biblioteka gotovo u potpunosti skriva detalje I2C komunikacije i niskorazinske naredbe kontrolera, pa možemo raditi s LCD‑om na razini postavi kursor – ispiši tekst.
Vježba 1. Hello, world! na LCD-u
U prvoj vježbi izradi klasičnu Hello, world! aplikaciju za LCD 1602:
- pravilno spoji LCD 1602 s I2C adapterom na Arduino (VCC, GND, SDA, SCL),
- u program uključiti Wire.h i LiquidCrystal_I2C.h, definiraj objekt zaslona i pozovi lcd.begin(),
- postavi kursor na početak (0,0) i ispiši poruku Hello, world! te eventualno svoje ime u drugom redu.
Napomena: Ako biblioteka LiquidCrystal_I2C ne postoji na računalu, preuzmi je ovdje. Raspakiraj je u direktorij Arduino/libraries.
// C++
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Postavi adresu na 0x27 za LCD 1602
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup()
{
lcd.begin();
lcd.backlight();
lcd.print("Hello, world!");
}
void loop()
{
// Ništa...
}
Dodatna pitanja i zadaci:
- Ispiši svoje ime u drugom redu ekrana.
Vježba 2. Pozicioniranje i skrolanje teksta
Druga vježba širi priču o LCD-u na rad s pojedinačnim znakovima i pomicanjem prikaza.
Trebaju nam ove funkcije:
setCursor(col, row)za precizno pozicioniranje teksta,scrollDisplayLeft()iscrollDisplayRight()za pomicanje sadržaja na ekranu.
Zadatak:
- U prvom redu ispiši naslov, npr. svoje ime.
- U drugom redu ispiši riječ (npr. Skrolam!).
- U petlji pomiči ekran desno pa lijevo korištenjem
scrollDisplayRight()iscrollDisplayLeft()u pravilnim vremenskim razmacima.
// C++
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Postavi adresu na 0x27 za LCD 1602
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup()
{
lcd.begin();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Arduino i LCD");
lcd.setCursor(0, 8);
lcd.print("Skrolam!");
}
void loop()
{
for (int i = 0; i < 16; i++)
{
lcd.scrollDisplayRight();
delay(500);
}
for (int i = 0; i < 16; i++)
{
lcd.scrollDisplayLeft();
delay(500);
}
}
Dodatna pitanja i zadaci:
- Napravi da se poruka pojavljuje izvan ekrana s desne strane i prolazi ulijevo kroz drugi red, kao traka s vijestima, a zatim u potpunosti nestane sa lijeve strane.
- Napiši redom više tekstova, koji će se ispisivati jedan nakon drugoga, kada prethodni u potpunosti nestane sa lijeve strane.
- Koje sve znakove možeš prikazati na LCD-u 1602? Prikaži ih sve, tako da se lagano skrolaju ulijevo.
- Napravi neku animaciju na ekranu, koristeći dostupne znakove.
Korisnički znakovi (custom characters)
Custom karakteri na LCD‑u 1602 omogućuju da na zaslonu prikažeš vlastite male sličice umjesto samo standardnih slova i brojeva. Riječ je o znakovima napravljenima od mreže od 5 stupaca i 8 redaka točkica (piksela), koje za svaki redak uključuješ ili isključuješ pomoću bitova u bajtu.
LCD kontroler ima posebnu memoriju (CGRAM) u koju možeš upisati najviše 8 takvih custom znakova, svaki definiran kao polje od 8 bajtova (koristi se samo donjih 5 bitova). Nakon što ih jednom definiraš u setupu (koristeći funkciju createChar()), u programu ih koristiš kao bilo koji drugi znak – ispisuješ ih s lcd.write(index) na željenu poziciju. Tako nastaju jednostavne ikone, strelice ili mali čovječuljci ili drugi spriteovi koji se mogu i animirati mijenjanjem više sličnih frameova.
Ovakva slika (sa lijeve strane) se pretvara u binarne vrijednosti (sa desne strane), a u kodu se predstavlja kao niz (array) binarnih podataka:
uint8_t man1[8] = {
B00100,
B01110,
B00100,
B01110,
B10100,
B00100,
B01010,
B10001
};
Vježba 3. Čovječuljak koji hoda
U trećoj vježbi koristimo znakove koje ćemo sami napraviti (custom characters) i koristiti kao spriteove, za izradu mini animacije čovječuljka koji hoda s lijeve na desnu stranu LCD ekrana.
Sprite je mala slika ili lik koji se crta iznad pozadine u igri i može se pomicati, sudarati s drugim objektima i mijenjati izgled (animacija).
Što je sprite u igrama?
Sprite je slika (bit-mapa) koja je dio veće scene, najčešće u 2D video igrama.
Može predstavljati lika, neprijatelja, metak, novčić, gumb ili bilo koji objekt koji živi u igri.
Animacija spritea nastaje nizom sličica (frameova) – npr. hod likа se crta kao više pozicija tijela i prikazuju se redom.
Često se više spriteova spaja u tzv. sprite sheet, jednu veliku sliku iz koje se izrezuju pojedinačni frameovi.
Primjer: Super Mario animacija
U Super Mario igri, Mario, gljiva, novčić i neprijatelji su spriteovi koji se kreću po pozadini. Ovdje je prikazan Mario:
Kako se spriteovi koriste u igrama?
Logika igre (programski kôd) odlučuje gdje se sprite crta, koliko brzo se pomiče i što se dogodi pri sudaru s drugim spriteom.
Svaki sprite ima svoje osobine: položaj (X, Y), brzinu, smjer, sliku koju trenutno prikazuje (frame animacije).
U korisničkom sučelju (dugmad, ikone) spriteovi se koriste kao male slike na koje možemo reagirati klikom ili dodirom.
Alati za dizajniranje korisnički definiranih znakova
U ovoj vježbi će nam jako pomoći neki alat za dizajniranje korisnički definiranih (custom) znakova. Jedan od njih je Chareditor.
Sa lijeve strane nacrtaj razne znakove na određenim pozicijama nacrtanog LCD-ekrana, a sa desne strane će se automatski generirati kôd za te znakove.
U svoj kôd iskopiraj samo definicije binarnih nizova.
Zadatak:
- Dizajniraj barem dvije verzije čovječuljka (različit položaj nogu/ruku) u obliku 5×8 matrica,
- Učitaj te uzorke u CGRAM pomoću
createChar(), - U petlji ispisuj čovječuljka na različitim pozicijama (npr. stupac 0 do stupac 15) i naizmjenično mijenjaj korišteni custom znak kako bi se dobio efekt hodanja.
// C++
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// prilagodi adresu ako treba (0x27 ili 0x3F su najčešće)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Dizajn 2 frame-a čovječuljka (5x8 točaka)
// Svaki red je 5 bita (u donjem dijelu bajta); 8 redova po znaku
uint8_t man1[8] = {
B00100,
B01110,
B00100,
B01110,
B10100,
B00100,
B01010,
B10001
};
uint8_t man2[8] = {
B00100,
B01110,
B00100,
B01110,
B00101,
B00110,
B01000,
B10000
};
void setup() {
lcd.begin();
lcd.backlight();
lcd.createChar(0, man1);
lcd.createChar(1, man2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Covjeculjak hoda");
delay(1500);
}
void loop() {
for (int col = 0; col < 16; col++) {
lcd.setCursor(col, 1);
// biramo frame: na parnim stupcima man1, na neparnim man2
if (col % 2 == 0) {
lcd.write((uint8_t)0);
} else {
lcd.write((uint8_t)1);
}
// kratka pauza da se vidi animacija
delay(200);
// obrišemo čovječuljka na trenutnoj poziciji
lcd.setCursor(col, 1);
lcd.print(" ");
}
delay(500);
}
Dodatna pitanja i zadaci:
- Je li izrada spriteova ograničena samo na jedan korisnički definiran (custom) znak? Objasni.
- Možeš li napraviti primjer takvog spritea koji prelazi granice jednog znaka?
- Na koja ograničenja si naišao prilikom izrade animacije pomoću spriteova većih od jednog korisnički definiranog znaka?
Što smo naučili?
- Kako LCD zasloni funkcioniraju na razini tekućih kristala, polarizirane svjetlosti i pozadinskog osvjetljenja.
- Upoznali smo se s LCD‑om 1602 kao karakternim zaslonom s 16 stupaca i 2 reda, te razlikom između paralelnog i I2C načina spajanja na Arduino.
- Korištenje osnovne upotrebe biblioteke LiquidCrystal_I2C – inicijalizaciju, ispis teksta, pozicioniranje kursora i skrolanje sadržaja.
- Kako dizajnirati i koristiti korisnički definirane (custom) karaktere za jednostavne animacije.
