Go Down

Topic: LCD code help (Read 1 time)previous topic - next topic

carstentb

Apr 15, 2012, 08:21 pm
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: [Select]
` /* "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(RS, LOW);         //Set DDRAM Address  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: [Select]
`int A[] = {5, 6, 7, 8, 9, 10, 11, 12};    //add these two arrays to all the other variables in the beginning of the sketchint 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!  XD

Marek080

#1
Apr 15, 2012, 08:50 pmLast Edit: Apr 15, 2012, 08:54 pm by Marek080 Reason: 1
Your B array has only 7 entries and not 8 but you access the 8th (B[7]) when using digitalWrite().

Code: [Select]
`for(byte nBitNo= 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, 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.

carstentb

#2
Apr 15, 2012, 09:09 pm
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?

Marek080

#3
Apr 15, 2012, 09:25 pm
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.

carstentb

#4
Apr 15, 2012, 09:44 pm
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!  XD

carstentb

#5
Apr 15, 2012, 11:35 pm
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: [Select]
`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 HomemyChar = 0x01;    for(x = 0; x < 1; x++)  digitalWrite(B[x], bitRead((byte)command, x));      delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));    delay(50);  digitalWrite(E, LOW);  delay(50);    command = 0x00;myChar = 0x3C;               //Function Set      for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }   delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));    delay(50);  digitalWrite(E, LOW);  delay(50);  command = 0x00;myChar = 0x06;                //Entry Mode      for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }   delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));    delay(50);  digitalWrite(E, LOW);  delay(50);  command = 0x00;myChar = 0x0F;           //Display Control      for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }   delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));    delay(50);  digitalWrite(E, LOW);  delay(50);  command = 0x00;myChar = 0x80;            //Set DDRAM Address      for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }   delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));    delay(50);  digitalWrite(E, LOW);  delay(50);  command = 0x01;myChar = 0x41;           //Write Capital "A"      for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }   delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, nBitNo));    delay(50);  digitalWrite(E, LOW);  delay(50);  command = 0x01;myChar = 0x42;           //Write Capital "B"      for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }   delay(50);  digitalWrite(E, HIGH);  delay(50);   for(byte nBitNo = 0; nBitNo < 8; nBitNo++)  digitalWrite(A[nBitNo], bitRead((byte)myChar, 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.

PaulS

#6
Apr 17, 2012, 12:11 pm
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: [Select]
`  for(x = 0; x < 1; x++)  digitalWrite(B[x], bitRead((byte)command, x));`
Why are you using a for loop to loop once?

Code: [Select]
`    for(x = 0; x < 1; x++){    digitalWrite(B[x], bitRead((byte)command, x));    }`
Why are you doing it more than once?