Reading Faceplate “Audio Mode” Knob

Once I got a retired faceplate’s LCD up and running, I realized I was wrong about its backlight circuitry. Now that it’s been sorted out, attention returns to the LCD. I want to map out all the segments, which means I need to get some way to interactive select individual segments. Recently I’ve used ESPHome’s network capabilities for interactivity, but this project uses an Arduino Nano for its 5V operating voltage. I can wire up my own physical control, but the faceplate already had some on board. Earlier probing established Power/Volume knob is a potentiometer, and Audio Mode knob is a quadrature encoder with detent.

The encoder is perfect for selecting individual segments. I can write code to activate one segment at a time. When the knob is turned one way, I can move to adjacent segments in one direction. When the knob is turned the other way, segment selection can follow suit. However, this knob does have one twist relative to my prior experience: Each detent on this encoder is actually two steps. When the knob is at rest (at a detent) the A and B pins are always different. (High/low or low/high). Intermediate values where A and B pins are the same (high/high or low/low) occur between detents.

This places timing demands for reading that knob. For encoders where each detent is a single step change and turned by human hands, polling once every hundred millisecond or so would be fast enough. However, since this knob can flash through a step very quickly between detents, I need to make sure those steps do not get lost.

There are many quadrature encoder libraries available for the Arduino platform. I selected this one by Paul Stoffregen, who I know as the brains behind the Teensy line of products. When working with interrupt-capable pins, this library will set up hardware monitoring of any changes in encoder state. This makes it very unlikely for encoder steps to get lost. According to Arduino documentation for attachInterrupt(), all ATmega328-based Arduino boards (including the Arduino Nano I’m using) have two interrupt-capable pins: 2 and 3. Using those pins resulted in reliable reading of knob position for mapping out segments of this LCD.

Source code for this investigation is publicly available on GitHub.

Two Separate Sets of Faceplate Illumination (Toyota 86120-08010)

I’ve successfully programmed an Arduino to interface with LCD controller on the faceplate of a retired car tape deck. When under the control of its original mainboard, the LCD segments and the LCD backlight always turned on and off in lockstep, leading me to think LCD backlight was under control of the LCD segment controller. But now that I have active LCD segments but no LCD backlight, I know my assumption was wrong. I’ll need to look elsewhere.

Looking at my notes from measuring voltage of each pin relative to data ground, two candidates stood out because their voltage levels changed when the LCD was active vs. inactive. When the LCD is on, there is ~6V difference between them. And when the LCD is off, there is ~0.5V between them. One candidate’s label was cropped at the bottom. Earlier I guessed maybe it said “CD-BL” but now that I look closer, I think the vertical bar to the left is part of the text: a “L” with its bottom cropped. That label is possibly “LCD-BL” which I optimistically expand to “Liquid Crystal Display Back Light”. The other candidate pin is labeled “BL-” which would be the negative terminal. Notably, “BL-” fluctuated relative to “GND” so these two pins, if they are our targets, have their own voltage planes.

The first test was with my backlight LED tester, which quickly shot up to the preset current limit of 20mA at less than 1V while the backlight stayed dark. I then measured with an Ohm meter, which indicated just 10 Ohms between these two pins. If that is a LED current-limiting resistor, it is the smallest I’ve ever measured. Might this backlight be some technology other than LEDs? I don’t know how a compact fluorescent light would look like under an Ohm meter. (I do know a filament bulb usually shows up as a short a.k.a. direct connection with no resistance.) I can’t see the actual light source, as it is buried within the metal case of the LCD assembly.

Well, this is a piece of salvaged electronics and I have little to lose. Especially since I believe the backlight is on its own circuit. So if I accidently destroy the backlight, I still have the rest of the faceplate to play with. I soldered wires to “LCD-BL” and “BL-” and connected it to my bench power supply. Gradually turning up the voltage, I start seeing a dull glow at just under 5V and got brighter as it reached 6V.

Illumination of this backlight isn’t great, but consistent with how it looked when I powered it up with the original mainboard.

The diffuser behind this LCD isn’t nearly as good as what we see behind, say, the screen of an Amazon Fire tablet. But it works well enough for us to see the LCD segments in the dark, and that’s all it needed to do in a car. These LEDs do not need to be daylight visible, as the LCD is readable in the presence of ambient daylight without backlight help.

At 6V this backlight drew almost 70mA, which is LED territory after all. If this was a piece of cheap consumer electronics, I would say 70mA indicates three heavily-driven LEDs. But this is from a Toyota, a brand with reputation for engineering for longevity. So I’m going to assume it actually represents four (or more) lightly driven LEDs. I increased the voltage until 9V, at which point it drew 80mA and was still pretty dim and uneven. I guess “bright enough to be legible at 6V” is all we’re going to get out of this backlight.

Since I had the bench power supply set up for testing LEDs anyway, I connected wires to two other pins “ILL” and “ILL-” which I had already determined to be on their own independent voltage plane as well. These wires are connected to the in-car dashboard illumination circuit, which has a dimmer knob. Being on a separate power plane explains the behavior I remember from using this tape deck in the car: lights illuminating faceplate buttons would change in brightness as I moved the dimmer knob, but the LCD backlight LED stayed at constant illumination. When I powered them directly on ILL/ILL-, I start seeing a tiny bit of glow at just over 5V (<10mA) and brighter as the voltage is increased.

I stopped at 14.4V (80mA) which is the maximum recommended voltage level for automotive lead-acid batteries, and thus likely to be the ceiling for automotive electrical systems like this one.

Between these two sets of lights, it means any project to repurpose them will need to generate multiple voltages. Up to 14.4V for button backlights (variable if we want dimming), 6V for LCD backlight, and 5V for digital logic including physical controls like the Audio Mode knob.

Successful Arduino Test of LC75853N Control

Using a Saleae Logic 8 Analyzer, I’ve examined the communication protocol between the mainboard and faceplate of a car tape deck. These signals match expectations of a Sanyo LC75853N LCD controller which uses Sanyo’s proprietary CCB (Computer Control Bus) protocol. CCB has some resemblance to SPI and I2C but is neither, though close enough to SPI for me to use the SPI analyzer mode on a Saleae analyzer.

But “close enough” won’t be good enough for the next step: take an Arduino Nano and write code to talk to the LCD controller via CCB, copying the data waveform behavior I saw as closely as I can. Arduino has a library for SPI that assumes control of the enable pin, which has different behavior under CCB so that would not work here. I investigated using the shiftIn() and shiftOut() routines, which is part of the standard Arduino library. They are software implementations of a clocked serial data transfer routine, but unfortunately their clock signal behavior is different from what I saw of CCB under the logic analyzer. (Active-low vs. active-high.) In order to emulate behavior of the tape deck mainboard, I would have to write my own software implementation of CCB serial data transfer.

On the hardware side, I could no longer avoid soldering to small surface-mount connector pins on the back of the faceplate. I started simple by soldering the four data communication wires: LCD-DO, LCD-DI, LCD-CLK, and LCD-CE. Probing the circuit board with my meter, the only alternative soldering points were directly to the LC75853N, and those pins are even smaller. However, I found alternatives for ACC5V and GND: those were directly connected to the volume control potentiometer, which has nice big through-hole pins for me to solder to. I soldered these wires to a small prototype board with header pins, which then plugged into a breadboard alongside my Arduino Nano.

As a “Hello World” for CCB, I wrote code to replicate the control signals as closely as I could. I won’t try to replicate the exact timing of every pulse captured by my logic analyzer because (1) Arduino doesn’t make that level of control easy and (2) the CBB spec has no explicit requirement for precise timing anyway. However, I aim to make sure relationship between every clock, data, and enable pin high/low transition is preserved. I can verify this by capturing my Arduino output and compared the output to what I captured from the tape deck mainboard, look for where they are different, and fix differences over several iterations. Finally, I was satisfied the data waveforms look the same (minus the timing caveat above) and connected the faceplate.

These are almost the same LCD segments that are visible when I captured the data communication between mainboard and faceplate.

The only difference I see is “ST” in the upper right, which lights up when the FM tuner has a good enough signal to obtain stereo audio. Since this tape deck didn’t have an antenna attached, “ST” blinks on and off. Apparently, I had taken this picture when “ST” was on, and the recorded control signal I played back on an Arduino was when it was off. This is close enough to call my first test a success.

The other visible difference was the backlight: illuminated when I captured the data control message, but dark when I played it back. I had hoped the backlight was under LC75853N control somehow, but it looks like those LEDs are actually separately controlled.

Source code for this investigation is publicly available on GitHub.

Logic Analyzer on Sanyo LC75853N Key Scan Input

I’m learning to understand control communications for a Sanyo LC75853N, which drives the LCD in the stock tape deck head unit of a 1998 Toyota Camry LE. My goal is to control the faceplate independent of the rest of the head unit, which means learning about Sanyo’s proprietary CCB (computer control bus) protocol. CCB resembles some parts of SPI and some parts of I2C but is neither of them. I was primarily focused on the LCD output, but in setting up my logic analyzer to look at LCD output control, I also have everything to examine keypress input.

Here is the Saleae logic analyzer output for the chip reporting that the volume knob was pressed, which is designed as the on/off toggle for this tape deck. The controller toggled LCD-CLK 32 times during this data transmission. Datasheet says the first 30 bits represent state for each of the scanned keys, followed by one bit representing sleep state, and one bit of padding whose state is irrelevant. Here the 0x08 represents the single scanned key that corresponds to the knob being pressed.

Before that happened, though, were several events of note. When a CCB peripheral wants to report data to the controller, it pulls the DO line low. (Spec sheet says DO has a 1k – 10k pull-up resistor.) It then waits for the controller to emit a peripheral address and then raise CE.

  • If the controller emitted the peripheral’s address, then it can start using DO to report bits upon each CLK pulse.
  • If the controller emitted another peripheral’s address, then it releases DO (letting it be pulled high again) and wait until CE is low, at which point it pulls DO low again.

When I read this part of the spec, I was confused at how the LC75853N would know whether to transmit or to receive when its address was called. Eventually I found the answer: it has two different addresses! Address 0x42 receives LCD data from the controller, and address 0x43 reports key scan data to the controller. I had missed the difference when I looked at the logic analyzer output earlier, 0x42 looked a lot like 0x43 when I was skimming through output. But it’s plainly there once I was paying attention. Address is transmitted on DI from the least significant bit first: 1100 0010.

Counting buttons on this faceplate, I don’t think it wired up all 30 possible key scans. But aside from the power button (pressing volume knob) logged here, I don’t know what they are. I might map them once I can perform CCB communication to read these key press reports. And if I fail to do that… I guess I wouldn’t care anyway. Onward to the Arduino!

Logic Analyzer on Sanyo LC75853N LCD Control

My Saleae Logic 8 analyzer is now tapped into communication between the mainboard and face plate of a tape deck. A quick examination of the captured data looks reasonable, now it is time to dig into the data, compare against the LC75853 datasheet, and understand what is going on with LCD output control.

Within the ~3/4 second of the faceplate getting power, this sequence is transmitted repeatedly approximately once every 5 milliseconds. Zooming in, I see they are three consecutive CCB transmissions to address 0x42:


Guided by the datasheet, I interpret them as:

  • Most of the 0x00 bits indicate the corresponding LCD segment is to be turned off.
  • Some of the 0x00 bits in the second and third set are fixed data.
  • In the first set, the two bits in 0xC0 maps to S0 and S1, which controls sleep mode. S0 =1 and S1=1 is one of three available sleep modes.
  • Also in the first set, the single bit in 0x10 translates to SC, the segment on/off control data. SC=1 means display state is off.
  • For the second and third set, they each have a single bit that appear to be fixed within the section labeled as DD (direction data) and their values written into the timing diagram.

After that initial ~3/4 of a second, the pattern makes a minor change and repeats less frequently: once every 50 milliseconds:


The two bits associated with sleep mode are now zeroes. Sleep flags S0=0 and S1=0 means “Normal operation”, so the chip is awake. SC is still 1, though, so LCD is still off.

Then I pressed the power button. This triggered a set of events (probably related to key scan reporting) that I will investigate later. Right now, I am focused on how the LCD control message changed to display “FM 1 CH 1 87.9”


The end of first set changed from 0x10 to 0x00. This cleared the SC flag, so now LCD is on. There are other control bits in the first set of bytes and they are all zero.

  • K0 and K1 set to zero means none of the key scan pins were reassigned to segment control duty, so the chip retains ability to scan up to 30 keys.
  • P0 and P1 set to zero means none of the segment pins were reassigned to digital output duty, so the chip can control a maximum of 120 segments.
  • DR set to zero means 1/3 bias drive voltage.

The display backlight is also illuminated now, but which of these bits are responsible? For now, that is still an unknown. Until I get more information otherwise, I’ll proceed on the assumption that all remaining bits are LCD segment control.

To get more information, I pressed the “Mode” knob changing the display to “BAS 0” and its control message to this:


That’s a lot of changes!

For a smaller delta, I turned the knob one step so it now shows “BAS 1”.


This is a more manageable set of changes. A single step changes “0” to “1”, which on a 7-segment display means turning off four segments. A change from 0xC0 to 0x80 turns off one bit, and from 0x0D to 0x00 turns off three bits. This matches expectation of deactivating four segments.

I didn’t take pictures for the next experiment: While in FM radio mode, I press the tuner up button once. This moved it off the first preset so “CH 1” disappeared and now the display shows “FM 1 88.1”:


Then I pressed it again, so it now displays “FM 1 88.3”:


All changes are in the first part of the control message. Changing from 0x10 to 0xD0 turns on two bits, 0xD1 to 0xD9 turns on one bit. These added up to the three activated segments, matching expectation of going from a “1” to “3” on a seven-segment numeric display.

These observations give me confidence that we are indeed looking at control bits corresponding to individual segments on screen. Not enough information to map out all the segments to their corresponding bits, but I am postponing that task until I have individual control through code. It would be much easier to map out segments when they are under my control. And if I fail to obtain control, I wouldn’t care about the segment map anyway.

With some confidence I understand the output side, now to look at the input side.

Sanyo CCB Close Enough to SPI For Logic Analyzer

I’m examining the control signals for a Sanyo LC75853N LCD driver chip, which uses a Sanyo proprietary protocol they call CCB. (Computer Control Bus.) It’s popular enough that I could find CCB reference material online, but it’s not popular enough to be natively understood by Saleae’s Logic Analyzer software. Beyond Saleae’s set is a list of Community Shared Analyzers but Sanyo CCB didn’t make the cut there, either. Those additional analyzers were written using Saleae’s Protocol Analyzer SDK so there is the option to write one for CCB. For the purpose of initial experimentation, though, their default SPI analyzer is close enough.

Before we even try using the SPI analyzer, we can look at the raw data. CCB transmits the peripheral address before raising CE. Here I can see 0x42 hexadecimal, or 0b01000010 binary. (The white binary numbers were not part of Saleae software, I drew it in afterwards.) In an unfortunate bit of coincidence, this binary value is symmetric so it alone couldn’t tell us if CCB transfer least-significant bit first or most-significant-bit first. According to spec, it is least-significant-bit first. Seeing this gave me the confidence I’ve wired up everything correctly for further probing.

The clock pulses measured out to be in the ballpark of 400kHz, which I can probably work with. But more importantly, I was relieved to see that the clock pulse widths varied somewhat between transmitted bits. This is encouraging because it meant the protocol is graceful under irregular clock pulses, making it more likely I can successfully communicate using CCB in software. Which is great because I don’t have dedicated CCB communication peripheral hardware.

The next step was to activate SPI analyzer with the following parameters. The biggest difference between CCB and SPI is the behavior of CE line, and thankfully Saleae’s SPI analyzer can be configured to ignore CE. (“Enable” set to “None”.) I set the SPI analyzer options to the following values to decode all the values regardless of CE status:

SPI Analyzer OptionValue
Significant BitLeast Significant Bit First
Bits per Transfer8 Bits per Transfer
Clock StateClock is High when inactive
Clock PhaseData is Valid on Clock Trailing Edge
Enable Line(Doesn’t matter when “Enable” is “None”)

Now the software can decode data for us. This time, the decoded values 0x42, etc. in this image was drawn by the software.

This was the start of the very first data transmission after I applied power to the tape deck. Which is why CLK started as low even though it is normally high when inactivity. When Enable is set to None, I see all the data regardless of CE status.

First question to answer: the B in CCB is “Bus”. How many devices are on this bus? Taking advantage of the difference between CCB and SPI, I can tell the SPI analyzer to decode just the CCB address by saying CE is Active Low:

SPI Analyzer OptionValue
Enable LineEnable is Active Low

The decoded values on LCD-DI were all 0x42, which tells me the LCD control chip is the only peripheral on this bus, which makes things simpler. I won’t have to worry about reading data intended for the wrong device. And once I decided I didn’t have to worry about different addresses anymore, I can switch the SPI Analyzer over to Active High CE. This will cause the analyzer to ignore addresses (since I expect them to all be 0x42) transmitted while CE is low and decode just the data.

SPI Analyzer OptionValue
Enable LineEnable is Active High

Within the ~3/4 second of the faceplate getting power, something is transmitted repeatedly approximately once every 5 milliseconds. Zooming in, I see they are three consecutive CCB transmissions to address 0x42:


Next: compare this captured data to the LC75853N datasheet to see if they make sense.

Sanyo LC75853N LCD Driver Archaeology

I’ve soldered wires to the connector between the mainboard and faceplate of the stock tape deck audio head unit from a 1998 Toyota Camry LE. (86120-08010) My goal is to learn enough to control the faceplate with my own creation independent of the mainboard. Since these two circuit boards can still be powered up, I can probe their voltages and listen to communications between them. A skilled electronics hacker can make sense out of the waterfall of bits, but I don’t have that level of skill yet. I need a little more information, and I started with this very prominent chip on the faceplate.

I couldn’t find where Sanyo hosts their electronic component datasheets, I kept stumble into unrelated areas like their consumer electronics site. This is a common problem when dealing with products made by huge companies with diverse product lines. There’s also the problem that Sanyo has been acquired by Panasonic in 2011 (Wikipedia) so it’s quite possible the relevant divisions have been merged or shut down and their website disappeared.

Seeking another source, I searched for this chip at Digi-Key. Their database did not list this exact item, but there were a few other LC7583 variants listed as “Obsolete” and without datasheet. I ultimately resorted to going through one of those internet sites that archive old PDFs. I find it annoying to have to wade through a bunch of “Click here to download!” ads that try to trick you into downloading irrelevant things that may or may not hide malware. It’s always a hunt for the actual link to the PDF we want, which may or may not have been modified maliciously. But eventually I ended up with Sanyo datasheet for “LC75853NE, 75853NW” which is hopefully close enough. The PDF was also slathered with the annoying site’s watermark, but I hope that’s all the annoyances in that file.

Here is the summary and high-level block diagram:

1/3 duty LCD display drivers that can directly drive up to 126 segments and can control up to four general-purpose output ports. These products also incorporate a key scan circuit that accepts input from up to 30 keys

Digging further into the datasheet, I learned of caveats with that summary. It is not possible to have simultaneous control 126 segments, four output pins, and scan 30 keys. In order to get 126 segments, we have to reallocate two key scan pins cutting the number of scannable keys by 10. And in order to use four output ports, we have to reallocate four segment pins cutting the number of addressable segments by 12. I’m sure such flexibility is useful for adapting to different usages, but it also means I will have to figure out the specific configuration used by this faceplate.

The operating voltage range is listed as 4.5V to 6V, so if I am to build a project to control this faceplate I might have an easier time with 5V parts like Arduino ATmega328P or PIC16F18345. Using parts like ESP32 would require voltage level shifters.

When I examined the connector labels, I noticed enable (LCD-CE), clock (LCD-CLK), data input (LCD-DI), and data output (LCD_DO) pins. I optimistically hoped it meant this chip communicated via SPI, but the datasheet said it actually used a Sanyo proprietary protocol called CCB (Computer Control Bus). I found no official Sanyo documentation here, either, but fortunately CCB was used in enough products that some electronics hackers had preserved a copy of CCB documentation. Like this page, where the author reverse engineered a different car audio head unit (Kenwood KDC-MP6090R) that used a different Sanyo CCB controller (LC75808) so they could control it from a STM32.

CCB have similar pinout as SPI, but its electrical behavior is different. Each device has a hard-coded address similar to I2C. There is a variation of CCB that merges DI and DO into a single half-duplex line, making it even closer to I2C but not still the same. I’m pretty certain I couldn’t use hardware SPI or I2C peripherals to talk to this chip, but in the CCB specification there’s a line “Using software or serial I/O facilities” which implied the creators explicitly supported doing CCB in software. (bit-banging) Looks like some people have claimed success doing so in Arduino so their precedents might be worth a look when I aim to do the same. But before I do that, I need to learn what normal CCB communication looks like.

Probing Voltage Range of Tape Deck Faceplate Interface

I have on hand electronic circuit boards of the factory stock tape deck unit 86120-08010 from a 1998 Toyota Camry LE. There is a connector between the main board and the faceplate, and I’ve soldered a row of wires so I can take a peek into its inner workings. I thought it might be fun to reuse the faceplate for my own project, creating something that could stand in for the main board.

Thankfully, the faceplate side connector was mostly labeled, including the ground pin which gave me a reference point for measuring all the other wires with a voltmeter. Here’s what I found:

AACC5VSteady 5V
BLCD-DOSteady 5V
GILL0V when mainboard ILL is 0V (lights off)
12V when mainboard ILL is 12V (lights on)
H(CD-BL?)7V when radio is on
8V when radio off.
IVOL.CONVolume knob potentiometer
0V counterclockwise limit
5V clockwise limit
JPULS-AQuadrature encoder for settings knob.
5.1V – 0.1V – 5.1V as knob is turned.
KPULS-BQuadrature encoder for settings knob.
0.1V – 5.1V – 0.1V as knob is turned.
LGND0V reference
MILL-0V when lights off
0.7V when lights on
NBL-0.7V when radio on
7.5V when radio off


  • One connector, which I wired to breadboard column P, has no label. It doesn’t seem to do much, either. Possibly unused?
  • The bottom ~1/3 of two labels were cropped off this silkscreen design. The one I wired to perfboard F might be “CD-EJE”, and H might be “CD-BL”. But it may as well be “CD-BI” or similar letters with the same top 2/3.
  • I was surprised that LCD-DO appears to hold steady at 5V, I expected it to fluctuate during data transfers. [UPDATE: This is expected for Sanyo CCB protocol in absence of event notification.]
  • LCD-DI, LCD-CLK, and LCD-CE fluctuates as expected.
  • There are two knobs on this control panel. They can be both turned and pressed. Turning the volume knob affects VOL.CON, but the press (radio power on/off) seems absent from this connector.
  • Similar story with the settings knob. Turning it affects PULS-A and PULS-B but pressing (select) is absent from the connector.
  • I know there is an LCD controller chip on this faceplate circuit board with additional feature to scan for button presses. Perhaps in addition to faceplate buttons it is responsible for reading presses on volume and settings knob? [UPDATE: Hypothesis confirmed.]
  • If the LCD controller chip lacks ADC (analog-to-digital conversion) and quadrature decoding, that would explain why the connector has VOL.CON, PULS-A, and PULS-B so something on the mainboard can interpret knob motion.
  • Several LEDs scattered throughout the faceplate turn on when ILL is high. Varying ILL between 9V and 12V controls brightness of these LEDs.
  • ILL does not control LCD backlight LEDs, whose brightness remains constant. Might the LCD control chip responsible for the backlight as well?
  • ILL- is a voltage plane that can be 0.7V higher than the GND plane. Have to keep this in mind when wiring up components, in case a 0.7V difference is problematic. Or ILL and ILL- could be wired separately from digital logic aspect of the circuit.

Next step: find more information on the traffic moving on LCD-DI/DO/CLK/CE pins.

Wires to Probe Toyota Audio Head Unit (86120-08010)

Successfully mapping out the segments for a food thermometer LCD had a nice side effect of improving my soldering skills. Armed with this experience, I feel more confident tackling the task of deciphering LCD controller communication protocol. Earlier I had successfully reassembled and powered up the circuit boards from a 1998 Toyota Camry LE stock tape deck. Now I intend to go beyond looking at pretty lights and see if I can control its front panel.

That front panel connects to the main board through this connector, which has labelled most of its contact points. Since I want to probe their behavior in a running system, I wanted to preserve the ability to plug it back into the mainboard. I had the soldering iron all warmed up ready to solder to the visible surface-mount contacts above and below this connector, but then I thought of a better idea.

Its mating connector is soldered to the mainboard, and it is a through-hole connector which meant there are exposed pins on the bottom of the mainboard. These pins are finer pitch than the 0.1″ I usually work with, but through-hole pins are still more familiar to me than surface mount pads. So I soldered my wires to these pins.

These wires are then brought out to another strip of perforated prototype circuit board, and a row of 0.1″ pitch headers.

Which then plug nicely into a breadboard for easy probing and experimentation. Thanks to the labeled connector, I already know which wire is ground so I connected a bare loop for my instruments to use as reference. Next step is to probe the remaining pins to determine their voltage range.

Segmented LCD From Taylor Food Thermometer

After figuring out the segmented LCD module salvaged from an electric blanket controller, I revisited the food thermometer LCD that foiled my first attempt at deciphering its multiplex encoding. This time I have a smaller solder tip to maneuver in limited space. I also have finer wires with softer insulation to reduce stress on these solder joints. And finally, instead of individual pins I will solder all of these wires to a perforated prototype board with pin headers, so that they all share physical stress together. The perforated board also had letters across the top, so I had convenient labels for each of the wires: A through W.

These changes solved the wiring continuity problem, but I hadn’t addressed the problem of applying pressure on the elastomeric “zebra strip” to keep it in contact with copper pads on the circuit board. Or at least, not elegantly.

“Not elegantly” meant there are two different types of tape involved, numerous spacers in various locations, and a small clamp all working together to keep that elastomeric strip in contact with the circuit board. If I am to reuse this LCD, I definitely need a better solution than this jury-rigged setup.

But it was good enough for me to obtain this mapping, scribbling things down as I went. In my earlier effort, I decided this screen didn’t use a typical segment/common pin split. I was wrong! Misled by poor electrical connections. This screen used 18 segments that ended up on my perforated prototype board as A through R. The five common pins ended up on S through W.

Once the segment and common pins were identified, I could wire up my test circuit to activate all segments on this LCD. And from this picture, I can translate my scribbled notes into a more legible segment map.

Some notes on this imperfect segment map:

  • There was crosstalk between pins C and D on my test setup, so they both activate if either is powered. Usually, one is blurrier than the other, but sometimes they look roughly equal and I had to guess which was which. So some of the C/D segments on this map may be reversed. (For example, C3 might actually be D3, and vice versa.)
  • I had intermittent connection on pin N. N0, specifically, was not seen (It was missing from the hand drawn map above) and was filled in, inferred, via a process of elimination.
  • The hundreds digit for the two temperatures can only show 1, 2, or 3. The three horizontal elements are all a single segment, and it is missing the segment to show 4. This makes sense for a food thermometer: while an oven can be set to be 400 degrees or higher, our food would be a charred hulk by the time it reaches that temperature so it’s not really relevant for a food thermometer.
  • The units for temperatures can be “C” or “F” and they only differ by one segment. All the remaining segments are fixed together along with a text label and the degree symbol. (B3 and Q3.)
  • R behaved strangely. It is associated with the “Timer” text in the upper right and the middle horizontal segment of “F” in the lower right. They seem to both illuminate regardless of which common pin is active, but that doesn’t make sense because there’s no reason for “Timer” text to be mutually exclusive with using Celsius units. Additional investigation is needed here but that requires individual segment control that I currently lack.

If I want to play with this LCD further, the first requirement is to get a better mounting system to send signal through that elastomeric strip. No tapes, spacers, or clamps. And in order to have individual control over segments, I’ll need either a dedicated LCD driver chip or a microcontroller with at least 18+5 = 23 GPIO pins. This is far beyond the number of pins available on an ESP32 so I’ll need to get up to speed on some other microcontroller if I want to tackle such a project.

For now, this LCD will not go back to the “I don’t know if I can use it” pile of salvaged electronics. It has been upgraded to the “I know I can use it and I’m waiting for a project idea” collection. I love making such an upgrade, and I want to see if I can do the same for a salvaged automotive tape deck faceplate.

Segmented LCD From Sunbeam PAC-215

I now have imperfect but working control of a 2-digit 7-segment LCD module salvaged from a Sunbeam PAC-215 electric blanket controller. I used an ESP32 for this initial run because I thought I needed voltage control over all ten pins. After a little bit of experimentation, I’ve found that I could probably get away with using 0V and 3.3V directly on each of the segment pins. For the common pins I need an additional option of the midway point 1.65V, but if it is true that an LCD uses very little current, perhaps I could supply that voltage with merely a voltage divider built from resistors? If true, I might be able to control this with something far simpler and less powerful than an ESP32. Perhaps an ATmega328 (Arduino)? Or a PIC16F18345, which has a DAC peripheral and already on hand. (If I’m going to buy a chip, I’ll take Joey Castillo’s suggestion and buy one with LCD control peripheral built in.) These are potential experiments for the future. For now, I want to wrap up work with this particular pair of salvaged LCDs which means leaving good notes for my future self.

I scribbled down this diagram when probing the pins. The pins were numbered before I knew what they did. Now that I know which are segment and which are common, I could label them differently.

I also moved to a zero-based counting system thinking it might be easier to match up to code. Color-coding the different common pins is an idea I picked up from Joey Castillo’s slides, but I wonder if that’s the best way to go. I can’t claim to be an expert on how to use color in a way that’s still accessible to the color blind, and coding common pin information in color risks losing data for scenarios like printing on a black-and-white laser printer.

Moving to letters for segments and numbers for common allows me to put them together as labels on each segment while reducing ambiguity. This is also friendlier to black-and-white printing, but it loses the visual delineation of color coding. Is this better? I don’t know as I see strengths in each. I couldn’t make up my mind on which to keep so I’ll keep both of these diagrams here as references for later.

With this successful milestone of working with LCD modules, I revisited a module that frustrated me earlier.

ESP32 as Driver for Simple Segmented LCD

Once I have some confidence that I can write ESP-IDF code to control voltage levels at a speed relevant for driving a LCD, it was time to move beyond a simple breadboard test circuit. Onward to a perforated prototype board for all ten pins of a simple 2-digit 7-segment LCD, salvaged from an electric blanket controller. In the interest of keeping the wiring simple, I chose ten GPIO pins on one side of this ESP32 dev module I’m using (*) so I could wire everything (almost) parallel.

A 1kΩ resistor connects each ESP32 GPIO pin to an LCD pin, and a 330pF capacitor connects each ESP32 GPIO pin to ground. It isn’t quite a straight shot of ten parallel pins, with a two-wide gap on the left (serial communication TX/RX pins) and a single pin gap on the right (GPIO2, which this dev board connected to a blue LED that I’m using as a system heartbeat indicator.) On the far right is a loop of wire connected to the ground plane, so I have a convenient place for my oscilloscope to clip onto.

That completes the hardware side for my initial test. Moving on to my ESP-IDF project, I started hard-coding a sequence of LEDC PWM duty cycle adjustments that would drive this LCD in a fashion that I believe is called 1/2 duty, 1/2 bias. I think 1/2 duty means switching off between two common segments so each set of segments has 1/2 of the time, and 1/2 bias means the inactive common pin is held at 1/2 of the voltage difference of the active pins. I’m still a beginner so that might be wrong!

I chose to hard code the test because it avoids all the lookup table code I’d have to do if this were to become an interactive changeable display. I have two number digits to work with, so my test pattern is a Hitchhiker’s Guide reference.

The result is clearly legible at the optimal viewing angle, but it fades off quite a bit as the perspective changes. I remember a much wider range of legible viewing angles in its original use, I assume it means I’m doing something different from real LCD driver circuits in this little hack. Possibly related is the observation that, if I illuminate this screen from behind with a LED, its light washes out the LCD.

The original device used two LEDs behind the LCD for backlight, and it didn’t make the digits hard to read, so there’s definitely something missing in my amateur hour LCD controller. But the fact remains it is under ESP32 control, and I learned a lot on my way here. This was the first tangible result of a lot of fumbling around after listening to Joey Castillo’s Remoticon talk on hacking LCDs. Seeing “42” show up on screen is a good milestone to stop and review what I’ve learned.

Source code for this experiment is available on GitHub.

(*) Disclosure: As an Amazon Associate I earn from qualifying purchases.

Switching to ESP-IDF For PWM Waveform Control

I used ESPHome and Home Assistant to quickly experiment with parameters for ESP32 chip’s LEDC peripheral for generating PWM (pulse-width modulated) signals, seeing how they looked under a cheap oscilloscope. But for actually driving a segmented LCD, I will need even better control over signal behavior. It is an issue of timing: I need to toggle between high and low states for each common segment pin to generate an alternating signal, and I have two common segments to cycle through. In order to avoid flickering the LCD, this cycle needs to occur at least several tens of times a second.

The tightest control over timing I could get with ESPHome appears to be the on_loop automation, which is generally triggered roughly every 16 milliseconds. This translates to roughly 62Hz which, if I could complete the entire cycle, would be sufficient. But performing all of those toggles within a single on_loop would be too fast for our eyes to see, so we can only take one step in the cycle per on_loop. In order to toggle both high and low on consecutive on_loop, that cuts me down to 31Hz. Then there are two common segments, which cuts it further to 15Hz. I need something faster.

Until I have other tools in my toolbox, the “something faster” I have on hand require going to Espressif’s ESP-IDF SDK. PlatformIO makes ESP-IDF easier to work with, and I’ve had experience with this arena. My starting point (chosen because I’ve done similar things before) is to write a FreeRTOS task dedicated to toggling voltage levels by changing PWM parameters. In between steps of the cycle, I use a FreeRTOS wait (vTaskDelay) to send this task into the background until the next step. This mechanism allows finer control over timing than the ~16ms of on_loop, though it is only slightly better at 10ms by default. Repeating the math above, that works out to 25Hz which would at least be as good as 24fps film. But that is not the limit. Once I’m working within ESP-IDF, I have the option to get even finer timing control. I can get a little bit faster by reconfiguring FreeRTOS tick rate via ESP-IDF’s menuconfig tool. And for ultimate timing control I can start working with hardware timers.

I whipped up a test program to generate a staircase pattern. From 0% duty cycle, to 50% duty cycle, to 100%, then 50%, and repeat with 0%. Running at 20ms per step in the cycle, the timing looks solid. I can easily move this to 10ms and still have a solid square wave.

The 50% PWM value looked almost good enough without a capacitor. (Left) I have a huge pile of 300pF capacitors on hand, so I tried one and the waveform looked much better. (Right.) This is good enough for me to move forward with wiring this signal into a segmented LCD.

Source code for this experiment is available on GitHub.

Quick ESP32 PWM Experiment via ESPHome

I’ve mapped out the segments of a small LCD salvaged from an electric blanket controller. I activated these segments with an ESP8266 that alternated between 0V and 3.3V on two GPIO pins. Good for individual segments, but not good enough to drive the whole display. There are eight segment pins and two common pins for 8*2=16 total possible combinations (14 of which are used for the two 7-segment digits) controlled from ten total pins.

Technically speaking, an ESP8266 has enough GPIO pins, but we’d start intruding into the realm of sharing pins between multiple tasks which is more complexity than I wanted to tackle for a quick test. When driving a LCD, we also want to control voltage levels on these pins and ESP8266 lacks hardware PWM peripheral. For these reasons I will use an ESP32. It has more than enough pins, and hardware PWM peripherals to support generating a voltage on all those pins. ESP32 LEDC PWM peripheral is very flexible, and I need to determine how I want to configure that peripheral.

I used ESPHome because it is a great platform for quick experiments like this. I don’t strictly need WiFi here, but easy integration to Home Assistant and ability to update code over the network are great conveniences. Before I found ESPHome, I would wire up a few potentiometers to the circuit board and write code to use ADC to read their positions. A bit of code will then allow me to interactively play with parameters and see their results. But now, with ESPHome in my toolbox, I don’t need to solder potentiometers or write code for ADC. I can get such interactivity from the Home Assistant dashboard.

By default, ESPHome configures LEDC PWM peripheral to run at a frequency of 1kHz. According to Espressif documentation, it can be configured to run as high as 40MHz, though at that point it really isn’t a “PWM” signal anymore with only a fixed 50% duty cycle. Slowing down the frequency increases the number of bits available for duty cycle specification, and I wanted to find a tradeoff that I think will work well for this project. Here is an excerpt of ESPHome configuration YAML I used for this test.

  - platform: ledc
    pin: GPIO23
    id: pwm_23
  - platform: template
    id: pwm_freq
    type: float
      lambda: |-
        int newFreq = (int)(10000000.0*state)+1000;
  - platform: monochromatic
    gamma_correct: 1.0
    output: pwm_23
    name: "PWM23"
  - platform: monochromatic
    gamma_correct: 1.0
    output: pwm_freq
    name: "PWM Freq"

This allows me to adjust two variables, each exposed to Home Assistant as a monochromatic dimmable light. Which I can change via a slider on a web page instead of a potentiometer soldered to the board. (The gamma correction value was set to 1.0 because we’re not actually controlling a visible light that requires gamma correction.)

  1. pwm_23 controls the PWM duty cycle.
  2. pwm_freq controls the PWM frequency via ESPHome Template Lambda. Theoretically from 1kHz to 10MHz, though in practice we won’t reach either end as the state never gets all the way down to 0.0 nor all the way up to 1.0.

As I adjusted the frequency, ESPHome automatically calculates the duty cycle bit depth.

[15:32:00][D][ledc.output:041]: Calculating resolution bit-depth for frequency 2491148.000000
[15:32:00][D][ledc.output:046]: Resolution calculated as 5
[15:32:00][D][ledc.output:041]: Calculating resolution bit-depth for frequency 2494322.000000
[15:32:00][D][ledc.output:046]: Resolution calculated as 5
[15:32:00][D][ledc.output:041]: Calculating resolution bit-depth for frequency 2497869.000000
[15:32:00][D][ledc.output:046]: Resolution calculated as 5
[15:32:00][D][ledc.output:041]: Calculating resolution bit-depth for frequency 2501411.000000
[15:32:00][D][ledc.output:046]: Resolution calculated as 4
[15:32:00][D][ledc.output:041]: Calculating resolution bit-depth for frequency 2503623.000000
[15:32:00][D][ledc.output:046]: Resolution calculated as 4
[15:32:00][D][ledc.output:041]: Calculating resolution bit-depth for frequency 2505428.000000
[15:32:00][D][ledc.output:046]: Resolution calculated as 4

From this snippet, we can see that 2.5MHz is the limit for 5 bits of resolution. 25 = 32 levels, which gives me control of resulting voltage in (3.3V / 32) ~= 0.1V increments. I think that’ll be good enough.

Here are some plots in oscilloscope form: First the starting point of 50% duty cycle at default 1kHz frequency, before and after adding a 100nF capacitor into the mix.

Not nearly good enough to output 1.65V. To make this better, I can increase the capacitance or increase frequency. Increasing capacitance will dull system response (and I need pretty quick response to rapidly cycle between LCD common pins) so I start cranking up the frequency.

At hundreds of kilohertz without capacitor, the resulting wave is more than what this little oscilloscope can capture at this timescale. When the 100nF capacitor is added in, we see a pretty respectable 1.65V signal, might even be good enough. But there’s plenty of room left to go faster.

Getting into the megahertz range, there’s enough natural capacitance in the system (wires, breadboard, etc.) that we see a pretty good waveform even without a real capacitor in line with the output. But with just a 330pF capacitor (much smaller than the 100nF I started with) the resulting voltage looks pretty good. At least, at this time scale. Now I need to move beyond ESPHome for better control of 2.5MHz PWM signals.

Electric Blanket LCD

I chose to take apart controllers from my old broken electric blanket because I got frustrated trying to control LCD from a food thermometer and went looking for something simpler. I was optimistic that an electric blanket controller, with just two 8-segment digits, would be just the ticket.

I was so eager I performed a quick LCD test before I even completed the teardown. I got a single segment to show up, which was a promising start. I was also happy to see this LCD connected to its circuit board with nice long metal pins that I could unsolder, not the elastomeric “zebra strip” used by the food thermometer. These pins are even spaced in a breadboard-friendly 0.1″ pitch, win!

I recently got the Engineer solder sucker from Adafruit, upon Helen Leigh’s recommendation and it made this de-soldering task much easier than with my previous lowest-bidder solder sucker. I now recommend the Engineer unit too, it is well worth the price premium.

I tried to put this module directly into a breadboard, but the pins are too fragile. (They would bend instead of pushing into the breadboard.) Thanks to the 0.1″ spacing, it was very easy to solder robust headers onto those pins.

The headers gave me a solid reliable connection to those pins, making it easy to map out all the segments. Far easier than the food thermometer LCD and its elastomeric strip. Now I need to figure out how to generate the voltage levels necessary to drive this LCD.

Electric Blanket Control (Sunbeam PAC-215)

Electric blankets are an energy-efficiency way to stay warm during cold nights. If I’m going to stay in bed while sleeping, why heat the whole house? Heat just the bed and get a comfortable rest. But they don’t last forever, and this particular Queen-sized blanket stopped heating for unknown reasons. I’m going to take apart its two control units (one for each half of the bed) to see what’s inside.

According to the label, this is a Sunbeam PAC-215 STYLE 85KQP with a maximum power draw of 360 watts. I interpret PAC-215 to mean the functional designation and 85KQP to mean a specific cosmetic variation, but that’s just a guess. (And it doesn’t affect a teardown, anyway.)

Peeling back all the adhesive circles unveiled two Philips-head fasteners.

Once those two fasteners were removed, there were three plastic clips to undo before the bottom could be separated from the enclosure. We see many thick traces and wires of through-hole components. Four small Philips-head fasteners hold the circuit board in place, the larger fifth fastener is for the heat sink and can be left in place.

In addition to those four fasteners, the LCD is held by two plastic clips and blobs of hot glue.

Once removed, we could separate the circuit board from the enclosure. Curiously, I see a sheet of metal glued to enclosure top conducting from one of the four screws out to the front of the display area. It might be for grounding purposes, but there is no other metal for it to make contact. It’s not obvious to me what user scenario justified this effort.

I was amused to see that backlight for the LCD is just a pair of LEDs soldered to the board. Simple, straightforward, and functional. No fancy multi-layer light diffusers for this screen.

The circuit board has a white silkscreen marking of PEP003-0A.pcb on the left and a copper marking of FR4(94V-0) DD2 REVB on the right. This picture was rotated 180 degrees relative to earlier pictures to better read identifier on the large surface-mounted IC.


I can make out the ST logo but a search for “DD2ZW2” and “MP9ACO218E” on their site both came up empty. Based on the traces going directly to the LCD, this chip has LCD control capabilities. How much more? I don’t know. It might be a complete electric blanket controller solution for all I know. The other item with a ST logo is a BTB06 triac.

I then proceeded to disassemble the other controller, whose enclosure came apart the same way. I had expected to find two different circuit boards: a primary controller with majority of logic and a secondary unit purely for user interface purposes. I was wrong: the two circuit boards are identical. They only differ in how wires were soldered to each board. I followed their paths and drew a crude diagram.

The power plug enters the first unit and connected to points labeled “H” (Hot) and “N” (Neutral). These are forwarded to the second unit as H2 and BN, respectively. H2 enters the second unit at its own “H” and BN goes to the second unit’s “N”.

Outputs of the first unit are labeled BH and BS, which enters the second unit as BH3 and BS2, respectively, and forwarded on to exit points BH2 and BS. The second unit’s own output goes out as BH, and neutral is forwarded out to the blanket plug.

The blanket plug itself was interesting. It was made of injection-molded plastic and designed to allow loose tolerances due to the flexible nature of the plastic yet still offer lots of mechanical strain relief.

The story continues inside, with plenty of strain relief considerations. This should nearly eliminate any mechanical stress from acting on the four crimped electrical connectors.

This teardown was more interesting than I had expected, as the controllers were more sophisticated than I had given them credit for. That was fun in its own right. But the motivation for doing this teardown today (instead of later) was so I could get my hands on some simple bare LCD modules I could play with.

Taylor Food Thermometer LCD First Round Fail

When I salvaged LCD for play later, I didn’t know enough about them to make sure I salvaged them with known controllers in working condition. Fortunately, by sheer luck I managed to do that with a car audio head unit. But this adventure started with a talk on direct control of simple LCDs and I wanted to get back to that initial motivation. My most recent LCD salvage was from a Taylor food thermometer, but it didn’t look easy to work with. Due to the fact its electrical contact is in the form of elastomeric “zebra strip” and I didn’t want to build my own circuit board to make contact with it.

I saved the original circuit board thinking that I could use it as reference when I get around to making my own board. These are just flat rectangles of copper, each one millimeter wide and spaced one millimeter apart. Thanks to Joey Castillo’s Remoticon talk, I learned that bare LCD require very little current so I think the surface area of these contact patches are generous. Perhaps I could get away with using only part of it?

I started soldering wires to these pads, trying to keep my soldered area to less than 25% of the surface area leaving remainder clear for the elastomeric strip.

I then severed all of the original traces to make sure my experimental signals won’t route through the original chip.

I started probing with alternating signals from an ESP8266 at 3.3V. This is what I see when I put them on the left-most and right-most wires: five segments darken, but one more clearly than the rest. “But wait, I see more than five segments” explanation: the three horizontal lines on that 3 are actually all a single segment, apparently this digit only needs to show a subset of numbers. For example, 2, 3, 5, 6, 8, and 9 can be shown with all three horizontal lines active, and 1 can be shown with all three inactive. There are four other dark segments but they are blurry. A horizontal segment in the upper left, two of the vertical segments on that digit, and a fixed text “Alert”.

Further probing found that the left-most five lines and the right-most five lines multiplex against each other, together letting me control 25 segments. Whenever I light one up, four others are blurry. After some experimentation I understand this is due to my voltage too high. Adding a voltage dividing resistor ladder (1 kilo-ohm and 470 ohm) brought it down to 2-ish Volts. Once at that level, individual segments activate cleanly without crosstalk activation of their multiplexing neighbors.

When I tried to get a picture of a single cleanly activated segment, I failed because a wire popped loose. Since this experiment required that I solder these wires to tiny fraction of the pad, these were very bad solder joints with small contact area. They began to fail one by one. Some would pop off cleanly so I knew it failed, others would seem to be physically connected but electrically discontinuous.

I got far enough to determine the multiplex scheme is different from the “common”/”segment” split mentioned in the Remoticon talk and common in multiple other LCD controllers. [Update: I was wrong. See link to update at the bottom of this post.] Figuring out the novel multiplex scheme might be interesting, but not while fighting bad electrical connections at the same time. After a few rounds of “multiplex or bad connection?” guessing game, I got frustrated and decided to postpone this puzzle until I can create better contact with the elastomeric zebra strip. I went looking elsewhere for a simple LCD.

UPDATE: I took another swing at this task and was successful on the second try.

Powering Up Toyota Audio Head Unit (86120-08010)

It appears two of my salvaged LCDs might have come from the same product, with identical (or nearly so) interface and command protocol. That is great, but I don’t know what that protocol actually is. It isn’t terribly promising as a starting point, so I decided to continue looking in my pile of salvaged electronics. Next candidate is the LCD embedded in the control panel of an automotive audio head unit. This was a stock tape deck from a 1998 Toyota Camry LE, which was replaced by an aftermarket deck for modern conveniences like Bluetooth audio. It was one of the retired pieces of equipment I brought to the January 2020 session of Disassembly Academy and taken apart. All metal pieces went into recycle, all plastic pieces went to landfill, and I kept the electronic circuit boards.

Since the metal external panels are gone, I no longer have the model number. Searching through eBay listings, I guess it was a Toyota 86210-08010. This listing explicitly mentioned Toyota Camry in their description. However, I saw several other Toyota units that looked superficially similar but with different numbers, like this 86120-04090. I thought maybe I’ll just call it “86210” but there are “86210” units that look wildly different like this 86120-2B761. Clearly there are complexities in Toyota parts numbering that I don’t understand, but for now I’ll go with 86210-08010.

The reason this particular LCD is interesting is because it is part of a still-intact control board. I’m optimistic that I could figure out enough of the control board to make it do my own bidding.

The backside of the board has a large identifier: 121941-4890D700. That didn’t turn up anything, but there are two other features on the back that make me optimistic.

The first is a clearly identified chip: Sanyo LC75853N and a search found its datasheet. It is a LCD controller with additional capability to scan for button presses, which makes sense for use in a control panel like this one. Furthermore, the datasheet should describe the control protocol.

Even better, the board has a connector to the rest of the radio, and it looks like all the pins are labeled. Some of them were cropped at the bottom and even if they weren’t cropped, I don’t necessarily understand what they all mean. But GND and ACC5V are clearly legible, which is a great start. What more can I ask for? Well, I can ask for it to be powered up and running so I can probe those pins in action.

When I replaced this head unit, I recall going online to purchase an adapter wiring harness and a pinout guide to know which wire went where. Many Toyota head units shared the same connector and pinout, so this diagram for a slightly different model was close enough.

I could buy another wiring harness, possibly this unit, but decided against spending more money. This is for experimentation and I could easily solder directly to the circuit board.

It probably didn’t matter very much in this case, but I also thought I’d follow wire color convention for automotive audio. I connected the “battery” (yellow) and “accessory” (red) wires up to +12V on my bench power supply, and black wires to ground.

The screen comes alive! Very nice. From here, I started disconnecting power wires and found that for purposes of powering up the control panel I only really needed half the wires, the three on the central connector. (Visible in the back of this image.) With a screen that is alive and kicking, and a datasheet that should explain everything, I expect a high probability of success for learning how to master this control board. This could be an interesting project, and the only problem is that it veers very far from Joey Castillo’s Remoticon talk which motivated me to look at LCDs. I set aside this project for later and started looking for simpler LCDs in my pile.

[UPDATE: I have returned to this device and made great progress on the second try.]

Risky Parallel LCD Test Surprisingly Worked

I briefly surveyed LCD controllers popular with hobbyist projects, hoping to find something that might match my mystery salvaged LCD units on hand. No luck. If my intention is to build a project with LCD screen, I should go and buy one of those popular units. But the point of the exercise is to try reusing salvaged electronics, so I stared at my two LCD units some more while thinking of Emily’s observation that they both had nine interface pins and the hypothesis they share a common command set.

I know for sure they aren’t identical. For starters, the two modules are different sizes. And while they both have nine interface connection; they are physically different. The bare LCD module has pins, and the headset LCD module is soldered to its circuit board with a segment of FPC (flexible printed circuit). Holding the bare LCD’s pins up to those soldered joints, I had an idea: what if I wired both LCDs together in parallel by soldering the bare LCD pins to the existing FPC pads?

The first thought was to dismiss it as a stupid idea. There were too many reasons why it wouldn’t work even if the devices have a common interface. If they were SPI devices, they would conflict on the MISO pin. If they were I2C devices, the two devices probably have different addresses, and the bare LCD wouldn’t do anything. Or if they had the same address, there would be conflict as they both tried to ground I2C control lines at the same time. LCD controllers like the PCD8544 had internal LCD voltage generators. Wiring two boost converters in parallel risks creating a feedback cycle that overshoots limits and destroy components. And if their wiring were completely different, I risk short-circuiting VCC to ground, or possibly connecting one of the boosted higher voltage lines to something that could not tolerate such voltage. And I’m sure there are other risks that didn’t come immediately to mind.

But despite all those risks, the thought refused to go away. After a day of “but what if?” ringing around in my head, I decided these were salvaged components that I would eventually discard if I couldn’t figure them out. (Or even if I could, if I’m being honest.) Basically, I didn’t have anything to lose by throwing the dice and trying parallel wiring.

I powered on the handset LCD and, after a few seconds, the screen came up. It was quite faded compared to earlier, so something in this circuit is unhappy with the parallel screens. But at least I didn’t kill it outright.

With a mental drum roll, I tilted my head to look at the other screen and… wow! I see something!

Both screens are very faded compared to what I’ve seen them earlier, but they are both nominally working while wired in parallel which is amazing! Seeing same text on both indicates the alphanumeric portions are common. The segmented portions below “CONNECTING…” are, however, different between the two displays.

The faded contrast tells me something is overstressed, so I quickly powered down after taking these pictures and de-soldered the second LCD. Powering the board back up restored normal contrast on handset LCD implying there was no permanent damage.

While there doesn’t seem to exist a popular common protocol for nine pin LCDs, at least these two are in common with each other. From a historical perspective, their commonality implies the bare LCD was salvaged from the base station for the wireless handset. From a reverse engineering perspective, having two devices with a common protocol meant I could leave the handset LCD intact for probing. I could then test my guesses with the bare LCD connected to another microcontroller. From a reuse perspective, it means if I’m successful figuring these guys out, that work could be utilized on two displays and not just a one-off. I could work on this project, but instead I decided to dig up another LCD that should be easier to decipher.

Hobbyist-Friendly LCD Controllers

When I dug up my collection of salvaged LCDs, I had expected to find bare arrays that I could power directly. But the first two units I probed turned out to have a controller embedded in the display. The good news is that I wouldn’t have to worry about complex multiplexing AC signals, the bad news is that the problem shifts to deciphering a digital communication protocol. With this switch, I decided it would be wise to pause and take a look at existing information on LCD controllers.

I’m excluding controllers dealing with large LCD arrays like those on computer and television screens, or even modern high resolution touchscreen phones, as they have signal requirements that exceed my current electronics skill. I’m starting at the lower end of the spectrum where they are accessible to the electronics hobbyist. The field appears to be dominated by two classics: the PD8544 and the HD44780. Both of these designations refer to specific products, but due to their popularity, they have become de facto generic names covering the many clones and compatible controllers that also exist.

Anyone who remembers Nokia’s classic snake game has spent time staring at a PCD8544-controlled LCD. Sometimes called the Nokia 5110 LCD, after the phone that introduced faceplate customization. PCD8544 was the brains literally behind the dot matrix screen on classic Nokia phones. Once the market moved to large touchscreens, a lot of Nokia phones were retired, making these screens easily and cheaply available for hobbyists. The bad news is that old Nokia bricks are no longer found in a drawer in every house, it’s been too long. The good news is that the display can still be purchased in a hobbyist-friendly breakout board format.(*) There exists multiple Arduino libraries for drawing to such a screen. Reading Adafruit documentation, I see there are eight pins in the interface instead of nine on the screens I have. I had hoped maybe my screen is closely related to a PCD8544 with an extra pin for some additional feature, but if so, pin orderings have been switched around as the VCC and GND pins are further apart. Fortunately the PCD8544 datasheet is widely available (here’s a mirror hosted by Adafruit) so it gives me an idea of what data stream for a SPI-controlled LCD looks like.

The other LCD controller targeted by several different Arduino libraries is the HD44780, an LCD dot matrix display tailored for showing alphanumeric characters. Making it very popular for devices that need to show a few words to the user, anything from household appliances to industrial machinery. It’s not technically a graphics display, but it can be hacked to show graphics via “custom fonts”. This ability to range from easy text output to complex graphics hacks make them a good choice for hobbyist projects, as they are sold in project-friendly format and easily affordable (*). Another (admitted flawed) metric of popularity is that somebody saw fit to write a Wikipedia page for HD44780, an honor granted to few other LCD controllers.

Could my salvaged display be a HD44780 compatible unit? First glance says no: the typical wiring requires 16 pins. A closer look gave me a bit of hope, as two of those pins may be absent for units without built-in backlight, bringing it down to 14 pins. There’s also a 4-bit operation mode, dropping it down to 10 pins. Removing just one more pine would bring it down to 9, but even then, it requires four data lines and my display uses two. For this reason I don’t expect much resemblance between my salvaged LCD controller and a HD44780. There are many other Arduino libraries for different LCD modules, but I didn’t know how to further narrow down the possibilities. Aside from laboriously searching through every pinout diagram in documentation, which I’m not inclined to do right now.

Looking at my other favorite prototyping ecosystem, ESPHome also has support for the Nokia-popularized PCD8544, though not the HD44780. Other units supported under their Display Components umbrella are mostly I2C and SPI devices plus a few UART controlled units sprinkled in between. They all use fewer than nine pins. However, they did remind me of the SPI protocol which makes me think my salvaged LCD may be a SPI unit. The two data lines may be MISO and MOSI pins. (The PCD8544 appears to be a SPI device without MOSI.)

A web search for “nine pin LCD” found this electronics StackExchange question titled Do 9 pin LCD modules have a standard interface? Sadly, the answer appears to be “No”. The specific example in this thread was identified as a UC164904, which is a SPI device plus extra pins like two for LED backlight control. As my particular unit had an external backlight, it is definitely not a UC164904.

If information on my LCD unit is to be found online, I will need to be more specific than “it has nine pins”. But if they both have nine pins, perhaps they’re controlled the same way? I tried the easiest (and pretty risky) test that came to my mind and was surprised when it worked.