Go Down

Topic: LCD inter-character delay needed (Read 2123 times) previous topic - next topic


I was surprised to find that lcd.print("some text") gave me garbage on the screen. After some experimentation, I found that I needed to provide a delay after each character, about 40 us, like so:

#define LCD_DELAY_CHAR 40

void WriteLCDLine(int Row, char* Text)
 lcd.setCursor(0, Row);
 int i = 0;
 while (Text != 0)

I'm new to Arduino, running a DueMilaNove board with an Optrex DMC20481, which has a HD44780 controller, 4x20 screen, 4-bit mode. Arduino 0012 Alpha.

Is there a tweak to the underlying library to set delay?

How can I see what the library is actually doing?



All the source code to the libraries can be found in hardware/libraries[/LiquidCrystal] in your main Arduino installation folder.  If you want to tweak the code, just edit the .cpp and delete the LiquidCrystal.o file in that same folder.  The Arduino IDE will rebuild it automatically!



Thanks for the pointer, Mikal. I don't want to customize lib code; I just want to see what's going on. Maybe there's a bug to report.

So I looked at LiquidCrystal.h and .cpp, and find that there is no print function defined or implemented there. That is confusing, because the compiler accepts lcd.print("text"). So where is it?

Next point. LiquidCrystal::send is what does the actual port writing. It has no delays. Perhaps there should be an optional parameter to the function, or a #define, or some other option for setting a delay.

One last nit. The code has hard-coded magic numbers (2 ms) for delays executed after clearing the screen, and homing the cursor. Why those particular values? Why delays there and not elsewhere? Why hard-coded values?



My guess is that since you are trying to throw char's at it in a fast loop, the LCD firmware can't react to it quick enough. You should first look at the HD44780 spec for timing information regarding this since it's really not something the library should be dealing with. Now any multi-function writes the library might do _will_ have to deal with timing issues of the HD44780 spec and probably why you see a delay in the driver code.

Looking at the code, a better way to do this might be to add your own code to determine the string of text you want shown and then throw that string at the LCD instead of char by char.



It's been my experience that LCD displays vary in their performance.  Settings that work fine for one don't for another.  I think LiquidCrystal is the best attempt to give optimal performance on a wide variety of LCDs.

@jkh-- If you look at the declaration for class LiquidCrystal, you'll see that it inherits from class Print.  When you call lcd.print, you are actually calling Print::print, which calls LiquidCrystal::send.



Thanks again, Mikal. I hadn't noticed the inheritance.

I understand about performance variation. That's why I am surprised that the underlying lib doesn't deal with it, ie let the user tweak delay. Doing so would move the abstraction up a level, and give the target audience (not pro embedded developers) a better chance of success.



A quick search for "HD44780 update frequency" turned up an AVR header file for driving HD44780 LCDs and in it you'll see how they include the MCU clock frequency on line 47( #define XTAL 1000000 ). It's used in the c source to define a 4 cycle delay based on what the MCU clock freq is.  Just saying that it looks like others are not throwing stuff at the LCD as fast as they can.


I looked at the spec of an LCD I'm using and it too talked about timing differences between the uCPU on the LCD and the MCU driving it. After that information, I found this line which might help you if this is the normal thing to do and/or is part of the HD44780 spec:

[glow]Note: during internal operation, busy flag (DB7) is read "High".[/glow]

It looks like maybe the library could implement one of two improvements to provide better compatibility. One, have the MCU freq as part of the setup so the delays can be implemented in the library with better reliability because they are based on what the real frequency is. The second option may be to have the library wait for subsequent writes based on if DB7 is still high.


Good find. Since I'm new here, I wonder whether there is some way to get this info to the lib maintainer as a suggestion for enhancement?--Jeff


You can post here or to the developers mailing list.  

Does 40 us seem like to too much a delay to simply hardcode for all displays?  Has anyone else had problems that required a delay between characters?  It would be nice to avoid requiring an explicit delay parameter / #define.

Patching the send() function to check the busy flag would also make sense, especially since we're currently required an r/w pin.  It would be good to have another solution in case we make that pin optional (i.e. leave it tied in the write setting).  


I wouldn't simply adopt 40 us as a fixed delay. As others have suggested, I think someone should sit down and study the 44780 data sheet and determine exactly what is required.

Checking the busy flag would be good. Of course, a program could hang if something went wrong. Perhaps this should be in a timeout loop.

An option to not use the write line sounds good too.



Anyone feel like giving this a shot?


I can if nobody needs it too quickly. We're throwing a party this weekend and then have a 3D coin toss system( eCoinToss.com ) to trick out for a bowl game so it'll be after Jan 1 if the eCoinToss stuff takes too long.

It would probably be best to see if the spec has stated timing requirements first off.  When those are known, applying that to what's being done in the Arduino library should probably be the next step. All the while taking into consideration that the 4bitLCD setup uses bits DB4-DB7 and the DB7 busy-wait method might work there too.

Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131