Tuesday, February 26, 2019

Building A Temperature Based Fan Controller

Cooling is important. I know this, because in the file vault I built myself there is hardly any airflow with 8 hard drives in close proximity to each other. This causes the hard drives to approach their safe temperature limit. In an enclosed space, they exceed it and shut down. This isn't good, as it wears the hard drives more than regular usage. So we need to add a fan to them. I want to build my own temperature based fan controller because I'll need one for another project I'm working on. The payoff on that one will be pretty cool, too. So stick around.

The design is fairly straight forward. I have to find a high pressure fan that will fit in the limited space I have by the hard drives that isn't too loud and is driven by PWM. Then I'll use an ATTiny chip to read a temperature sensor and send the PWM signal to the fan. Easy, right? Gosh I hope so.

We know that this whole circuit will be powered by 12V because that's what the fans require to run. The ATTiny requires about 5V, so I'll need a voltage regulator. And then the fan pinouts that I've read say that the speed is controlled by a 3.3V PWM signal.


But it turns out this isn't quite true. The Speed Control pin actually has ~6V on it. However, if I drain it to ground, then I get full fan speed. So perhaps we can use PWM on a transistor that drains to ground. It's a bit of a bastardization of what a transistor is supposed to do, but it works. I uploaded the Arduino Fading example code and changed the pin to a PWM pin on the ATTiny and got pulsing fan speeds. Interesting to note, I had to smooth the supply voltage quite a bit to keep the Arduino from restarting if I plugged a fan in or unplugged it. I assume that this should be a permanent fixture in the circuit in case of large changes in fan speed that causes transient brownouts of the chip (or voltage spikes). Perhaps a single larger capacitor would be better.


This is the mess of a circuit after I tried to work in the temperature sensor. I'm using a TC74 which communicates the temperature over an I2C bus. The ATTiny doesn't support this natively, but through software anything is possible.

I initially tested the sensor using a big-boy Arduino Uno with I2C hardware. It worked perfectly the first time. However, when I tried to use it with the ATTiny and the TinyWireM library, it wouldn't do anything. So I tried another core - this core, to be exact - which says to have abstracted away the software I2C implementation into the include for `Wire.h` as required by the TC74 library.  This didn't work either. I was confused to say the least.

It's very hard to debug an ATTiny chip. Very hard. My only output was the LED I had plugged into the breadboard. It was supposed to flash when it read something other than 128 or 0 from the temperature sensor (room temperature is about 22). It just... wasn't. So I hooked up my logic analyzer to try to see what was going on with the I2C bus. And then it started working - the temperature data made it and it was writing the correct PWM value to the output pin. As soon as I removed the probes, it stopped working. This happened even if I touched the SDA line.


So I tried rebuilding the circuit with shorter wires to discourage high resistance or capacitance. I also switched the transistor out for a full-blown MOSFET and I got myself a proper 5V regulator (both of which not pictured here since I was only debugging the logic part). And it still didn't work. I decided to dive deeper into what was causing the issue. Again, I hooked up my logic analyzer and saw what it was doing:


This was all well and good. But when I unplugged SDA from the analyzer, it appeared that the clock signal was no longer being pulled up.


This was some of the strangest behavior I've seen. I know you can do I2C on a breadboard so long as the signal speed isn't too fast. The ATTiny's USI I2C implementation runs at about 111.11kHz (and you can't seem to change it). So I think we're good there.

I'll spare the debugging details. It took me way to long to figure out. Basically, I noticed a trend that the communication would become more stable as the value of the pull-up resistors increased. I honestly don't know why, but I ended up using 22K pull up resistors. My best guess (and I'm already stretching enough just to understand this at this point) is that I wasn't achieving the required minimum sink current (3mA) and that was breaking something. Page 55 of NXP's I2C Bus Spec has nice graphs to check, but as far as I can tell, it's not really in agreement with my hypothesis. If you have any thoughts, let me know.

But now that that's working, we can write the code. I was going to use a pretty fan curve with an exponential ramp up to full temperature to keep the fans quiet until they needed to be loud, but I decided to use a linear function instead. Here is the code. Very short, sweet, and to the point. All of the complex stuff is happening behind the scenes making the USI Hardware do I2C stuff.

Then I moved it to some perf board. I was never too great at organizing things on perf board, but before adding the 12V line for the fans, this is what it looked like:


The long wires may affect the I2C bus communication, but if communication fails, the ATTiny will put the fans on full blast just in case. It's a good fail condition, I think.

So now I get to put it in the system this was designed for. What system is that? I'll leave a hint here: it's a computer that relies on something else to move air through it, otherwise it overheats within minutes. So hopefully this will work as well as I think it will in my head. Otherwise, it'll shut down due to overheating way too often and I don't want to damage the mystery system. Until then, I'll probably make another one of these and put it in my file vault to keep the hard drives cool. I have too many of these fans and I need to use them.

No comments:

Post a Comment