LCD 1602A not intializing

I am using an LCD 1602A which uses the Hitachi HD44780 microcontroller. I am attempting to initialize it for 5x8 characters, 2 lines, and 4-bit mode. For some reason, only one line shows contrast. It works fine when I use the LiquidCrystal library. Here is my code:

void cmd(byte bin) {
  for (byte i = 0; i <= 3; i++) {
    digitalWrite(i + 2, bitRead(bin, i));
  }
  digitalWrite(11, 1);
  delayMicroseconds(1);
  digitalWrite(11, 0);
  delayMicroseconds(100);
}

void setup() {
  for (byte i = 2; i <=  13; i++) {
    digitalWrite(i, 0);
  }
  delay(100); // POWER UP
  // function set 1
  cmd(0b0011);
  delay(10);
  
  // function set 2
  cmd(0b0011);
  delayMicroseconds(100);
  
  // function set 3
  cmd(0b0011);
  delayMicroseconds(100);
  
  // set to 4 bit
  cmd(0b0010);
  
  // set to 4 bit, 2 lines, and 5x8 chars
  cmd(0b0011);
  cmd(0b1000);
  
  // turn off display
  cmd(0b0000);
  cmd(0b1000);
  
  // clear display
  cmd(0b0000);
  cmd(0b0001);
  delay(5);
  
  // entry mode set
  cmd(0b0000);
  cmd(0b0110);
  
  // TURN IT ALL ON
  cmd(0b0000);
  cmd(0b1111);
}

void loop() {
  
}

Note that I am not yet using the RS pin or R/W pin, so I have connected both of them to GND. Here are two pictures of my wiring:

I have been through hundreds of datasheets and I even looked at the code of the LiquidCrystal library. I think the most trusted datasheet would Sparkfun's HD44780 full datasheet (I'm pretty sure it's the official dataheet).

RohitRojo:
. . .
Note that I am not yet using the RS pin or R/W pin, so I have connected both of them to GND. Here are two pictures of my wiring:

In that case you are doomed to failure.

Have you tried doing a Google search for "LCD Programming Examples". Currently in the US the first hit points you to LCD Programming Examples which has some examples that have been working for decades.

Don

On second thought ... connecting R/W to GND is correct and you should be able to do the initialization without manipulating RS.

EDIT
Please be aware that your initial commands should be sent out using 8-bit techniques. After you issue the actual command to switch to 4-bit mode the technique changes. Therefore any initialization routine that uses the same technique throughout is incorrect.

I remember trying your technique at one point. I really don't remember why it didn't work reliably. Note that you have at least one delay that is way too short and you are missing the delay after one of the function set commands. Don't feel bad about that one, it's missing from the datasheet as well.

Scroll down to the bottom of the page I linked to above, go to the home page, and then look at the LCD Initialization section.

Don

Why don't you try setting pins as OUTPUTs? :roll_eyes:

Paul__B:
Why don't you try setting pins as OUTPUTs?

For some reason, this worked... It worked to the extent of the cursor showing, but it's still initializing one line...

floresta:
Note that you have at least one delay that is way too short and you are missing the delay after one of the function set commands.
...
Scroll down to the bottom of the page I linked to above, go to the home page, and then look at the LCD Initialization section.

Yeah, I've seen that page a thousand times, still didn't help :frowning:

Well, I fixed my problem. Turns out, the HD44780 likes to have two lines set to HIGH and 5x10 font size set to high in the final function set, even though 5x10 character font for two lines isn't supported... Anyways, thanks @Paul__B for telling me to set pins to OUTPUT, still wondering why this affected the arduino. Thanks @floresta for trying to help.
Here is my final code if anyone in the future faces my problem:

void cmd(byte bin) {
  for (byte i = 0; i <= 3; i++) {
    digitalWrite(i + 2, bitRead(bin, i));
  }
  digitalWrite(11, 1);
  delayMicroseconds(1);
  digitalWrite(11, 0);
  delayMicroseconds(100);
}

void setup() {
  for (byte i = 2; i <=  13; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, 0);
  }
  delay(100); // POWER UP
  // function set 1
  cmd(0b0011);
  delay(10);
  
  // function set 2
  cmd(0b0011);
  delayMicroseconds(100);
  
  // function set 3
  cmd(0b0011);
  delayMicroseconds(100);
  
  // set to 4 bit
  cmd(0b0010);
  delayMicroseconds(100);
  
  // set to 4 bit, 2 lines, and 5x10 chars ( for some reason, HD44780 likes 5x10 char font instead of 5x8... )
  cmd(0b0010);
  cmd(0b1100);
  delayMicroseconds(50);
  
  // turn off display
  cmd(0b0000);
  cmd(0b1000);
  delayMicroseconds(50);
  
  // clear display
  cmd(0b0000);
  cmd(0b0001);
  delay(5);
  
  // entry mode set
  cmd(0b0000);
  cmd(0b0110);
  delayMicroseconds(50);
  
  // TURN IT ALL ON
  cmd(0b0000);
  cmd(0b1111);
}

void loop() {
  
}

EDIT: In addition, my pins were reversed... I thought I had been very smart with my arrangement, but I was in fact very wrong...

RohitRojo:
. . .
Turns out, the HD44780 likes to have two lines set to HIGH and 5x10 font size set to high in the final function set, even though 5x10 character font for two lines isn't supported... Anyways, thanks @Paul__B for telling me to set pins to OUTPUT, still wondering why this affected the arduino. Thanks @floresta for trying to help.
. . .

You have to set "two lines" (DB3) high for almost every device that is commonly sold. Very few displays have a configuration that uses only one line of memory. The font size (DB2) only has an effect when using one line of memory so when DB3 is high then DB2 essentially becomes a 'don't care'.

Not setting the pins to output means that none of the commands that you thought you were sending to your device were actually being sent. The problem did not affect the Arduino, it affected your device.

Be sure to come back and let us know how you made out when you actually display a message on your device.

Don

It should be fairly obvious that unless you set pins to OUTPUT, they will not actually output data. :roll_eyes:

What you would not usually notice, is that when you use a library, it is the library code itself that methodically sets all the lines you have specified, to OUTPUT to make it work. :grinning:

That said, the chip is CMOS and failing to set pins to OUTPUT means that when you digitalWrite to them, they alternate between open circuit and the weak INPUT_PULLUP, so if you had some even weaker pull-down attached, a CMOS chip might actually respond. It is common for people to forget to set pins to OUTPUT and connect a LED to them (and ground), then complain that the LED works, but is so dim! :astonished:

Paul__B:
That said, the chip is CMOS and failing to set pins to OUTPUT means that when you digitalWrite to them, they alternate between open circuit and the weak INPUT_PULLUP, so if you had some even weaker pull-down attached, a CMOS chip might actually respond. It is common for people to forget to set pins to OUTPUT and connect a LED to them (and ground), then complain that the LED works, but is so dim!

Wow, that is honestly very useful information... Thanks!

floresta:
Be sure to come back and let us know how you made out when you actually display a message on your device.

Yup, everything is working perfectly fine, thanks!