Reading from LCD 16x2

Hello there!
Since, this is the only post that was showing up at the top, when I was searching for a way to read from the LCD, before finding a solution, I would like share the way that I've found to make it actually work.
The first question many people often get is why do we even have to read from the LCD, when we're the one who are writing to it. But that's not always the case. Sometimes we won't be the one writing to the LCD. The main reason why people want to read from an LCD is, to interface the Arduino to an LCD in the electronics we see in our day-to-day lives and read the data it's displaying and do something with this data (which was the project I've been working on lately).

Apparently, the official LiquidCrystal library doesn't contain any function to read from the LCD. So, I've dug deeper into this forum, and found a solution here.

The hd44780 Library contains a function to read the data from the LCD and a demonstration that implements it. Download this Library and add it as .ZIP library in your IDE. Go to Examples > ioClass > hd44780_pinIO and open the ReadWrite sketch. This sketch prints the time elapsed since the Arduino has begun, on the first line of the LCD and then reads this data from the LCD and prints it on the second line. Additionally, this example requires us to connect the RW pin of the LCD to the A0 pin of the Arduino.

Hope you find this helpful.

— Raj

For those that stumble across this, Do not install the hd44780 library this way.

Unless using an IDE version prior to 1.6.2, (which is very old)
please do not attempt to install the hd44780 library this way.
The hd44780 library is available in the IDE library manager and should be installed using the IDE network install. You simply enter the library name in the search box, and the IDE will find it and you can click on it to install it.
Not only is easier but it will ensure the library is installed properly.
Installing the library using download zip file from github will not install the library correctly if you use the IDE zip installation due to the name and directlry format used in the github zip files. Installing this way can create problems in the future when updating the library since you can end up with multiple versions of the library installed in different directories.

This is true for any library that is supported by the IDE library manager not just the hd44780 library.

There are detailed instructions in the Installation section on the hd4480 github page for how to install the library and it highly discourages adding the library to the IDE from a zip file, given the installation issues and future library upgrade issues when installing that way.

--- bill

You really need to explain that because quite frankly, it makes no sense! :astonished:

Thanks a lot for clarifying Bill. I thought there's no difference between installing libraries using the IDE library manager and the zip installation. For this, I've installed it as .zip library. And yeah, I'm using an old version of the IDE. But now I get that it's a bad practice. Point noted. :raised_hands:

— Raj

Sure! Btw, I've explained it in the very next sentence, where I said:

But I'll clarify it further. Let's take home electricity meter as an example. Say, we want to extract the data being displayed on the meter to keep track of our consumption. If it uses same/similar LCD as/to hd44780, we can interface the Arduino with this LCD and we can possibly use the RW pin to get the data from the LCD directly, without having to figure out how to interface the Arduino with the IC on the meter, that controls everything. In this case it's the IC on the meter that writes to the LCD, not us. This is what I mean by that.

Scenarios like this are the only ones I can think of, where we want to read the data from the LCD. Also I haven't attempted it. So this process of reading data from such LCDs might not be possible. I'm not well versed in electronics. So, I could be wrong. I'm open for any knowledge you want to share about this case! :innocent:

— Raj

While a scenario of reading an LCD that was written by another host at first sounds possible and potentially simple, in practice, it is not really possible.
The issue is that the hd44780 physical interface (the pins) was not designed to be controlled by multiple hosts.

There are many issues that will arise with attempting to do this.
The first big issues is how to control the E signal.
How to arbitrate this control when there are multiple hosts attempting to control it.
There is also control of the r/w signal. The original circuit may ground this pin if only doing writes.
Also, one host may want 4 bit mode and the other 8 bit mode.
Then there is control of the data bus pins. The original host may set them to output mode and leave them which means that they are driven all the time, including when the host is not actively performing a write operation.
If this is the case, then when the 2nd host (the one trying to read the LCD) comes along and tries to read from the LCD, (assuming it could control the E and r/w signals) the LCD and the original host would have a bus collision creating shorts on the data pins since the LCD and the original host would both be driving the data pins.

And even if you added additional circuitry to isolate the E, r/w and data pins between the hosts, and ensured that both were using the same 4 vs 8 bit mode, (
like say using an i2c backpack which can allow multiple masters on a single i2c bus), there is the possibility of usage collisions.
I.e. the original host is attempting to write to the LCD as the 2nd host is attempting to read from the LCD or in the middle of reading the LCD.
There is no mechanism that can be used to tell a host to "wait a second" before controlling any of the signals.
Assuming that could be resolved - which is unlikely, there is the issue of timing between usage to account for instruction timing.
The reading host can't just immediately access the LCD after the first host finished sending something to it. This is because the LCD needs time to finish processing that instruction before it can be sent another instruction. In some cases it can be quite a bit of time.
For example, suppose the first host sent a clear or home instruction, those instructions can take several milliseconds to complete. If a host sends another instruction while this instruction is being processed it can create issues, including causing the LCD and host to lose nibble sync when using 4 bit mode.
The reading host would have to know what the last instruction sent was and when it was sent to account for the amount of time, but if the reading host is only reading DDRAM, (the contents of the display), it has no way of knowing what instructions are being sent or even when they were sent.

It is theoretically possible to snoop all the hd44780 signals E, R/W DB0 to DB7 and then internally emulating the hd44780 to determine what is on the display.
This would not interfere with the host that is controlling the LCD.
However, depending on the implementation of the host that is controlling that LCD, this can be difficult to impossible due to the minimum timing that is allowed.
For example, tcycE is only 500ns which means that the host can do a transfer to the LCD every 500 ns. That can be difficult to keep up another processor is polling the lines.
Even if using an ISR to trigger on E falling to monitor LCD writes, rather than polling,
the data hold time tH which is the amount of time the data (the data pis) are guaranteed to be valid for after E drops. tH is only 10ns
There is no way to respond to an ISR much less read the data pins in only 10ns.

That is the theoretically minimum timing/ maximum speed.
In practice it is not that fast on real-world implementations.
So in some cases it becomes possible to determine what is on the LCD by snooping all the signals, but it isn't a given that it is possible.
End even if it is possible, it requires fully emulating the entire hd44780 instruction set to be able to create virtual LCD screen to be able to see what is on actual LCD.
In the Arduino forum, I have seen several projects attempt this over the years, but the authors have abandoned them as it ends up being more complicated or more work than they anticipated.

Here are a few realistic real-world scenarios as to why you may want to read the LCD display.
None of these involved more than a single host.

Suppose you want to test the LCD memory.
In order to test the memory, you need to be able to write and read from it.
The I2CexpDiag sketch included in the hd44780 library uses this capability to test DDRAM.

Suppose you want to scroll each line of a display up to make room on the bottom line.
You could this by reading each line and writing on the line above.
This would not require any additional RAM - which can be precious on some processors and the scroll function would not have to know what was written to the LCD. It simply moves each line up by reading each line and re-writing it.
Note: scrolling can also be done using the LCD display shift capabilities.
The shift capabilities are more efficient since it does not involve any reading or re-writing of any data to the display.
It does require some tricky logic in the library to keep track of the shift offsets to re-map cursor positions but it can be managed.

In another scenario, the sketch really does not know what got written to the LCD but wants to get access to the characters.
Consider if the sketch used something that formats the output like the Print class to output a number to the display.
Something like lcd.print(var)
While the sketch can know the value of that number in the variable since it can look at the variable, it won't actually know what characters were written to the display since the Print class is formatting it. This can particularly be true when using floating point or non based 10 radix output.
This can be more complex than a simple variable particularly if using 3rd party Arduino cores and the printf method. i.e. you can do something like:
lcd.printf("sensor1: %d, sensor 2: %d", s1, s2)
In that case, the sketch does not know what was written.

Overall, in practice, reading LCD memory is of limited value given its narrow use cases.

--- bill

1 Like

Well, this concept has (not entirely surprisingly, just about anything is possible here :grin:) been touted here before.

Clearly you would not design both parts of a system to "share" a display (but I am pretty sure that has been asked here before) as it makes no sense, is just making things unnecessarily difficult. But the idea of intercepting data from an HD44780 display in a piece of equipment you did not design yourself is an albeit improbable, possibility.

There are two approaches to this. Your idea of taking over the display and reading back the data is one, which would require adding logic to switch all the control lines from the original processor to your interrogating system. This introduces a number of risks, particularly that of the original processor attempting to access at the same time.

Oh never mind, Bill has just submitted! :astonished:

1 Like

@bperrybap I'm really grateful for the explanation that you've put up as to why would this be a bad idea. Though I may not know the exact workings of the electronics that are being involved here, I do get a rough idea of how complex this gets as we progress, provided the bunch of issues that would arise while attempting this.

Now I do realize that reading the LCD memory have very few applications as it's hardly of any use in the electronics.
Thanks a ton for explaining clearly with all the examples. Really informative! :fire:

That's very much true. Also this gives me an idea of a new (of course complicated) scenario.
So let's say, we use another LCD as a backup and add a new logic to channel the data pins (of the IC, that writes the data to the original LCD) to this backup LCD, whenever we try to read from the original LCD so that whatever the data the IC sends (through the data pins) while we're trying to read, would be sent to the backup LCD. And after the reading is done, we switch the channels back to this original LCD, reverting back to the original circuit as a whole.
Again, this may also be impossible as the pins may disconnect in the middle of execution of a set of instructions that must be completed by the IC.
And btw, I'm not going to attempt this. I'm just wondering out of curiosity, whether this would theoretically be possible or not. :sweat_smile:

— Raj

Adding another LCD does not help or change the situation.
The logic needed to do the isolation would be roughly the same if not identical as with a single device.
And the big issue is how to ensure the LCD that is being read has not missed any updates.
If you isolate the LCD so you can read it (doesn't matter if there is 1 or 2 devices) the isolated LCD device will miss any updates that happen while it is being read.

--- bill

If you really wanted to intercept the data written to the LCD, then you would be best to use a hardware latch to capture the writes to it, given that it is only written to and never read.

In fact, this could be a "dummy" and you would have separated the actual display to be written by your new system instead with information adjusted to your requirement.

As Bill notes, you would still need to interpret that data, probably not worth the effort.