Go Down

Topic: 16x4 LCD topic discussion (Read 3283 times) previous topic - next topic

polishdude20

So after the mod locked my topic before any progress was done I decided to post everything that I know here on this topic.

Basically I have 2 16x4 LCD' s. One of them is fine but the other does not display the hello world sketch properly (as you can see in the video). Now, both of them have the same problem which basically is that the characters populate the screen in the order of rows beginning with 1 then 3 then 2 then 4 . Normally an LCD should do 1,2,3,4. From all I know I think that is a common problem for all 16x4 LCD's not just mine.

So basically this is to Don first of all but more so for the people who also have this problem and may encounter it in the future. Hopefully my research and help can solve this problem and help the smarter ones here to fix it. So without further ado here is the video (sorry for the quality) :

http://www.youtube.com/watch?v=-GiD70cY1YU




floresta

It looks like you are vindicated.  The display that you got with the delay between characters is correct.  This means that your wiring is obviously ok.  In my opinion the display is probably out of specification.  I'm working up a more detailed answer, but I thought you would like to get this news as quickly as possible.

Meanwhile, before I spill the beans, see if you can explain just why I said that the display was correct.  You will need an ASCII chart.


Don

floresta

I think that the problem you are having here might be related to one I ran into last week on avrfreaks.  Could you please scrounge up four more wires and test your LCD in the 8-bit mode?  I don't think that pictures are necessary, just a description of what happens should be OK. 

Don


polishdude20


I think that the problem you are having here might be related to one I ran into last week on avrfreaks.  Could you please scrounge up four more wires and test your LCD in the 8-bit mode?  I don't think that pictures are necessary, just a description of what happens should be OK. 

Don




sorry but how would I connect the wires and modify the code for 8 bit?

floresta

Quote
sorry but how would I connect the wires and modify the code for 8 bit?


Old:
//LiquidCrystal lcd(RS,EN,D4,D5,D6,D7);
  LiquidCrystal lcd(7,8,9,10,11,12);


New:
//LiquidCrystal lcd(RS,EN,D0,D1,D2,D3,D4,D5,D6,D7);
  LiquidCrystal lcd(7,8,2,3,4,5,9,10,11,12);


I have arbitrarily chosen pins 2, 3, 4,and 5 for the D0, D1, D2, and D3 lines.  You can use any available pins as long as the argument (the stuff in the parentheses) of LiquidCrystal lcd matches.  Stay away from 0 and 1.

Don

floresta

For those who weren't following the original thread (http://arduino.cc/forum/index.php/topic,53893.0.html) here's what is going on.  

When polishdude20 ran the standard Hello World program he got the everchanging display shown at the beginning of his video.  Since that program sends new data to the display every second or so it makes troubleshooting the display difficult.

The following program is a good one to use when testing an LCD that displays scrambled data or displays good data in the wrong location.  It sends 80 bytes of data to the LCD controller which will put a displayable character at every location of every LCD screen from an 8x2 up through a 20x4 or 40x2.  It will work on some 16x1 displays (which are actually 8x2 internally) but you will have to change the lcd.begin argument for other 1-line displays.  By comparing what is actually displayed by this program with what should be displayed you can frequently pinpoint the problem.


Code: [Select]
#include <LiquidCrystal.h>

// Don't forget --> LCD RW pin to ground

//LiquidCrystal lcd(RS,EN,D4,D5,D6,D7);
 LiquidCrystal lcd(7,8,9,10,11,12);

void setup()
 {
 lcd.begin(16, 4);
 for (int i=33; i<113; i++)     // send 80 sequential ASCII characters to the LCD DDRAM
   {
   lcd.print(i,BYTE);           // display each character as it is stored
//    delay(100);                  // un-comment to observe addressing sequence
   }
 }

void loop()
 {  
 }



When polishdude20 initially ran this program he got this incorrect display shown at about 4:35 into the video:



When he un-commented the delay he got this correct display shown at about 5:10 into the video:




In my opinion he has an LCD controller that is operating at the edge of (or beyond) it's specifications. It seems to work OK when there is a delay between characters, but not when they are sent rapidly.

Take a look at the Execution Time column of the Instruction set (Table 6 of the Hitachi datasheet). At the top you will see that the execution time is specified for a specific LCD controller clock speed and at the bottom you will see a note that shows how the time changes at different clock speeds.

Now take a look at the AC Characteristics (page 49 on my copy of the datasheet) and you will see that the minimum allowable clock speed is less than half the speed used for the Execution Time column of the Instruction set. This means that a correctly written program, one that will work for every 'in specification' LCD module, will use much longer time delays than those in the datasheet table.

I believe that the LiquidCrystal library uses delays that are close to those specified in the Instruction set table.  This works for the vast majority of displays, but not all the time as you can see.  It won't be hard to modify the library if you are so inclined.

I may be able to add more to this when the results of the 8-bit test program are in.


Don

polishdude20

Great news guys!

I ran the LCD in 8-bit using Don's code and the pins he told me to use and it works like the other LCD. Without the delay now it runs the characters fine and it works.

Now with the hello world code I tried it and it doesnt have that character cycling error  but now all it says is "o, world!" and then counts every second on the second row properly. Heres the code.

Code: [Select]
// include the library code:
#include <LiquidCrystal.h>


  //LiquidCrystal lcd(RS,EN,D0,D1,D2,D3,D4,D5,D6,D7);
  LiquidCrystal lcd(7,8,2,3,4,5,9,10,11,12);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 4);
 
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis()/1000);
}

Nick Gammon

If I may, the datasheet I have doesn't specify a certain delay, but says this:

Quote
Busy flag indicates that KS0108B is operating or no operating. When busy flag is high, KS0108B is in internal operating. When busy flag is low, KS0108B can accept the data or instruction.


Now while they quote typical times to do stuff, you are really supposed to check the busy flag. I admit in the library I wrote, I didn't bother. If you don't check the flag, you have to build in a delay, and if you make it too low, sometimes you may get rubbish. If you make it too high, well it is slow.

The results we are getting here suggests that the library's delay is a bit on the low side for this particular display. And maybe the room temperature is an influencing factor. Switching to 8-bit mode may be masking the problem, as internally it is now taking a different path.

As for missing part of "Hello, world" that also could be an artifact of the display not being ready after reset.

When I was playing with displays, and using I2C as a communication protocol, I didn't need a delay (the protocol itself caused a delay). Switching to SPI (which is about 30 times as fast) I had to build in a delay, or just got a "dead display".
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

floresta

#8
Mar 06, 2011, 03:49 pm Last Edit: Mar 06, 2011, 03:57 pm by floresta Reason: 1
@polishdude20

Your 8-bit experience is similar to, but not exactly the same as the one at avrfreaks.  In that case, using the LiquidCrystal library the chip worked correctly with the 8-bit interface and incorrectly with the 4-bit interface.  We speculated that there was a timing (or delay) problem but this was never followed up with any testing.

In your case the program works a lot better with the 8-bit interface than the 4-bit interface but not completely correctly since the first bunch of characters are not displayed.  There may be more than one issue here but I believe that in any case the problem relates to time delays that are not long enough for your display.  We don't know if your display is within specifications or not but I do think that the present delays are not long enough to handle displays near the low end of the specified range of clock speeds.  The LiquidCrystal initialization procedure also deviates slightly from the recommended in terms of when it turns the LCD ON and this could conceivably be the problem since your error occurs immediately after that initialization procedure completes.  I couldn't convince LadyAda (the author of LiquidCrystal) to fix this when her version of the library was introduced.


Don

floresta

#9
Mar 06, 2011, 03:51 pm Last Edit: Mar 06, 2011, 04:02 pm by floresta Reason: 1
@Nick

First of all you are talking Apples and Oranges.  The KS0108B is a driver chip for a Graphical LCD not for a Character mode LCD.  A similar Hitachi chip is the HD61202U, not the HD44780 chip that we are dealing with here.  It's easy to get confused especially when one is dealing with an abbreviated data sheet.  I have not been able to find anything more than an 18 page datasheet for the Samsung chip.

The Hitachi datasheet for the HD44780U does, however, contain a statement very similar to the one that you quoted for the KS0108B:

When the busy flag is 1, the HD44780U is in the internal operation mode, and the next instruction will not
be accepted. When RS = 0 and R/ = 1 (Table 1), the busy flag is output to DB7. The next instruction
must be written after ensuring that the busy flag is 0.


There is nothing in your quote or in this one that implies that this is the way you are 'supposed' to do anything.  It just states how the busy flag relates to processor activity.

In the Hitachi datasheet, just above the Instruction set is this note:

Note:     Be sure the HD44780U is not in the busy state (BF = 0) before sending an instruction from the
         MPU to the HD44780U. If an instruction is sent without checking the busy flag, the time between
         the first instruction and next instruction will take much longer than the instruction time itself. Refer
         to Table 6 for the list of each instruction execution time.


The second sentence needs some interpretation.  I believe it says that if you don't make provisions to check the busy flag before sending an instruction then you must allow enough time for the previous instruction to complete before you send the next one.  This time (delay) must be "much longer" than the instruction execution time given in the table.

The note does not emphasize the fact that Table 6 gives typical, not worst case, execution times but notice that it does say that the delay should be "much longer" than that value.  Unfortunately the LiquidCrystal library and most other programs that I have examined do not do this.  They work the majority of the time, but then again the majority of chips probably operate close to their nominal specifications.



Quote
As for missing part of "Hello, world" that also could be an artifact of the display not being ready after reset.
This was my initial thought as well but it is not correct since the controller is obviously being initialized (mostly) correctly.

Don

Nick Gammon

Page 22 of my copy of the HD44780U manual says:

Quote
Interfacing to the MPU

The HD44780U can send data in either two 4-bit operations or one 8-bit operation, thus allowing interfacing with 4- or 8-bit MPUs.

•   For 4-bit interface data, only four bus lines (DB4 to DB7) are used for transfer. ...

The busy flag must be checked (one instruction) after the 4-bit data has been transferred twice. Two more 4-bit operations then transfer the busy flag and address counter data.


(my emphasis)

That is specific. For 4-bit mode the busy flag "must" be checked. This page is a  bit silent about 8-bit mode. But page 24 says:

Quote
Because the busy flag is set to 1 while an instruction is being executed, check it to make sure it is 0 before sending another instruction from the MPU.


Again, I didn't bother in my code and it worked once I tweaked the delays. Still there is a warning there of incorrect operation if you don't check it.

I think you are right about your interpretation of the bit about "take much longer". They are basically saying "play it safe if you don't check the busy flag ... and this may take longer than actually checking it".
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

mowcius

I suggest you use the liquidcrystal440 library - I use my 16x4 LCD in 4 bit mode with no issues using this library.

floresta

#12
Mar 07, 2011, 12:13 am Last Edit: Mar 07, 2011, 12:19 am by floresta Reason: 1
Quote
The busy flag must be checked (one instruction) after the 4-bit data has been transferred twice. Two more 4-bit operations then transfer the busy flag and address counter data.

(my emphasis)

But you emphasized the wrong part of the sentence.  The sentence does not mean that you must check the busy flag.  What it means is is that if you are using the 4-bit interface, and if you are checking the busy flag, then you must check it after downloading the entire data byte (after the 4-bit data has been transferred twice).  

Actually that isn't quite true.  You can check the busy flag after downloading the first nibble but you must download (and ignore) the next nibble before trying again.


Quote
... and this may take longer than actually checking it".
I believe that checking the busy flag will always result in faster operation.  However the extra speed is not needed in many applications and the savings of a processor pin is frequently more important.

Don

floresta

#13
Mar 07, 2011, 12:14 am Last Edit: Mar 07, 2011, 12:20 am by floresta Reason: 1
Quote
I suggest you use the liquidcrystal440 library - I use my 16x4 LCD in 4 bit mode with no issues using this library.
That's because John took the trouble to correctly interpret the datasheet while writing the library and to ask for help when he needed it.

Don

mowcius

Quote
That's because John took the trouble to correctly interpret the datasheet while writing the library and to ask for help when he needed it.

Yep - Shame some other people aren't like that :P (Not that I could do any better though)

Go Up