Stealing data sent to an LCD

Hey guys,

I have done some basic work interfacing an arduino and an LCD and as far as I understand the arduino sends serial information to the LCD in order for the onboard IC's to understand and display on the screen.

Well I want to reverse this....

I have a device that measures a lasers power then displays the result on to the detachable LCD module.

Well I would like to take the info that the circuit is transmitting to the LCD and take that in as serial data to the arduino. Is this possible? The LCD module is a standard 16 pin configuration, so I assume pin 7 - 14 are used as serial outputs to the LCD correct?

We'd need a little more info. Do you have a datasheet, part number, etc for the LCD you have?

Model number is SVM802B-1/V2

Datasheet is here... http://www.datasheet4u.net/download.php?id=611907

I just need some direction (link, code snippet... anything) to intercept the data and make it into something the Arduino can understand.

Anyone???

so I assume pin 7 - 14 are used as serial outputs to the LCD correct?

Think not, I think it is parallel 7-14 = 8 datalines = 1 byte in parallel.

You could try to read them with a 74HC165 shiftin - http://www.arduino.cc/en/Tutorial/ShiftIn - and - http://arduino.cc/en/Reference/ShiftIn -

So the chip basically "records" all input then spits it out once the ardunio asks for it.. is that correct?

If so, does it matter what format the incoming communication is in? I believe I have found the 4 terminals responsible for the data transmission. But I have confirmed that pin 7 - 14 are D0 - D7 So I assume this is where the data is sent.

One thing - if it is a standard HD44780 compatible LCD, it is a Parallel device, not serial. There are major differences between the 2 in how they work and what your solution has to be.

A Shift register will normally record 1 byte of data, i.e. 1 character. It does this by shifting in 8 bits, 1 bit at a time.

Your Arduino really has to do nothing other than sit listening to the LCD lines though, in case it ends up missing something if it is off somewhere else executing something else in a program loop.

As far as I know it is a standard HD44780... so it is a parallel interface device.

So with the suggested CD4021B shift register I can accomplish this? If this is not available what type of shift register am I looking for?

EDIT: Is this what I'm looking for? http://jaycar.com.au/products_uploaded/ZC4858.pdf

Thanks in advance

Is this what I'm looking for?

looks good, maybe you should find a version that is easier to solder ?

Ok, So I've bought 2 of these shift registers now I need program them in.

I've connected them as shown below...

I've also used the code supplied here http://arduino.cc/en/Tutorial/ShftIn11

This only gives me outputs like below...

111000

111000

111000

111000

11100

11000

111000

11100

11000

111000

11000

Which I have tried to convert to bytes but only getting garbage.

I know the onboard chip runs at 4800 baud, how can I sync the shift register, Arduino and LCD display chip?

Aaaaaaanyone? :~

What does your code look like? Would be interesting to see what your doing.

Still instead of interception what about reading from the LCD.
The LCD has ram so you could try to access it and copy what is in the screens memory.

Or, working with what you have, the character generator rom table in the TC1602A pdf might help you decode the response.

I used the code found on the link I provided above.

//**************************************************************//
//  Name    : shiftIn Example 1.1                              //
//  Author  : Carlyn Maw                                        //
//  Date    : 25 Jan, 2007                                      //
//  Version : 1.0                                               //
//  Notes   : Code for using a CD4021B Shift Register    	//
//          :                                                   //
//****************************************************************

//define where your pins are
int latchPin = 8;
int dataPin = 9;
int clockPin = 7;

//Define variables to hold the data 
//for shift register.
//starting with a non-zero numbers can help
//troubleshoot
byte switchVar1 = 72;  //01001000

void setup() {
  //start serial
  Serial.begin(9600);

  //define pin modes
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  pinMode(dataPin, INPUT);

}

void loop() {

  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(latchPin,1);
  //set it to 1 to collect parallel data, wait
  delayMicroseconds(20);
  //set it to 0 to transmit data serially  
  digitalWrite(latchPin,0);

  //while the shift register is in serial mode
  //collect each shift register into a byte
  //the register attached to the chip comes in first 
  switchVar1 = shiftIn(dataPin, clockPin);

  //Print out the results.
  //leading 0's at the top of the byte 
  //(7, 6, 5, etc) will be dropped before 
  //the first pin that has a high input
  //reading  
  Serial.println(switchVar1, BYTE);

//white space
Serial.println("-------------------");
//delay so all these print satements can keep up. 


}

//------------------------------------------------end main loop

////// ----------------------------------------shiftIn function
///// just needs the location of the data pin and the clock pin
///// it returns a byte with each bit in the byte corresponding
///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0

byte shiftIn(int myDataPin, int myClockPin) { 
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
//we will be holding the clock pin high 8 times (0,..,7) at the
//end of each time through the for loop

//at the begining of each loop when we set the clock low, it will
//be doing the necessary low to high drop to cause the shift
//register's DataPin to change state based on the value
//of the next bit in its serial information flow.
//The register transmits the information about the pins from pin 7 to pin 0
//so that is why our function counts down
  for (i=7; i>=0; i--)
  {
    digitalWrite(myClockPin, 0);
    delayMicroseconds(0.2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      //set the bit to 0 no matter what
      myDataIn = myDataIn | (1 << i);
    }
    else {
      //turn it off -- only necessary for debuging
     //print statement since myDataIn starts as 0
      pinState = 0;
    }

    //Debuging print statements
    //Serial.print(pinState);
    //Serial.print("     ");
    //Serial.println (dataIn, BIN);

    digitalWrite(myClockPin, 1);

  }
  //debuging print statements whitespace
  //Serial.println();
  //Serial.println(myDataIn, BIN);
  return myDataIn;
}

I'm just trying to get some consistent results.

The output should look like this:

0mW
eng dnw up

But I'm getting a bunch of random letters with no consistency when I change the output to byte.

Think you must look if the LCD has some sort of clock signal, and synchronize your duino to that.

This is the pin config..

  1. VSS
  2. VDD
  3. V0
  4. RS
  5. R/W
  6. E
    7 ---- 14
    D0----D7

So which pin will give me the clock pin. Personally I think this can all be fixed with proper syncing. The wiring looks right.

Come on guys.... If you reply to a thread, keep checking back...

There is a problem with your logic.

You don't seem to know/test to see when the screen is being updated.
I see you just have a loop that is constantly reading the screens data pins.
You need to work out how to be in sync with the data being send to the screens processor.
You then need to decode what the messages being sent to the screen is,
is it change to cursor location in screen memory or is it an update/change to the value in screen memory.
The character codes on page 15 of http://www.adafruit.com/datasheets/TC1602A-01T.pdf might help decoding the text.

Also reading arduino-0022\libraries\LiquidCrystal\LiquidCrystal.cpp may help in working out what's going on.

http://www.adafruit.com/datasheets/HD44780.pdf Page 5 might also help.
Pin 6 E - MPU Starts data read/write that might also be the one to look at as it's this start you want to catch.
Also Page 8

Busy Flag (BF)
When the busy flag is 1, the HD44780U is in the internal operation mode, and the next instruction will not
be accepted. When RS = 0 and R/W = 1 (Table 1), the busy flag is output to DB7. The next instruction
must be written after ensuring that the busy flag is 0.

A good way to debug your routine is to have one arduino running the helloworld example and a 2nd arduino running your snoop hack.
That way you cut down on the random variables of getting it to work with a random device by getting it going with someone simple.

I am guessing you might be able to get timing/sync/update notification by monitoring pins 4 or 5 of the LCD, but NB that a guess.

Also when displaying your 8 bit codes include the leading 0's so 11100 is 00011100 make it easier to see what's going.

So your current returns where and I think decodes to; (base on page 17 character codes from http://www.adafruit.com/datasheets/HD44780.pdf)

0011 1000 - 8

0011 1000 - 8

0011 1000 - 8

0011 1000 - 8

0001 1100 - either blank or custom character 5a??

0001 1000 - either blank or custom character 1a?? not sure

0011 1000 - 8

0001 1100 - ...

0001 1000

0011 1000

0001 1000

I reserve the rigth to be wrong :slight_smile:

Ok.... Now I'm getting somewhere...

Pin 6 - E is indeed the Clock pin I was looking for.... I modified the code below to only read from the shift register when the clock pin is high.

This is the current code...

//**************************************************************//
//  Name    : shiftIn Example 1.1                              //
//  Author  : Carlyn Maw                                        //
//  Date    : 25 Jan, 2007                                      //
//  Version : 1.0                                               //
//  Notes   : Code for using a CD4021B Shift Register    	//
//          :                                                   //
//****************************************************************

//define where your pins are
int latchPin = 8;
int dataPin = 9;
int clockPin = 7;
int LEDClk = 3;

//Define variables to hold the data 
//for shift register.
//starting with a non-zero numbers can help
//troubleshoot
byte switchVar1 = 72;  //01001000

void setup() {
  //start serial
  Serial.begin(9600);

  //define pin modes
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  pinMode(dataPin, INPUT);
  pinMode(LEDClk, INPUT);

}

void loop() {

while (digitalRead(LEDClk) == HIGH ){
  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(latchPin,1);
  //set it to 1 to collect parallel data, wait
  //delayMicroseconds(20);
  //set it to 0 to transmit data serially  
  digitalWrite(latchPin,0);

  //while the shift register is in serial mode
  //collect each shift register into a byte
  //the register attached to the chip comes in first 
  switchVar1 = shiftIn(dataPin, clockPin);

  //Print out the results.
  //leading 0's at the top of the byte 
  //(7, 6, 5, etc) will be dropped before 
  //the first pin that has a high input
  //reading  
  Serial.println(switchVar1, BIN);

//white space
Serial.println("-------------------");
//delay so all these print satements can keep up. 


}}

//------------------------------------------------end main loop

////// ----------------------------------------shiftIn function
///// just needs the location of the data pin and the clock pin
///// it returns a byte with each bit in the byte corresponding
///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0

byte shiftIn(int myDataPin, int myClockPin) { 
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
//we will be holding the clock pin high 8 times (0,..,7) at the
//end of each time through the for loop

//at the begining of each loop when we set the clock low, it will
//be doing the necessary low to high drop to cause the shift
//register's DataPin to change state based on the value
//of the next bit in its serial information flow.
//The register transmits the information about the pins from pin 7 to pin 0
//so that is why our function counts down
  for (i=7; i>=0; i--)
  {
    digitalWrite(myClockPin, 0);
    //delayMicroseconds(0.2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      //set the bit to 0 no matter what
      myDataIn = myDataIn | (1 << i);
    }
    else {
      //turn it off -- only necessary for debuging
     //print statement since myDataIn starts as 0
      pinState = 0;
    }

    //Debuging print statements
    //Serial.print(pinState);
    //Serial.print("     ");
    //Serial.println (dataIn, BIN);

    digitalWrite(myClockPin, 1);

  }
  //debuging print statements whitespace
  //Serial.println();
  //Serial.println(myDataIn, BIN);
  return myDataIn;
}

Here is the output I am getting.... (note the consistency in the output :D) This is in BIN (binary) output mode... (read all of it)

-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111

***Repeat***

I have a feeling the Shift register and arduino can not speak to each other fast enough... Do you think this could be the problem?

As I heat up the Laser sensor I can see shifts in the output... for example...

-------------------
11111111
-------------------
11111111
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
0
-------------------
0
-------------------
11111111
-------------------
11111111
-------------------
11111111
-------------------
11111111
-------------------
0
-------------------
0
-------------------
0
-------------------
0
-------------------
0

Does this make any sense to anyone?

How can I take this and turn it into meaningful data?

Just some thoughts. Have not gone thru the whole thread to see what has been discovered so these are only ideas.

First off I would determine if the lcd is being driven in 4 or 8 bit mode. That way you know what to look for in the data being sent.
Is the R/W being used? That adds to the complexity.The data bus is bi-directional.

I would just use the pins of the arduino to hookup to it bypassing the shift register to reduce the problem to its simplest before taking on another.

Treat the enable pin as an interrupt source and in the service routine read the data pins. You will also need to read the RS pin to
see if it's a command or data. If the R/W is being used then that will also need to be delt with.

Driving an lcd is not set in stone- meaning that there are several ways to do it and that would be my main task at hand in finding out how to interface to it.

Hope this helps.

I have a feeling the Shift register and arduino can not speak to each other fast enough

Possibly, if you have enough pins I wouldn't bother with the added complication of a serial SR, just read the signals directly through a port as justone suggested.


Rob