Pages: [1]   Go Down
 Author Topic: LCD code help  (Read 356 times) 0 Members and 1 Guest are viewing this topic.
Offline
Newbie
Karma: 0
Posts: 4
 « on: April 15, 2012, 01:21:20 pm » Bigger Smaller Reset

Hello everyone, this is my first post here so I hope I'm doing things right!
I've been learning with the Arduino on and off now for a few months, but just recently started some major programming with higher functions and stuff.
I recently got a character LCD that I've connected to my board (Arduino Uno) via a parallel connection.
Being curious, I wanted to know exactly how all the pins on the LCD worked to display characters, down to the basic zero's and one's, and after a few days of research I was finally able to get it working without the LiquidCrystal library.
All that was working really well, until I decided that I wanted to try and write it in more efficient code and not take up eleven lines of code for each instruction/data i wanted to send.
What I want to be able to do is set each pin on my arduino (5-12 for Data Busses 0-7) either HIGH or LOW, depending on the status of each bit of a hexadecimal character. I hope this is making sense.
For example, if I wanted to display a capital A, which in ASCII is represented by 0x41 (Hexadecimal), I want a program that will break down that hexadecimal character into its binary equivalent (0 1 0 0 0 0 0 1), read each bit of that byte, and set the cooresponding pin HIGH or LOW.
This way I can just plug in the hexadecimal representation of what ever character I want to write instead of looking up the binary representation of that character and manually change each pins output.
Here's the original code I wrote with all the basic commands:
Code:

/* "Arduino pin, lcd pin - function"
2, pin1 - RS
3, pin2 - R/W
4, pin3 - E
5, pin4 - D0
6, pin5 - D1
7, pin6 - D2
8, pin7 - D3
9, pin8 - D4
10, pin9 - D5
11, pin10 - D6
12, pin11 - D7
*/
int lcdPins[12] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int x;
int RS = 2;
int RW = 3;
int E = 4;
int D7 = 5;
int D6 = 6;
int D5 = 7;
int D4 = 8;
int D3 = 9;
int D2 = 10;
int D1 = 11;
int D0 = 12;
int backlight = 13;

void setup()
{
for(x = 0; x < 11; x++){        //Sets each pin (2-12), which coorespond to RS, RW, E, & DB7-DB0, to outputs.
pinMode(lcdPins[x], OUTPUT);
}

pinMode(backlight, OUTPUT);      //Sets backlight as output and turns it on
digitalWrite(backlight, HIGH);
delay(50);

/*
The next groupings are just sending the LCD instructions to get ready to write characters to it
*/

digitalWrite(RS, LOW);         //Clear Home
digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);
digitalWrite(D0, LOW);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
digitalWrite(D4, LOW);
digitalWrite(D5, LOW);
digitalWrite(D6, LOW);
digitalWrite(D7, HIGH);
delay(50);
digitalWrite(E, LOW);
delay(50);

digitalWrite(RS, LOW);         //Function set
digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);
digitalWrite(D0, LOW);
digitalWrite(D1, LOW);
digitalWrite(D2, HIGH);
digitalWrite(D3, HIGH);
digitalWrite(D4, HIGH);
digitalWrite(D5, HIGH);
digitalWrite(D6, LOW);
digitalWrite(D7, LOW);
delay(50);
digitalWrite(E, LOW);
delay(50);

digitalWrite(RS, LOW);         //Entry mode
digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);
digitalWrite(D0, LOW);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
digitalWrite(D4, LOW);
digitalWrite(D5, HIGH);
digitalWrite(D6, HIGH);
digitalWrite(D7, LOW);
delay(50);
digitalWrite(E, LOW);
delay(50);

digitalWrite(RS, LOW);         //Display Control
digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);
digitalWrite(D0, LOW);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
digitalWrite(D4, HIGH);
digitalWrite(D5, HIGH);
digitalWrite(D6, HIGH);
digitalWrite(D7, HIGH);
delay(50);
digitalWrite(E, LOW);
delay(50);

digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);
digitalWrite(D0, HIGH);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
digitalWrite(D4, LOW);
digitalWrite(D5, LOW);
digitalWrite(D6, LOW);
digitalWrite(D7, LOW);
delay(50);
digitalWrite(E, LOW);
delay(50);

/*
Here I'm just sending the binary byte 0 1 0 0 0 0 0 1
to the LCD on DB0 - DB7 to tell it to write a capital A
*/

digitalWrite(RS, HIGH);         //Write capital "A"
digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);
digitalWrite(D0, LOW);          // 0
digitalWrite(D1, HIGH);         // 1
digitalWrite(D2, LOW);          // 0
digitalWrite(D3, LOW);          // 0
digitalWrite(D4, LOW);          // 0
digitalWrite(D5, LOW);          // 0
digitalWrite(D6, LOW);          // 0
digitalWrite(D7, HIGH);         // 1
delay(50);
digitalWrite(E, LOW);
delay(50);

}

void loop()
{

}

And here's where it gets funky.
I tryed to use Arrays and For Loops to perform each command in only a few lines of text.
This was the only way that seemed logical to me, but that's why I'm here, to ask you guys!
So I set up two arrays, one (A), that contained the output pins 5-12, or DB0-DB7, and the other (B), 8 elements long, where each element would be either HIGH or LOW depending on the bits of a certain byte.
So here's what I wrote:

Code:
int A[] = {5, 6, 7, 8, 9, 10, 11, 12};    //add these two arrays to all the other variables in the beginning of the sketch
int B[7];

/* Here's where all the setup commands would go, but I'm leaving them out to make it shorter.
*/

char myChar = 0x41;
int y;
for(y = 0; y < 7; y++)

{

if(bitRead(byte(myChar), y) == 1)    //by doing these functions I can change the character I want to write by only changing the hexadecimal character
{                                    //assigned to the variable myChar. The byte() function changes it to a byte, and then bitRead() reads each bit of
B[y] = HIGH;                       //that byte, and if it is equal to 1 sets the cooresponding element of array B to HIGH, if its equal to 0, that element
}                                    //of array B becomes LOW.
else
{
B[y] = LOW;
}

}

digitalWrite(RS, HIGH);
digitalWrite(RW, LOW);
delay(50);
digitalWrite(E, HIGH);
delay(50);

digitalWrite(A[0], B[0]);      //This is just saying that each pin 5-12 will be HIGH or LOW, depending on the cooresponding element of array B.
digitalWrite(A[1], B[1]);
digitalWrite(A[2], B[2]);
digitalWrite(A[3], B[3]);
digitalWrite(A[4], B[4]);
digitalWrite(A[5], B[5]);
digitalWrite(A[6], B[6]);
digitalWrite(A[7], B[7]);

delay(50);
digitalWrite(E, LOW);
delay(50);
*/

So I think something in the for loop is not working correctly. Any and all help/comments/sugestions/criticism would be appreciated!
Thank you!
 Logged

Germany
Offline
Jr. Member
Karma: 0
Posts: 91
Walking on Nails
 « Reply #1 on: April 15, 2012, 01:50:44 pm » Bigger Smaller Reset

Your B array has only 7 entries and not 8 but you access the 8th (B[7]) when using digitalWrite().

Code:
for(byte nBitNo= 0; nBitNo < 8; nBitNo++)
This does the same without the intermediate array B. HIGH is defined as 0x01 and LOW as 0x00.

Additionally I think you have to reverse array A, because in your example D0 is the most significant bit and you set it at A[0] / bitRead(..., 0) which handles the least significant bit.
 « Last Edit: April 15, 2012, 01:54:25 pm by Marek080 » Logged

loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

Offline
Newbie
Karma: 0
Posts: 4
 « Reply #2 on: April 15, 2012, 02:09:56 pm » Bigger Smaller Reset

Thank you! That worked, and it's much shorter than what I originally had.
Im still wondering why my B array did not have 8 elements, because the original for loop should have started it at zero, right? and assigned either a high or low status for elements zero through seven, which is eight elements?
 Logged

Germany
Offline
Jr. Member
Karma: 0
Posts: 91
Walking on Nails
 « Reply #3 on: April 15, 2012, 02:25:50 pm » Bigger Smaller Reset

You declared B[7] (running from 0 to 6) instead of B[8] (from 0 to 7). Then in your loop y started at 0 and counted to 6 (y < 7). So even if the loop would be corrected you still would access the 8th element of B which was not declared thus you would overwrite something else in memory with strange effects as a result. Hope that is somehow understandable - or in other words: do not access an array beyond its bounds.
 Logged

loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

Offline
Newbie
Karma: 0
Posts: 4
 « Reply #4 on: April 15, 2012, 02:44:50 pm » Bigger Smaller Reset

Yes that helps a lot. Thanks again, and I was able to declare B to have eight elements and my original code worked,
but I like yours better anyway!
 Logged

Offline
Newbie
Karma: 0
Posts: 4
 « Reply #5 on: April 15, 2012, 04:35:15 pm » Bigger Smaller Reset

I have a question about reading the busy flag from the LCD...

Is there a way to read the busy flag continuously, and when it is on pause the program, and then wait to continue until it is off?

Here is my code I have now:
Code:

int lcdPins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int A[] = {5, 6, 7, 8, 9, 10 ,11, 12};
int B[] = {2, 3, 4};
char command;
char myChar;
int x;
int backlight = 13;
int E = 4;

void setup()
{
for(x = 0; x < 11; x++){        //Sets each pin (2-12),
pinMode(lcdPins[x], OUTPUT);    //which coorespond to
}                               //RS, RW, E, & DB7-DB0,
//to outputs.

pinMode(backlight, OUTPUT);      //Sets backlight as output
digitalWrite(backlight, HIGH);   //and turns it on
delay(50);

command = 0x00;            //Clear Home
myChar = 0x01;

for(x = 0; x < 1; x++)

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

command = 0x00;
myChar = 0x3C;               //Function Set

for(x = 0; x < 1; x++){
}

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

command = 0x00;
myChar = 0x06;                //Entry Mode

for(x = 0; x < 1; x++){
}

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

command = 0x00;
myChar = 0x0F;           //Display Control

for(x = 0; x < 1; x++){
}

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

command = 0x00;
myChar = 0x80;            //Set DDRAM Address

for(x = 0; x < 1; x++){
}

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

command = 0x01;
myChar = 0x41;           //Write Capital "A"

for(x = 0; x < 1; x++){
}

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

command = 0x01;
myChar = 0x42;           //Write Capital "B"

for(x = 0; x < 1; x++){
}

delay(50);
digitalWrite(E, HIGH);
delay(50);

for(byte nBitNo = 0; nBitNo < 8; nBitNo++)

delay(50);
digitalWrite(E, LOW);
delay(50);

}

void loop()
{}

So essentially I could have the one function that reads the BF and get rid of all the delay(50) commands.
 Logged

Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
 « Reply #6 on: April 17, 2012, 05:11:09 am » Bigger Smaller Reset

Quote
Is there a way to read the busy flag continuously, and when it is on pause the program, and then wait to continue until it is off?
Yes. Use a while loop(). Won't be any faster.

Code:
for(x = 0; x < 1; x++)
Why are you using a for loop to loop once?

Code:
for(x = 0; x < 1; x++){