Go Down

Topic: How to read HD44780 LCD programmatically (Read 4530 times) previous topic - next topic

pdorcas

How can I read the LCD?  It is a common HD44780 compatible LCD, connected in parallel 4-bit mode.
Arduino Mega 2560 Rev 3.

#include <LiquidCrystal.h>
. . .
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

There are lots of methods now for lcd, but they have to with writing to the display.
Are there other methods for the HD44780 in LiquidCrystal.h that are not exposed in the header that I can use for reading the display?
Is there another library with some methods for reading?


pdorcas

How can I read the LCD?  It is a common HD44780 compatible LCD, connected in parallel 4-bit mode.
Arduino Mega 2560 Rev 3.

#include <LiquidCrystal.h>
. . .
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

There are lots of methods now for lcd, but they have to with writing to the display.
Are there other methods for the HD44780 in LiquidCrystal.h that are not exposed in the header that I can use for reading the display?
Is there another library with some methods for reading?

robtillaart

There is no reading back as far as I know in any library.
The only way to do this correctly is to make a "shadow" screen which buffers the content send to the screen.

This will effectively result in a HD44780 simulator, not trivial but doable - definitely a project in itself.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

2nd thought,

Better is to use a model view design pattern.
That means that you make a model (set of vars) you want to be displayed. This model will be displayed on the LCD in a separate function. for that it reads the model too.

pseudo code
Code: [Select]

struct model
{
int voltage;
float temperature;
}

void loop()
{
  model.voltage = analogRead() * 5.0/1023;
  model.temperature = getTemperature();

  if (millis() - lastDisplay >= refreshTimeout)
  {
     lastDisplay += refreshTimeout;
     // display values from model here
  }
 
  // read back model
  x = model.temperature;
  y = model.voltage;
}


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

floresta

It is not possible to read from the LCD using the current LiquidCrystal library as there are no provisions to use the R/W signal on pin 5 even if you do choose to connect it. 

The LiquidCrystal440 library and its updated successor does have provisions for checking the busy flag (which involves reading from the LCD) so you could take a look at that library for some ideas. 

To get a copy start here:--> http://code.google.com/p/liquidcrystal440/ and follow the Downloads link to get to the latest version.


Don

Nick Gammon

Please do not cross-post. This wastes time and resources as people attempt to answer your question on multiple threads.

Threads merged.

- Moderator
Please post technical questions on the forum, not by personal message. Thanks!

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

floresta

#6
Feb 22, 2013, 10:03 pm Last Edit: Feb 22, 2013, 10:06 pm by floresta Reason: 1
Quote
The only way to do this correctly is to make a "shadow" screen which buffers the content send to the screen.

You are answering this from a more modern perspective than might have originally been intended when the LCD controller was designed.  I mean that it looks like you are assuming that he wants to read back information that corresponds to that displayed on the screen.

If you are using a display with less than 80 characters then there is some unused RAM in the LCD controller.  In ancient times when RAM was scarce this RAM was a valuable resource and could be (and was) used for general purpose storage.  Perhaps the OP has an application such as this in mind.

Here is what the HD44780U data sheet has to say (just before Figure 1).

Display Data RAM (DDRAM)

Display   data   RAM   (DDRAM)   stores   display   data   represented   in   8-bit   character   codes.   Its   extended
capacity is 80 × 8 bits, or 80 characters. The area in display data RAM (DDRAM) that is not used for
display can be used as general data RAM.
See Figure 1 for the relationships between DDRAM addresses
and positions on the liquid crystal display.


Don

pdorcas

The HD44780 LCD  has functions to read the display in libraries for other microcontrollers (PicBasic, for example).   So I was just searching for the same functions for the Arduino.  I really, really like the Arduino, and don't like it when there is support for other microcontrollers which is lacking for the Arduino.

For the immediate need, I will create an in-memory ("shadow") view of the LCD, send that view to the LCD, and also then be able to read fro that view.  It will be a simple 2x16 array of char.  Fortunately there is a lot of extra programming space in the Mega 2560.  Having this view in RAM serves the capability of cloning the LCD display to the PC, but doesn't help any in auto-testing the LCD, hence the need to read the LCD.

In the future I will work on providing an update to the Arduino library to make it more complete. 

Thank you for all the comments and suggestions!  I consider the question to be answered.
Phil Dorcas

robtillaart

Do you have access to library code of one of those other platforms?
Can you post a link?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

pdorcas

In PicBasic, the support for the LCD is built into the language, and I don't have access to it's source code.
The methods to read has two parameters, the first is the address to read from the LCD, usually $80 or $C0 for the first and second lines respectively.  The second parameter is an array of characters, where the LCD characters were placed. 

Examples for reading from the LCD:
  LCDIN $80, [ InArray[20], InArray[21], InArray[22], InArray[23],_
               InArray[24], InArray[25], InArray[26], InArray[27],_
               InArray[28], InArray[29], InArray[30], InArray[31],_
               InArray[32], InArray[33], InArray[34], InArray[35] ]
             
  LCDIN $c0, [InArray[36], InArray[37], InArray[38], InArray[39],_
              InArray[40], InArray[41], InArray[42], InArray[43],_
              InArray[44], InArray[45], InArray[46], InArray[47],_
              InArray[48], InArray[49], InArray[50], InArray[51] ]

I'll read the Fujitsu documentation and figure it out for the Arduino.  Wish I had other source code to access as a guide.  Maybe from the mfg.  Thank you.

Retroplayer

Reading from the LCD is pretty much the same as writing to it. When you write to it, you are simply putting a byte into the DDRAM. So, you just read it instead... You do need control of the R/W line, though.

So you set the RS pin high, the R/W line high, then toggle the E line. Each time you toggle the E line, it will increment (or decrement depending on how you set it up) and give you the byte in the next address.

So the only difference is that you are setting the read/write line high instead of low and listening on the data lines instead of writing something to it. Modifying a library wouldn't be much more than copying the functions and changing them to set the read write line and return a byte ( or array of bytes) instead of sending one.

pdorcas

That sounds easy enough.  Thank you!  I'll look at the LiquidCrystal library, and make the recommended changes.  Thank you very much for your help!

Retroplayer

You got me looking at it, actually. There actually already is support for a RW pin if you define one. I've made several little changes already to support reading. If I were to modify the library, what functions would be useful? I would think a read function where you give it an address and length would be useful. What else?

floresta

#13
Mar 07, 2013, 10:08 pm Last Edit: Mar 07, 2013, 10:10 pm by floresta Reason: 1
Quote
So you set the RS pin high, the R/W line high, then toggle the E line. Each time you toggle the E line, it will increment (or decrement depending on how you set it up) and give you the byte in the next address.

It's not quite that simple in the 4-bit mode since you have to read twice for each byte and reassemble the nibbles.  Also, don't forget that you do the actual reading while E is high, not after it goes low.

Quote
You got me looking at it, actually. There actually already is support for a RW pin if you define one.

Look again.  If you define the pin then all they do is drive it low...PERIOD.

I am not trying to discourage you, I am just pointing out some of the problems.  John went through all of this when he was writing the LiquidCrystal440 library a few years ago and I provided him with some code for starters.  All he was doing is reading the busy flag, but the added work to get the other seven bits should be trivial*.  Why don't you see if you can find anything here --> http://code.google.com/p/liquidcrystal440/ (follow the Downloads link to get to the latest version) before you try to reinvent the wheel.

Don

Edit: * Famous last words....

robtillaart

Quote
I would think a read function where you give it an address and length would be useful. What else?


primary functions would be

char lcd.readChar(row, col)        // reads 1 char
char * lcd.readStr(row, col, len)   // reads len chars - should it wrap around end of line?

some ideas:

char lcd.readChar(); // reads form last known (internal) row/col  e.g. gotoxy(r,c); x = lcd.readchar()

char lcd.readNext(); // reads a char and moves to next position?

maybe some function to read self made chars / font back into an array?

readback backlight status?
bool lcd.getBackLight()
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up