February 13, 2017

Reverse engineering the Coolstat Evap Cooler controller

I bought one of these back in 2015. It replaced the control module in my Master-Cool brand evaporative cooler. From the start I was unhappy about one thing. Namely when the temperature got near the target, it would turn the blower motor on and off every few seconds. I was certain this was going to burn out the blower motor, and sure enough after less than a year in service it did.

Everyone I describe this to says exactly what I said, "What! No hysteresis?". Nope, aparently not -- but we intend to fix this by adding a dead band rule. In other words when the motor turns on, it stays on for at least N seconds. And when it turns off, if stays off for at least M seconds. Most likely N = M = 60 seconds.

So now my goal is to augment (or replace) the control module with something with a more intelligent algorithm. The first trick is to learn enough about this thing to figure out how to modify it.

Hardware basics

There are two units, connected by a 3 wire cable. The in house control panel (shown above) has a monochrome LCD screen and 6 buttons. The "in cooler" module has buttons and relays, which will be described later -- or basically ignored in this discussion.

A quick look at the control panel shows that the 3 wires are labelled Tx, G, and B. A meter on these shows 3.38 volts on both the Tx and B. So G and B are ground and power respectively. And as I hoped, all the smarts must be in the control panel since it can only send commands (so it must run open loop as far as motor and pump status). If we can determine the protocol on the Tx line, we can replace it with almost anything we like.

Inside the control panel is a PCB that consists essentially of one component, a Holtek HT46R64 chip. This is some kind of oddball 8 bit RISC controller in an OTP version, and in a 52 pin QFP package.

So far I have no idea what it uses for a temperature sensor or where it is. It may be the glass encapsulated thing at the bottom of the PCB. Given that this is an unusual controller with OTP EPROM, there is no way to modify (or even read out) the firmware.


It was fairly quick work to connect this to a 3.3 volt supply (I already had one set up for another project) and put a scope on the Tx line. The control unit is "talking" at 4 Hz (every 250 ms) as you can see on the first of these scope captures.

I guessed that the slave unit ( the power controller ) would turn everything off if it did not get a message regularly, but this is unfortunately not the case. I remove the control panel and the fan keeps running indefinitely. It just goes to show, never assume the engineers had a clue.

The message being sent is simple enough. It is a uniquely encoded serial byte sent at 1000 baud, i.e. each bit time is 1 ms as shown in this second scope capture:

We have a "start" sequence where the line is held high for two bit times (2 ms), followed by 8 data bits. Each of the data bits is 1 ms long, and like any good bit, comes in two flavors.

For each bit, the line is always first low, then high. In one state the line is low for 300 us, then high for 700. In the other state the line is low for 700 us, then high for 300. I call these states L and S respectively (for "long" and "short" refering to the high state time).

Messages look like SLSLxxxx, where "xxxx" are the bits of interest. The "SLSL" is a constant "prolog" that never changes. There is a 4 bit payload in each message. In the message shown above, the payload is "LLLL"

We can label the payload fgpx, and the 4 bits control:

The "L" state indicates the feature is off, the "S" state indicates the feature is on. So the "LLLL" state shown above has everything off.

Note that we should never turn on both f and g (I don't know if the slave unit will guard against this or not, but I don't want to find out). Activating both relays to power both the fast and slow windings on the blower motor is almost certain to cause damage.

All the above was sorted out by using the buttons on the control module to put it in every possible state and making a chart of the different commands being sent.

The plan -- what microcontroller?

Almost any controller could be used to cope with this protocol. It would be nice if it ran off of 3.3 volts of course. I decided to use an ESP8266 on an ESP-12 module. What will surprise most people is that I have no intention of using the Wifi capability of the chip. At least in part this is to prove the point that these make swell little microcontrollers.

As an aside, I find it hilarious to compare the ESP8266 to the Holtek (and consider that the Holtek is still doing the bulk of the work). We have an 80 Mhz 32 bit RISC processor on one hand and an 8 Mhz 8 bit processor on the other. The ESP8266 has 64K plus 96K of ram, the Holtek has 192 bytes, and so forth.

There are some other good reasons to use the ESP-12. It is tiny. I measure 0.65 by 0.95 by 0.135 thick. It is also dirt cheap (about $2) and I have several just laying around. This will fit nicely inside the control panel box (It has 0.2 inches of clearance). I can just epoxy it (or use double stick tape) to a handy empty area on the PCB, bug wire it, and cut one trace to patch it in.

One consideration is driving the 100+ feet of cable to the slave unit. I don't want to do this directly from an output pin on the ESP8266. The existing board has a transistor to drive the cable as a buffer and I would be wise to cut the trace that drives this transister and retain it as a signal buffer and line driver.

The above image shows where I intend to mount the ESP-12. The trace I intend to cut is the one from the Holek chip to "R3". It is important to note that this signal is inverted from the one shown in the scope capture above (the buffer transistor Q0 inverts the signal, which is to be expected actually).

Finishing it up

I hot glued the ESP-12 in place and then did a bunch of careful point to point wiring and soldering. I allowed for the signal inversion in the code, but still had to sort a couple of things out. I added a header with 5 pins. Two are to install a shorting jumper to ground GPIO-0 to be able to run the boot loader convenients. The other three are Tx, Rx, and Ground for a Uart. Also a bare ESP-12 needs to have a couple of other signals taken care of. One is to pull CH_PD up. I used a 5K resistor, but was certainly tempted just to pull it to Vcc directly. Also GPIO-15 needs to be grounded. I did nothing at all with GPIO-2. This pin drives the on-board LED, but also is checked on bootup. The LED serves as sort of a pullup -- at any event it works fine with GPIO-2 just left alone.
Have any comments? Questions? Drop me a line!

Tom's Auto repair pages / tom@mmto.org