Arduino Projekten

Mon 21-Jan-19
15:48:28




LCD - Eerste aansluiting.

Datum: Sat 20 June 2015
Samenvatting: De eerste aansluitingen van een LCD (20x4 tekens en RGB-background-light) op de Arduino Uno


De ArSid gaat een LCD-Display krijgen en wel een van 4 regels met 20 tekens en met een RGB-backlight. Er moet geoefend worden om zo'n LCD met de Arduino aan te kunnen sturen.

Allereerst de aansluitingen. Bij de meeste LCD experimenten worden er pennen aan de LCD-unit gesoldeerd (male-connector), zodat deze rechtstreeks in een breadboard kan worden gestoken. Voor meer flexibiliteit in het experimenteren besloot ik om er een gaatjes-connector (female-connector) aan te solderen en de aansluitingen met Arduino-draadjes te maken.

Doorspitten van documentatie over de LCD-units leert dat de aansluitingen (en wel van links-boven (nr.1) naar midden-boven (nr.18)) als volgt zijn. Gelukkig staan deze aansluiting-nummers ook op het display zelf:

PinNaam Functie Kleur draad
1 Gnd Ground Zwart Gnd
2 Vcc +5V Lcd Rood +5V
3 Vlcd Lcd Display Bias Groen Potmeter Loper
5 Rs Register Select: L=Command H=DataBlauw Arduino D12
4 R/W Read/Write: L=Write H=Read Blauw Gnd
6 Enable Enable H->L=Accept Data Blauw Arduino D13
7 D0 Data I/O 0 Geel Gnd
8 D1 Data I/O 1 Geel Gnd
9 D2 Data I/O 2 Geel Gnd
10 D3 Data I/O 3 Geel Gnd
11 D4 Data I/O 4 Oranje Arduino D8
12 D5 Data I/O 5 Oranje Arduino D9
13 D6 Data I/O 6 Oranje Arduino D10
14 D7 Data I/O 7 Oranje Arduino D11
15 Anod. VccBacklight Common Anode Rood +5V
16 Kat. Rood Backlight Rood Wit Gnd
17 Kat. GroenBacklight Groen Wit Gnd
18 Kat. BlauwBacklight Blauw Wit Gnd

Het blijkt dat deze aansluitingen niet veranderd zijn dan ik in een oud databoekwerk "Liquid Crystal Display" van Optrex (uit 1989) vond. Bestuderen van de aansturing vanuit het programma tegenwoordig en vanuit dat databoek geeft aan dat ook dat hetzelfde is gebleven. En eigenlijk vind ik dat dit databoekwerk duidelijker is in het aansturen van de LCD-Displays, dan de tabellen die ik op internet gevonden heb. Niet alleen staan hun afmetingen erin, maar ook duidelijke tijdsdiagrammen, aansluit- en aanstuur-tabellen.

De LCD-unit kent zowel een 8-bits als een 4-bits aansturing. Hoewel ik de LCD in de ArSid met 8-bits wil aansturen, heb ik hier eerst de 4-bits aansturing gebruikt ... maar dat is nog niet meegevallen. De LCD-pinnen D0 .. D3 moeten met de GND worden verbonden. De bits voor deze pinnen gaan door de pinnen D4 .. D7.

De "Lcd Display Bias" moet wel met de loper van een potmeter (tussen Vcc en Gnd) worden verbonden (op de foto: het groene draadje naar het blauwe rondje met pijl).

Een LCD heeft twee registers, een Data Register en een Commando Register. Welke ervan de data op de aansluitingen D0..D7 gaat ontvangen, hangt af van de aansluiting Rs (Register Select). Is deze aansluiting LAAG, dan gaat de data naar het Commando Register. Bij HOOG gaat de data naar het Data Register.

LCD - Het Commando Register.

Dit register regelt diverse instellingen en algemene functies van de LCD (waaronder Blink, ClearScreen, GotoXY, HomeCursor).

D7 D6 D5 D4 D3 D2 D1 D0 Omschrijving
0 0 0 0 0 0 0 1 ClearScreen & Home Cursor
0 0 0 0 0 0 1 * Home Cursor, of te wel de Cursor gaat naar de eerste positie op het scherm en de Scherm verschuiving wordt op 0 gezet
0 0 0 0 0 1 I/D S Instellen Cursor Richting I/D=LAAG Omlaag | I/D=HOOG Omhoog
S=LAAG Zonder Scherm Shift | S=HOOG Met Scherm Shift
0 0 0 0 1 D C B D=LAAG Zet Display Uit | D=HOOG Zet Display Aan
C=LAAG Zet Cursor Uit | C=HOOG Zet Cursor Aan
B=LAAG Geen Cursor Blink | B=HOOG Blink Cursor Positie
0 0 0 1 S/CR/L * * S/C=LAAG Cursor Verplaatsen | S/C=HOOG Scherm Verschuiven
R/L=LAAG Schuif naar Links | R/L=HOOG = Schuif naar Rechts
0 0 1 DL N F * * DL=LAAG 4-bits Data | DL=HOOG 8-bits Data
N=LAAG 1/8 of 1/11 Duty | N=HOOG 1/16 Duty
F=LAAG 5*7 Pixel Tekens | F=HOOG 5*10 Pixel Tekens
0 1 Cg5Cg4Cg3Cg2Cg1Cg0Cg0..Cg5 = Adres Character Ram (voor zelf gedefinieerde tekens)
1 Dd6Dd5Dd4Dd3Dd2Dd1Dd0Dd0..Dd6 = Adres Data Cursor (soort van GotoXY) in tekens vanaf linksboven

Voor de Adres Data Cursor zijn maar 7 bits gereserveerd. Dit betekent dus dat er maar 128 lokaties mogelijk zijn. Voldoende voor 2x40 of 4x20 displays.

Het Commando Register kan ook uitgelezen worden en geeft dan de volgende gegevens terug.

D7 D6 D5 D4 D3 D2 D1 D0 Omschrijving
BF Ac6Ac5Ac4Ac3Ac2Ac1Ac0Busy Flag BF=LAAG Accepteerd Instructies | BF=HOOG Interne Verwerking is Bezig
Ac0..Ac6 = Adres Counter (soort van WhereXY) (zowel Character Ram als Data Cursor

Maar meestal wordt het uitlezen niet gebruikt.

LCD - Het Data Register.

Via dit register kunnen de tekens op het scherm worden gezet en wel op de positie die de cursor aangeeft. Bij standaard instellen van de cursor naar rechts, zullen de tekens van links naar rechts op het scherm worden geplaatst. Het zetten van de cursor op een andere plek (via commando %1Dd (bit 7 = %1; bit 6..0=cursor positie)) zullen de tekens vanaf deze locatie worden neergezet.

Eigen tekens worden ook via dit Data Register opgegeven, echter dan moet eerst het commando %01Cg (bit 76 = %10; bit5..0=Adres Character Ram) worden opgegeven, waarna de data in opeenvolgende plaatsen van het Character Ram worden geplaatst en wel bit4..0 (bit7..5 worden dus niet gebruikt).

Ook het Data Register kan worden gelezen. Dan krijgt men de inhoud van betreffende teken-positie terug, OF de inhoud van het Character-Ram. Maar net als bij het Commando Register wordt ook dit niet vaak gebruikt.

Achtergrond Verlichting.

Ik heb gekozen voor achtergrond verlichting met RGB-Led. Net als bij de RGB-Led van de Arduino basis-set, heeft die van het LCD-display een gemeenschappelijke anode en kunnen de aparte kleuren worden gekozen door betreffende R, G en B aansluiting met de Gnd te verbinden, of door deze (middels PWM) met de Arduino aan te sturen.

Het Programma.

De initialisatie van de LCD-unit is tijdgevoelig, als in: dit mag niet te snel gebeuren. Er zijn extra vertragingen nodig, terwijl er eerst 3 keer de 8bit-interface moet worden opgegeven.

Daarna wordt de uiteindelijke databus breedte opgegeven (hier 4-bits), tesamen door de benodigde display-instellingen (2 regels tekst en een 5x8 font). Waarom 2 regels tekst opgeven, terwijl er 4 regels zijn? Het blijkt dat na het volschrijven van regel 1, er wordt verder gegaan op regel 3. Daarna komt regel 2 en wanneer deze vol is geschreven, wordt op regel 4 verder gegaan. Dus het is eigenlijk een 2x40 LCD, waarvan de rechterhelft onder de linkerhelft is "gemonteerd" (zie foto).

Er moeten enkele display-instellingen worden uitgezet, zoals het display zelf, de cursor en het knipperen van de cursor.

Na het wissen van het display worden de juiste display-instellingen opgegeven (display aan, cursort uit/aan knipperen uit/aan).

Er volgen nog 2 display-shift-instellingen (cursor/ display-shift; links/ rechts opschuiven en niet/ wel opschuiven).

Het programma is recht-toe recht-aan geschreven. De pin-nummers worden apart opgegeven en geadresseerd met eenvoudige IF (bit-waarde) THEN digitalwrite HIGH/LOW. Benodigde vertragingen (DELAY(x)) zijn nog aan de hoge kant. Maar de basis is er.

Eigen tekens opgeven.

Er worden hier al 8 eigen tekens opgegeven en wel met 64 regels met binaire data. De tekens zijn (per 2 tekens) Blokgolf, Driehoekgolf, Zaagtandgolf, Ruisgolf. Tekens die in de ArSid ook gebruikt moeten gaan worden (zie tweede regel op de foto).

Nu dit deel ook werkt, is uitbreiding naar meer eigen tekens (ADSR-grafiek, filter-type) eenvoudig ... echter ... er kunnen maar maximaal 8 eigen tekens tegelijk worden getoond.

En verder?

Er zijn verbeteringen nodig. De uiteindelijke uitsturing gata met een 8-bits databus. De vertragingen moeten kleiner. Er gaat direct-port programering worden gebruikt.

Uiteindelijk zullen eerder genoemde vertragingen bij het aansturen van de SIDs zelf duidelijk hoorbaar worden in het geproduceerde geluid.

En wellicht gaat er een interupt-functie worden gebruikt om de tekens naar het display te sturen, zonder dat het hoofd programma zelf hoeft te wachten tot het display de data heeft geaccepteerd.


Broncode: [1: LCD - Eerste aansluiting.]

1: De broncode van LCD - Eerste aansluiting.

(Sat 20 June 2015) De eerste aansluitingen van een LCD (20x4 tekens en RGB-background-light) op de Arduino Uno

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// Exploring Program for a LCD 20x4
//
// 4 Bit Interface
//

byte lcd_d0  =  8; // Data 0
byte lcd_d1  =  9; // Data 1
byte lcd_d2  = 10; // Data 2
byte lcd_d3  = 11; // Data 3
byte lcd_rs  = 12; // Register Select
byte lcd_en  = 13; // Enable
byte led_pwr =  2; // Power led

byte qqstart=0;
byte qq=32;

void setup ()
{
lcd_init();
pinMode(led_pwr,OUTPUT);
}

void loop ()
{
digitalWrite(led_pwr,HIGH);
delay( 5);
digitalWrite(led_pwr,LOW);
delay( 5);

// Write a char to the LCD
do_lcd_write(1, qq);
if (qq <=255)    { qq=qq+1; } else { qq=qqstart; }
}

void lcd_init ()
{
pinMode(lcd_d0, OUTPUT);  digitalWrite(lcd_d0,  LOW);
pinMode(lcd_d1, OUTPUT);  digitalWrite(lcd_d1,  LOW);
pinMode(lcd_d2, OUTPUT);  digitalWrite(lcd_d2,  LOW);
pinMode(lcd_d3, OUTPUT);  digitalWrite(lcd_d3,  LOW);
pinMode(lcd_rs, OUTPUT);  digitalWrite(lcd_rs,  LOW);
pinMode(lcd_en, OUTPUT);  digitalWrite(lcd_en,  LOW);
//--------------------------------------------------------------------------------------------------------
delay(20);                          // Wait while the LCD-unit itself is initialized
do_lcd_write(4, B00110000);    // 1st LCD write (set 8bits interface)
delay(6);                           // Wait some
do_lcd_write(4, B00110000);    // 2nd LCD write (set 8bits interface)
delay(1);                           //  Wait some more
do_lcd_write(4, B00110000);    // 3rd LCD write (set 8bits interface)
//--------------------------------------------------------------------------------------------------------
do_lcd_write(4, B00100000);    // Now DO the correct LCD initializing (4bits)
do_lcd_write(0, B00101000);    // Function-Set 4-bits, 2-lines, 5x8-font, <none>, <none>
do_lcd_write(0, B00001000);    // Set Display On/Off Control: Cursor, Blinking
do_lcd_write(0, B00000001);    // Clear Display
do_lcd_write(0, B00001110);    // Set Display On/Off Control: Cursor, Blinking
do_lcd_write(0, B00010100);    // Set Cursor/ Display Shift: Shift/Cursor, Right/Left, <none>, <none>
do_lcd_write(0, B00000110);    // Entry Mode Set: Inc/Dec, DisplShift
//--------------------------------------------------------------------------------------------------------
make_lcd_chars();
do_lcd_write(0, 128 +   0);    // Home the Crsr
}

void do_lcd_write (byte rr, byte dd)
{
// Write Register (0) or Data (1)?
if ((rr & 0x01) == 0) { digitalWrite(lcd_rs, LOW)} else {digitalWrite(lcd_rs, HIGH)};

// Sent bit  7..4
digitalWrite(lcd_en,  HIGH);
if ((dd & 0x10) == 0) { digitalWrite(lcd_d0, LOW)} else { digitalWrite(lcd_d0, HIGH)}
if ((dd & 0x20) == 0) { digitalWrite(lcd_d1, LOW)} else { digitalWrite(lcd_d1, HIGH)}
if ((dd & 0x40) == 0) { digitalWrite(lcd_d2, LOW)} else { digitalWrite(lcd_d2, HIGH)}
if ((dd & 0x80) == 0) { digitalWrite(lcd_d3, LOW)} else { digitalWrite(lcd_d3, HIGH)}
delay(1);
digitalWrite(lcd_en,  LOW);
delay(1);

// Sent lower bits when not initializing
if ((rr) < 4)
   { // Sent bit 3..0
     digitalWrite(lcd_en,  HIGH);
     if ((dd & 0x01) == 0) { digitalWrite(lcd_d0, LOW)} else { digitalWrite(lcd_d0, HIGH)}
     if ((dd & 0x02) == 0) { digitalWrite(lcd_d1, LOW)} else { digitalWrite(lcd_d1, HIGH)}
     if ((dd & 0x04) == 0) { digitalWrite(lcd_d2, LOW)} else { digitalWrite(lcd_d2, HIGH)}
     if ((dd & 0x08) == 0) { digitalWrite(lcd_d3, LOW)} else { digitalWrite(lcd_d3, HIGH)}
     delay(1);
     digitalWrite(lcd_en,  LOW);
     delay(1);
   }
}

void make_lcd_chars ()
{
do_lcd_write(0,64);
do_lcd_write(1, B00000000);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00011111);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00011111);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00000000);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000010);
do_lcd_write(1, B00000100);
do_lcd_write(1, B00001000);
do_lcd_write(1, B00010000);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00010000);
do_lcd_write(1, B00001000);
do_lcd_write(1, B00000100);
do_lcd_write(1, B00000010);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000000);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00000000);
do_lcd_write(1, B00000000);
do_lcd_write(1, B00000000);
do_lcd_write(1, B00000011);
do_lcd_write(1, B00001100);
do_lcd_write(1, B00010000);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000111);
do_lcd_write(1, B00011001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00000001);
do_lcd_write(1, B00001001);
do_lcd_write(1, B00001001);
do_lcd_write(1, B00001101);
do_lcd_write(1, B00010010);
do_lcd_write(1, B00000000);

do_lcd_write(1, B00000000);
do_lcd_write(1, B00000010);
do_lcd_write(1, B00000011);
do_lcd_write(1, B00010101);
do_lcd_write(1, B00010101);
do_lcd_write(1, B00001101);
do_lcd_write(1, B00001000);
do_lcd_write(1, B00000000);

do_lcd_write(0, B00000010);
}

//=======================================================================================



Broncode: [1: LCD - Eerste aansluiting.]

Afbeeldingen

lcd1_1.jpg
1/9: lcd1_1.jpg.
lcd1_2.jpg
2/9: lcd1_2.jpg.
lcd1_3.jpg
3/9: lcd1_3.jpg.
lcd1_4.jpg
4/9: lcd1_4.jpg.
lcd1_5.jpg
5/9: lcd1_5.jpg.
lcd1_optrex_2x40_1991.jpg
6/9: lcd1_optrex_2x40_1991.jpg.
lcd1_optrex_databoek_1.jpg
7/9: lcd1_optrex_databoek_1.jpg.
lcd1_optrex_databoek_2.jpg
8/9: lcd1_optrex_databoek_2.jpg.
lcd1_optrex_databoek_3.jpg
9/9: lcd1_optrex_databoek_3.jpg.

De aansluitingen van LCD - Eerste aansluiting.

De eerste aansluitingen van een LCD (20x4 tekens en RGB-background-light) op de Arduino Uno

Arduino Uno

Pwr USB ?
 
?
aref
gnd Lcd Read/Write
? d13 Lcd Enable
ioreff d12 Lcd Register Select
reset d11 Lcd D7
+3.3v d10 Lcd D6
+5v d9 Lcd D5
Lcd Read/Write gnd d8 Lcd D4
Lcd Read/Write gnd
Vin d7
d6
a0 d5
a1 d4
a2 d3
a3 d2
a4 d1
a5 d0