Enhanced LiquidCrystal

http://healthriskappraisal.org/LiquidCrystal440.zip seems to work, as does the main site.

Ok, it seems to be a problem with the firewall you are using port 8000. Will have to try it from a different pc.

[edit]it was the firewall[/edit]


I was curious as to how you checked for the busy flag and looked at your code. It seems to me you have a bus issue that may damage the LCD and/or the Arduino when checking the busy flag.

The way I read the HD44780 datasheet is that the full bus (8 datalines) will be reversed when you pulse EN and RW is low. In your code however you only reverse the Arduino busy bit (B7) to input. The other bits (B0 to B3 for 4-bit and B0-B6 for 8-bit) will then be low impedance output as will the Arduino pins. If the LCD/Arduino outputs are at opposing logic levels you will have a dangerous short.

Did I miss something or are you reading the datasheet differently?


... seems to work, as does the main site.

I'm having trouble getting past the second page on my Health Risk Appraisal. After I click on "Ask me the questions..." I get an almost blank screen with the message "no age,sex cookie found. Quest1: {}" This happens with Firefox 3.5.7 and IE 7.0.x on Windows XP. Maybe it has a premonition that my appraisal will be too bleak.

Back to the real topic...

It seems to me you have a bus issue ...

It seems to me that Ben is correct. I think I reversed all of the bits on the code I sent you. I may even have reassembled the byte. You can never tell when you might want to use the address information that is provided on those bits.


Yikes. I was reluctant to set all the pins to input because I thought it would take a long time. I have not seen a problem here after running quite a lot of data through the interface but if Ben and Don think there's an electrical issue, they are probably right. I will work on this; in the meantime stick with the options that don't pass RW since those don't test the busy flag, leave RW low and data in one direction.

We'll see how timing comes out if I switch all of those pins' mode.

quickly ballparking performance -- I'd added a couple of things since the previous benchmark to make println work properly so this isn't quite the same as what was benchmarked before: 8 data pins +RW 619 8 data pins - RW 650 4 data pins +RW 678 4 data pins -RW 734

So I'm thinking that pulling out all of the busy flag testing stuff makes a lot of sense; there are several hundred bytes of code and the performance advantage is less than 10% if I switch all the data pins to INPUT during the busy flag test and then back to OUTPUT when that is done.

It will probably be the end of the weekend before I do all of that and test it thoroughly; it'll be shorter than what I have now, slightly faster than the non-busy flag test above, still work with 40x4, fix linewrap, fix println, fix scroll preceding setCursor, fix the 16x4 thing.

I really have run an awful lot of characters through this thing without seeing an electrical problem but I certainly have to defer to the engineering guys; the logic diagram describing the arduino digital pins, pullup resistors etc is considerably beyond me.

I did get the code modified and reposted tonight. http://HealthRiskAppraisal.org/LiquidCrystal440.zip

Modifications to LiquidCrystal for the Arduino

I made several modifications to the LiquidCrystal library module from Arduino17:

40x4 LCDs I added support for an LCD of 4 LInes and 40 characters. I think that if 24x4, 32x4 LCDs exist, they would also work with the software as I have modified it although I have not had the opportunity to test that. The 40x4 LCD (and any HD44780 based LCD with between 81 and 160 characters) will have 2 enable lines. To use an LCD with 4 lines and 40 columns you would declare your LiquidCrystal object as: LiquidCrystal lcd(RS,RW,Enable1,Enable2, data3,data2,data1,data0); at this time I don't support 8 data lines. (You can pass 255 as the RW item, ground RW and save an Arduino pin.) Then in the setup function you would call: lcd.begin(40,4);

Linewrap When you declare the dimensions of the LCD in your begin call, the LiquidCrystal library remembers how long the lines are. Now when it reaches the end of line 1, text wraps onto line 2 (not line 3 as previously).

println Although print has worked properly in the past, println has not. Now the '\r' and '\n' characters are not sent to the screen as though they were visible characters and the '\r' resets the character position to the top of the next line.

16x4 LCDs The begin statement also correctly positions text at the beginning of the line on 16x4 (and 40x4) LCDs, which were not correctly handled before.

setCursor In the past setCursor selected a location in the HD44780's RAM not actually a screen location. If you use any of the commands that shift the display left or right with the previous routines, then setCursor and print, text appears in an unexpected location on the screen. With the new software, if you call either scrollDisplayLeft() or scrollDisplayRight(), the LiquidCrystal package keeps track of the relationship between RAM and the LCD so that setCursor coordinates are pegged to a specific spot on the screen, rather than a spot in RAM. The sotware does not handle autoScroll, however. Call home() after autoScroll to restore the expected relationship between setCursor and the LCD screen.

Speed testing All of the interface modes go faster than the eye can follow. I compared the speeds of the different interfaces--writing 80 characters to the screen then 80 blanks and looping through that 20 times. The results are: 4 data pins 727 milliseconds 8 data pins 644 milliseconds The 4 data pin option is significantly faster than the previous LIquidCrystal which takes 1076 milliseconds because of an unnecessary delay between sending the high and low data nibbles.

Crazy 8 Addressing 16x1 LCDs often have an unusual address layout; these modules often have two 8 character halves and work best with this software if you declare them as lcd.begin(8,2); if you do that, then you can print(“abcdefghilklmno”); and have all the characters appear as you would like across the screen. If you use any of the scrolling commands, the bizarre addressing of these modules will manifest itself. For details follow the LCD Addressing link at web.alfredstate.edu/weimandn

Disadvantages The two real disadvantages I can see to the changes I have made are:

The code is a little longer than before.

  1. The possibility that someone with a little 16x2 LCD is using the scrollDisplayLeft() or scrollDisplayRight() instructions to move data across the screen, but wants to write the data 40 characters at a time with a print statement. This version really does not let the user write data to the HD44780 DDRAM which is not visible. To accomplish a scrolling display with 40 characters per line, you would now need to write 16 characters, scroll the display, write a little more and so on.

There are going to be some incompatibilities between code that assumed that line 1 wrapped onto line 3, etc.

Directions for the future I see little purpose to retaining the 8 pin interface or RW pin options. Even in the slowest situation output to the LCD goes faster than the eye can follow. The slowest situation would be using the 40x4 LCD, doing a scrollDisplayLeft() or scrollDisplayRight() and then printing 160 characters. When the display has been scrolled, the software actually calls setCursor internally with every character sent to the LCD, so you would be communicating 480 items to the LCD in that instance. As I have tested the various interfaces with the various shapes of LCDs, I have reflected many times on the likelihood that no one else has tried the 8 bit interfaces for some time. Don Weiman argues that inclusion of both 4 and 8 bit interfaces makes the code harder to read. I am more motivated by the idea that the 8 bit interface takes up Arduino RAM and pins but contributes little additional function.

Bug The one bug I am aware of is that autoscroll() on a 40x4 LCD only scrolls 2 lines despite my best efforts.

Thanks Certainly my efforts would not have been possible without the help and prior efforts of David Mellis, Limor Friede, and Donald Weimann. Don was particularly patient in guiding me through the idiosyncracies of the HD44780 based LCDs.

The one bug I am aware of is that autoscroll() on a 40x4 LCD only scrolls 2 lines despite my best efforts.

Yeah... :( I don't need that for anything though. Thanks for the updated code.


I've spent several hours trying to fix it and have absolutely no use for autoscroll myself. Interestingly I can get it to be either group of 2 lines depending on where on the screen I was writing last. the LCDtest suite (included in the download) demos this. It of course doesn't affect smaller LCDs with only one HD44780. As far as I can tell it doesn't affect the other commands that need to go to both HD44780 chips on the 40x4--clear, home, righttoleft text mode, scrolling under program control, display on/off etc. >:(

one more clue, perhaps, is that the while which 2 lines autoscroll seems to depend on where I wrote last (the 2 lines I didn't write last are the ones that scroll), the autoscroll commands are always sent first to the upper 2 lines then to the lower 2 lines.

I think I am finished with the project at this point, unless some smart person can figure out that last bug. I've done a lot more than I set out to do at the beginning, which was just to get it working with the 40x4 display. I've learned a lot and had a lot of fun doing it.

I've learned a lot and had a lot of fun doing it.

... and provided a very useful contribution to the community on your first try. [smiley=dankk2.gif]

... and provided a very useful contribution to the community on your first try.

Agreed [smiley=thumbsup.gif]


Hey is the server down again. I have downloaded your new code but appear to have lost it and I don't seem to be able to download it again...


Thanks to Ben and Don for all their help. I think the server is OK now.

It did download again, eventually (took like 5 minutes) but thanks again for the code.


I've known about the bug with 40x4 displays and autoscroll now for 3 weeks and it finally occurs to me that there is surely an UGLY rather stupid work around for it. I haven't tested it actually but I'm sure it would work. it would involve calling autoscroll twice in succession. I suppose it might be necessary to reposition the cursor between the 2 calls. Even if for some reason the hd44780 controlling the 2 lines that scrolled after the first command received the second one, it would just keep scrolling. It could even be built into the library as a special case only with 40x4 displays and I could pretend I'd fixed the bug. But it would be ugly and stupid. :-/

Well ugly and stupid would be better than not working...


I posted the idea so people could use the work around. And perhaps to inspire someone with a different perspective to see a real fix.

Scrolling gets blown out of proportion when I work on the library, because its the complicated bunch of things the display can do and so is involved in many of the tests in my test program (which is included with the download). In real code, I have no use for it. I knew about the bug for at least 2 weeks before I posted anything about it; I was pretty sure no one would find it in a short period of time; I wouldn't have found it except that I started putting together a thorough test procedure when I started working on the library, adding tests as I added features and found problems to demonstrate. Then before I post code I run 4 interfaces on 4 different shapes of LCDs, 2 interfaces on the 40x4. That takes almost an hour but it leaves me pretty confident I've found everything I ever knew could be a problem.

Great work.

I've been wondering about the RW pin.

I have a project in development that needs a very fast bar graph. I was going to use the programmable characters to make the last segment variable length to get a one dot wide bar resolution.

There are two, possibly academic questions: - Is "faster than the eye can see" really true for something like a bar graph?

  • Is there any way to, and do you get any advantage out of, trying to sync the value update (which is related to analog sampling in my case) to the refresh cycling of the LCD?

I was thinking of an experiment that involves getting the bar graph working, and then using something like an adjustable sine wave synthed signal to drive it. Walk the frequency up until you can't really get the bar graph to follow the signal. Try that with and without the RW.

I'm in the middle of building a shield for this project and can't try this experiment right now, but I'm planning to. Do you have an old version of the code around I could try?

Well I would like to do a bar graph on my 40x4 but it seems very slow at refreshing. When I write one character over another it is visibly taking a long time. Any ways of speeding it up?

I did see something on fast refresh on LCDs some time ago but I can't for the life of me find it. Anyone else know where it is? [edit]I can't have been looking very hard before, here it is: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264215873/0[/edit]