This project started out as a simple idea - get serial data out of a cheap scale. When I say cheap, I mean cheap. I wanted to get the weight data into a PC program, and a serial connection was the easiest way to do this.
My original plan was to find the processing IC for the display and take the raw data from there. Use an Arduino to process into a serial string and pass it to the PC. But that idea turned out to be impossible. The entire circuit for the balance was a "black blob". That's it. All I had to work with was the black blob IC and the raw LCD glass. This made things far more difficult, maybe impossible. But in the end, I pulled it off.
The LCD glass had 16 pins. I figured that for each value shown on the display, there would be a unique value on the pins. So if I could look at this value and assign it to a lookup table of weights, I could theoretically spit that value out of the serial port.
You can not have any DC on a raw LCD glass for a long period of time - it will destroy the liquid crystal. So the signals on the pins are all multiplexed, and turn on/off in a synchronous pattern. This means there is no "Vcc" or "Ground". All pins are turned on or off in a particular sequence to display a particular value. I say on or off....as if it could be that easy. There are FOUR different voltage levels - 0v thru 3v. My initial goal was to identify what sequences equated to the values of specific digits. It wasn't long until I found a pattern and cracked the code. This is what I had to work with. You might want to sit down before viewing the .pdf and the links to the scope shots below. And keep some Tylenol handy.
Finding Structure in Chaos
Now that I have the 19 total signals from the display fully decoded, I can think about how to go about processing them. There are two ideas - process the analog signals or convert the signals to binary, and then process them digitally. I decided on the latter because the signals are long, about 16ms, and there are only 4 voltage levels to deal with. I found that if I treated the 3 and 2 volt levels as 'high' and the 1 and 0 volt levels as 'low', I could develop a unique binary marker for each of the 19 signals.
The lower signal (purple) is the raw signal coming of the LCD display (pin 7) for place 1. This decodes to 'zero'. The yellow signal above is coming off the 4051 multiplexer. I'm using the 4051 to choose between the 8 different signals I need to read from the LCD. I'm using a PIC to generate the timing signal in blue. This is based upon a clock signal that is made from one of the backplane signals. The green signal is the output of the comparator. This is a unique, binary representation of the raw 'zero' signal in yellow. The next step is to use an Arduino (or some other processor) to convert the comparator output to something a PC can read.
This got me moving in the right direction. I was able to get rid of the LM339 and do it's job in the firmware. I'm also started controlling the 4051 multiplexer from the Arduino instead of the PIC. The PIC is still needed for the timing, however I changed the way it's doing this. Instead of generating a timing pulse for each bit, I'm generating a single pulse for the very first bit and using a delay to get the others. Also, I found that I did not need all eight bits to uniquely ID each digit. I only need four bits, so I'm getting just the even ones. This lightens the overhead, and the code runs much faster this way.
An overview of how this works -
The raw LCD data has four voltage levels - 0v, 1v, 2v, and 3v (seen in purple). You can see all of these signal in the 'Links' section below. I'm using the ADC of the Arduino to assign the 0v and 1v to a LOW bit. And the 2v and 3v to a HIGH bit. Like this:
Because the raw LCD data is repeating, I need to time when I take the measurement of each bit. This is where the backplane, AND gate, and PIC come into the picture. A backplane signal from PIN1 of the display (seen in yellow in the scope) is being fed into a CMOS AND gate. This signal never changes, and contains a single 3 volt peak that is 2ms long and appears every 16ms. The output of the AND gate is the clock signal that I'm using for the timing (seen in blue). Because it's 2ms wide, the same length as the raw LCD signal bits, I cannot use it the way it is. The PIC takes this signal and produces a sharper 500us signal (seen in green). So now I can say:
When timing pulse from PIC == 1
get bit data
get bit data
I do this four times, to get four bits, and put them in an array, where they'll later get decoded into a single numeric digit.