Referring to post: LCD data read and show on computer It was not clear what the final code is. Could you post the code and schema again, and if possible, an explanation of how it works?

My problem:

I need to read the information of a lcd 20x4 display, which is controlled by a PLC (which has the protected hex code), and send the data through the serial port.

For this I am using an arduino one to do the reading. I connected the arduino in parallel with the display data bus, to try to read the bits and convert later.

This is the schematic I'm using: enter image description here

Note: I have placed 1k resistors to make the pulldown on each pin, to avoid reading errors.

With this code:

enter image description here enter image description here

The problem is that I'm having these results in reading: enter image description here

No matter what appears on the screen, they are always invalid characters. If someone identifies where my problem is, I'll be very grateful.

  • No final code was posted as far as I can see, just pseudo-code that could be adapted to suit.
    – Finbarr
    Commented Oct 16, 2018 at 13:42
  • Stack Exchange is not a forum, and your "question" is not answerable.
    – brhans
    Commented Oct 16, 2018 at 13:48
  • I edited my question, I think it became clearer.
    – Joao Anacleto
    Commented Oct 16, 2018 at 14:10
  • The display shown in your picture is 16x2 display LM016L. Why do you think that your "a 20x4 display" has the same control method as the LM016L display? Commented Oct 16, 2018 at 17:21
  • Serial.print() will be too slow for this. Also your 1K resistors are potentially too stiff, if you want a keeper for undriven lines try 10K or larger. Ultimately, you need to either write code informed by actual understanding of the operations described in the LCD data sheet (including details of clock-data timing), or if you just want to do a general capture to analyze, you should instead use a cheap USB-based logic analyzer ala sigrok/pulseview which has a chance of having sufficient sampling rate to capture the operations asynchronously. Commented Oct 16, 2018 at 18:12

2 Answers 2


I would recommend ditching the the digitalRead in this case - it is performed sequentially, and is rather slow. As you only need to read 8 input lines, consider using Port register: The Arduino Uno comes with a total of three Ports which "hold" all of the I/O pins. Those are

  • PORTB = Digital Pins 8 through 13 plus the crystal pins
  • PORTC = Analog Input 0 through 5, reset pin
  • PORTD = Digital Pin 0 through 7

Since you need the RX and TX lines (Digital pin 0 and 1) for your serial communication, you will have to split the signal onto two registers.

I would recommend connecting D0 through D3 to Digital Pins 8 through 11 for the first four bits (meaning they'll go to bits 3 to 0 of Port B), and D4 through D7 to Analog Pins 0 To 3 (meaning they'll go to bits 3 to 0 of Port C). RW goes to Pin 7, RS to Pin 6, E to Pin 5.

The code you would then use to read the data would be this: uint8_t byte_displaydata = 0x00; uint8_t RW = 7; uint8_t RS = 6; uint8_t E = 5;

void setup() {
  Serial.begin(1200); //perhaps increase this a bit
  pinMode(RW, INPUT); //some speed is lost compared to register manipulation, but that is likely insignificant
  pinMode(RS, INPUT);
  DDRB &= ~((1 << DDRB0) | (1 << DDRB1) | (1 << DDRB2) | (1 << DDRB3)); //technical not necessary since they're initialized with 0
  DDRC &= ~((1 << DDRC0) | (1 << DDRC1) | (1 << DDRC2) | (1 << DDRC3));
  PORTB &= ~((1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2) | (1 << PORTB3)); //disable internal pullups
  PORTC &= ~((1 << PORTC0) | (1 << PORTC1) | (1 << PORTC2) | (1 << PORTC3));


void loop() {
  if(digitalRead(RS) == HIGH && digitalRead(E) == HIGH){
    byte_displaydata = 0x00; //reset byte_displaydata
    byte_displaydata = PINB << 4; //push PINB bits 3 to 0 to bits 7 to 4
    byte_displaydata |= (PINC & 0x0F); //filter PINC bits 3 to 0 and OR them into result bits 3 to 0

Please note that I have not tested this, and only recently have gotten started in AVR / Arduino. If anyone can look this over, I'd greatly appreciate it.

Source: Microchip ATmega328P datasheet, Arduino pin mapping


It is probably too late for the OP but there is a protocol sniffer for such LCD screens which use the HD44780 series LCD driver as, for example, the common LCD1602 does. The code is published here:


The data rate would be too fast for Serial.print() to print each character received in real time so a queue is used to consolidate the data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.