Reading from LCD 16x2

Yes, you can read a HD44780 if you have the RW pin under program control. Just look to see how a library checks the BUSY.

The speed of 4-bit or 8-bit interface is similar. You can write the single Enable strobe in 1us for an 8-bit. You can write the two strobes in 2us for a 4-bit.

The actual operation cycle takes 37us to complete. So you can write a fresh character every 37us. e.g. 1us + 36us to do something else. Or 2us + 35us to do something else. You may find this significant !

Of course, I am talking theoretically. The Arduino library probably wastes the 35us anyway. And will probably have some processing overhead.

It is a mystery why young people are so concerned with writing fast to an LCD. Your eyes can't read that fast. The actual liquid crystal takes time to change.


Many: Anyway, I've learned some quite interesting things along the way, in particular that an 8bit interface divides by two the communication time (relative to the 4bit interface that I was using) which will definitely be better in this project (considering I don't use much more other pins on my UNO anyway).

Again - it simply is not worth it. Use the 4-bit interface like everyone else! :grinning:

There is a delay involved in sending a command to the controller - but the delay is in the controller, not the interface!

While you could use the "busy" flag (which involves the same read command as you would use to read data) to minimise delay, it is in practice simpler just to invoke a delay. Now the trick is that the delay only occurs once you issue the command, and the command is only issued once it receives all eight bits. This means that you issue the second four bits immediately after issuing the first four bits, there is no delay between, only after you have issued the command, So in practice, there is negligible inefficiency in using the four bit mode and you will find it no faster to use the library in 8-bit mode.

Whilst the delay is written into the library, you could bypass that and remove the "busy waiting", writing your own code to perform the command transfer, then execute other code while waiting for the command to complete.

But again, the counting task in your situation is far slower than the delay involved in sending commands to the LCD and simplicity will win out. :grinning:

Ok... I'll keep it simple :D

One more thing. If you do use the busy flag in an attempt to get rid of the fixed delays involved in dealing with the LCD you should incorporate some sort of timeout sequence in your busy-flag code. Otherwise your entire program could hang up (waiting for the flag to change) if there is a problem with the LCD.


Thanks for this advice. Since the delay is so small I will keep it simple in the context of this project but I’ll try this afterwards, if only to get a better understanding of LCD display.

Many: Thank you for your answers. The reason I'm doing this is that I am designing a digital clock to be displaid on the LCD without using an RTC module. What I want is to have a method that would allow the user to set the time using buttonswitches from the breadboard.

As paul said, from that description there is absolutely no reason to read the display. In fact, you probably need to re-think your implementation. For something like that, the typical design is to separate things into separate and distinct "layers". - Time keeping - Time Display - Time setting

For tracking time, you will want to use something that runs in the background. And the best way to track time is actually not to track it in human form of (hr, min, sec, etc...) but by using an epoch counter. The Time library is great for handling time as it tracks time using an epoch an includes all the necessary API functions to access the time, convert it to human elements like yr, mnth, day, hr, min, sec, etc, and to set the time. The Time library can work with or without an RTC.

Then all you need is a way to display the time elements and a user interface to set it.

It doesn't make much sense to be worrying about the timing overhead of things like 4 bit vs 8 bit as as 4 bit mode when used across something as slow as a i2c i/o expander can still update the display memory faster than the liquid crystal inside the LCD display can rotate its molecules to change the actual pixels. And then the human eye is not particularly fast at seeing changes so the speed of updating the display of 4bit vs 8bit is not a visual issue. It may be a CPU overhead issue if you have other CPU needs in your code as a slower interface uses more CPU, but it is pretty much a non issue from a visual perspective. And for something as simple as a clock, there shouldn't be any realtime CPU overhead issues.

--- bill

I know how it uses just 4 bits to communicate what needs 8 bits. First it flashes the first 4 bits of the code and the. last 4 bits of the code.

Commenting to unlock the thread at the request of a forum member.

Hi to everybody,

I believe I was Many time ago.

I can't explain how, why and ... but I asked because I am a cybersecurity expert, and those days I was looking for answers in question. Nowadays I am developing a project called SOS. It is a project of 1k of ways to send an SOS signal.

In the project I have implemented what I asked here, thanks to you all and the data sheets plus the docs. Then, I am here to advice the code is ready. On GitHub: Please pay attention to it!

Why did I this project of reading RAM of LCD? Simply: resources. Avoid using a buffer to save shell commands and answers, in case of a situation of emergency where we won't have enough... the philosophy is to keep the resources alive in consequence, to work harder. Have a look the a use case in the same project. Subproject number 1: KeyToLCDEMAIL2... nothing else. Here to serve & try to help. Best regards and thanks to all.

freeyournetwork, Lots of poetry/philosophy about life in your project. I am not grasping the project. I do see a modified LiquidCrystal library with the added code in a recv() and read4bits() to read data from DDRAM but it does not appear to be used in the KeyToLCDEMAIL2.ino sketch. So I don't understand the use case for needing to read the LCD ddram.

BTW, the hd44780 library includes a read() function and a status() function to allow reading data from ddram and getting the lcd status value which includes the current ddram address. These functions are available across multiple i/o classes so you can use them on lcds that are controlled directly with pins or via a i2c backpack.

--- bill

Hello bill (bperrybap),

thanks for your interesnt on the project and my reply. I have to say that I am a bit scared of receiving bad words, but at the moment all of those are plenty of grace.

Well, I need to explain a bit the project and the motivation, and I do as follows. The covid-19 made me to encourage against the need of resources, and I was wondering to save memory from the LCD readings... (sorry my bad english). But the project is abdandoned and I don't know really why I removed the implementations of the LCD char reading... but I did to be able to use the SOS... well, no matters. The true is that I was thinking first to do some way and later I realized to do it better other way. And as it costs to me a lot to do the code for reading the LCD; I decided to publish it.

The true is also that I hope somebody can use it instead of me, or also as me. I did first, but later I removed it because I found other way to do a tty on the LCD and the SIM... well, that's how I can explain it. If someone wants to use the code and to improve it is welcome. I was used to encourage against unimplemnted things and try to do them. Usually there're not needed, and some others I just remove them from the main code. Anyway, the project is now finished... ( I mean Idk if it will be used somewhere by me or anyone else...).

Poetry is because those days were really hard to me, we are experiencing a hard situation where I was trying to situate me in a very chaotic world, and nobody helped. Well, that's not really true. I mean, nobody else helped on the development actively or shared my worrying... which I recognize was really high. But... I realized also I can not fight against the world, I can try to do my best, but if I see is a waste of time and energy to try to save the world with SOS systems to help each other in a very chaotic world, and people is thinking in going for party for example (I don't judge I only say the main thinking of myself) instead of doing something to help... what can a man only do for the rest of the world? A lot of people, well, some 5 people, helped me on Tg and Fb with likes... it was very interesting and heavily hard to speak about the topic, but... I also realized those systems are really also hard to build for an expert, how complicated may be to people without skills? And without the proper injection of money or help, the project went inside the place of the sunken dreams... sorry. I tried. The probability of losing was high, the only way to do it was to try it and hope the people will help. That's the way I was so poetic... and philosophic. But... maybe I was wrong and the world isn't so wrong actually. I really don't know. I just try to continue my life and try to give the best I have.

Thanks by your help. Hope this at least, helps also.

--- Abel

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.

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

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: