LCD code help

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. :stuck_out_tongue:
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:

/* "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:

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! XD

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

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.

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?

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.

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

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:

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++)
  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.

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.

  for(x = 0; x < 1; x++)
  digitalWrite(B[x], bitRead((byte)command, x));

Why are you using a for loop to loop once?

    for(x = 0; x < 1; x++){
    digitalWrite(B[x], bitRead((byte)command, x));
    }

Why are you doing it more than once?