LCD Display working in 8-bit mode but not in 4-bit mode

Hi, I need some help figuring out why my LCD display is working fine in 8-bit mode, but in 4-bit mode, some of the characters I want to display get mapped to different Japanese characters.

I am using a 16x2 QAPASS 1602A LCD screen and an Arduino MEGA 2560.

The issue is with the characters highlighted in this table from the datasheet:

For example, the characters 'fghijklmnopq7891' are shown accurately in 8-bit mode. However, in 4-bit mode, they show up as follows:

I don't think it is a hardware or soldering issue since it is working fine in one mode, but not in the other.

P.S. - In the schematics below an Arduino UNO is shown but the connections I have made with my Arduino MEGA are exactly the same.

This is my circuit in 8-bit mode and the code below:
I will post the schematic for 8-bit mode in a reply below since new users are only allowed 3 embedded media posts.

#include <LiquidCrystal.h>

const int rs=2, en=3, d0=4, d1=5, d2=6, d3=7, d4=8, d5=9, d6=10, d7=11;
LiquidCrystal lcd(rs,en,d0,d1,d2,d3,d4,d5,d6,d7);

void setup() {
  lcd.begin(16,2);
  lcd.print("fghijklmnopq7891");
}

void loop() {
}

This is my circuit in 4-bit mode and the code below:

#include <LiquidCrystal.h>

const int rs=2, en=3, d4=8, d5=9, d6=10, d7=11;
LiquidCrystal lcd(rs,en,d4,d5,d6,d7);

void setup() {
  lcd.begin(16,2);
  lcd.print("fghijklmnopq7891");
}

void loop() {
}

Thanks in advance!

8-bit schematic:

Soldering of header pins to LCD:

I suggest you to test the circuit with the default 'hello world' example given in the Arduino IDE. That's the easiest way to check.

This is what I get for 'hello world.'

Which is the same issue as described in the original post.

You have shown drawings of how your circuits should be connected.

We need photos of how your circuits are actually connected. There's obviously a
problem with one or more of the data lines.

If the photo shows that the connections are correct then one or more of the wires is defective.

Don

1 Like

Look at the bit patterns for the failing characters. Bits 3 and 7 appear shorted together in 4 bit mode.

1 Like

If 3 and 7 are shorted together, then I should get different outputs (both incorrect) in 8-bit mode as well as 4-bit mode, correct?
Because all I'm doing is disconnecting d0-d3 and changing the code when I change over from 8-bit to 4-bit.
However, all my 8-bit mode outputs are accurate.

4-bit mode:

8-bit mode:

Is it possible for the wires to be defective if all I have done when switching from 4-bit to 8-bit is add the connections for d0-d3, and changed the code?

I have also switched around all the wires, but I still run into the same issue.

Do the specs tell anything about the state the other 4 pins should have in 4bit mode? E.g. tied to GND?

1 Like

I have not seen any literature or tutorials that call for that. I tried it now and it did not fix the problem.

That is why I said appear - in 4 bit mode it is the same wire. It would be a strange hardware problem to cause that. It would then seem that the software is setting the high bit wrong - but I would have thought there would have been a test of 4 bit mode.

There are a lot of libraries with LiquidCrystal.h of various quality. I would try the hd44780 library by Bill Perry in pin I/O mode (hd44780ioClass/hd44780_pinIO.h) and see if you still have the problem.

I tried the library you suggested, as well as a few others to test them out, but the same issue persists. :frowning:

Maybe something on the Arduino board. Try moving to Arduino pins 4-7 instead of 8-11 for 4 bit mode.

To me it looks like it could be a timing problem with this specific display. In 4 bit mode the library sends first the 4 high order bits then the 4 low order bits. It looks as if before all the high order bits have been read by the display, the low order bits crash in.
For example 'h' . First nibble 0110 is sent then nibble 1000 is sent. It appears that the first bit of the second nibble , that is the 1, is overwriting the first bit of the first nibble , that is a 0. Hence, instead of the 'h' being seen as 01101000 it is seen as 11101000 which is the square root symbol.
It would be interesting to see if the same thing happens with explicitly setting the blinking cursor to various positions on the display to see if some positions are unreachable.

My guess is on a wiring issue.
Perhaps an issue with the wire connected to LCD D7.

Also, from what I see, the code matches fritzing diagrams, but it doesn't match the wiring the photos.
i.e. the Arduino pins in the constructor in the code doesn't match the wiring in the photos.
If I look at the LCD constructors in 4 bit or 8 bit mode sketches,
they are using Arduino pins 8,9,10, 11 for LCD d4-d7
But both photos appear to show LCD d4,d5,d6,d7 pins connect to Arduino pins 2,3,4,5

If that were the case, then neither 4 bit or 8 bit mode would work.
But yet there is photo of 8 bit mode supposedly working.

So something is not as it appears.

--- bill

Yes, my apologies. The code I posted in the original code is not the code I'm using in reality, but only in terms of pin assignment. I had posted that code as it applies to the schematic. Here is the code I've been actually using, which is accurate and works in 8-bit mode but not in 4-bit mode.

8-bit:

#include <LiquidCrystal.h>
const int rs=12, en=10, d0=9, d1=8, d2=7, d3=6, d4=5, d5=4, d6=3, d7=2;
LiquidCrystal lcd(rs,en,d0,d1,d2,d3,d4,d5,d6,d7);

void setup() {
  lcd.begin(16,2);
  lcd.print("hello world");
}

void loop() {
}

4-bit:

#include <LiquidCrystal.h>
const int rs=12, en=10, d4=5, d5=4, d6=3, d7=2;
LiquidCrystal lcd(rs,en,d4,d5,d6,d7);

void setup() {
  lcd.begin(16,2);
  lcd.print("hello world");
}

void loop() {
}

Moving the pins around did not work.

The blinking cursor appears to be working just fine in 4-bit mode at all positions. Here is the code I used to test it.

#include <LiquidCrystal.h>
int i, j;
const int rs=12, en=10, d4=5, d5=4, d6=3, d7=2;
LiquidCrystal lcd(rs,en,d4,d5,d6,d7);

void setup() {
  lcd.begin(16,2);
  lcd.cursor();
  lcd.blink();
}

void loop() {
  for(i=0;i<2;i++){
    for(j=0;j<16;j++){
      lcd.setCursor(j,i);
      delay(3000);
      lcd.print("h");
    }
  }
}

Here the cursor moves to a position in the display, blinks for 3 seconds, prints a square root symbol, and then moves to the next position. After one complete loop, my display is filled with square root symbols. If I print 'a' instead of 'h', it prints all a's as expected.

So it seems to have handled the high order bit OK in that sequence.

This is fascinating. I can't imagine how, even if anyone wanted, how they could set up the wiring to the display in such a way as to duplicate the symptoms you have reported. Maybe a small capacitor between the E pin and ground could start messing things up or a floating RW pin?
A connection problem in one of the two on board chips (black blobs) seems a plausible explanation .
Anyway, can you post a picture of the back of the display ?

If you are using the LiquidCrystal library then you can start playing with the timings in LiquidCrystal.cpp here which shape the pulse at the end of the Library write operation signalling that the data is ready:

void LiquidCrystal::pulseEnable(void) {
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(1);    
  digitalWrite(_enable_pin, HIGH);
  delayMicroseconds(1);    // enable pulse must be >450ns
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(100);   // commands need > 37us to settle
}

However, such a display is a low value item and replacing it would be an option to consider. However, it is an interesting puzzle to solve.

Here is a picture of the back of the display.

I will play around with the timings to see if that changes anything. Thanks for the code!

I will buy a new display, but I'm also curious to know what's going on here.