DIY fan controller for ThinkPads (should be adaptable to other laptops/desktops).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

77 lines
2.2 KiB

// normal delay() won't work anymore because we are changing Timer1 behavior
// Adds delay_ms and delay_us functions
#include <util/delay.h>
// Clock at 8MHz
#define F_CPU 8000000 // This is used by delay.h library
word VentPin = 1;
word DetPin = A0;
float PWM = 50; // takes values from 0 to 100
float PWM9, PWM8, PWM7, PWM6, PWM5, PWM4, PWM3, PWM2, PWM1;
// Thermistor
int Vo;
int DeltaT = 10; // shift curve up/down
float R1 = 13000;
float logR2, R2, T;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
// Boot up delay countdown to keep the fan spinning initially
int countdown = 10000; //Microseconds to delay
void setup() {
//Serial.begin(115200);
TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(WGM02) | _BV(CS01);
// Set TOP and initialize duty cycle to zero(0)
OCR0A = 40; // TOP - DO NOT CHANGE, SETS PWM PULSE RATE
OCR0B = 30; // duty cycle for Pin 1(PB1) - generates 1 500nS pulse even when 0
pinMode(VentPin, OUTPUT);
pinMode(DetPin, INPUT);
}
void loop() {
// Thermistor data acquisition
Vo = analogRead(DetPin);
R2 = R1 * (1023.0 / (float)Vo - 1.00);
logR2 = log(R2);
T = (1.00 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
T = T - 273.15;
// End of temperature measurement
// PWM control Logic
if (T < 30) {
// this next if is necessary to trick BIOS into thinking it xontrols the fan at boot
if (countdown > 0) {
countdown--;
delayMicroseconds(100);
PWM = 50;
}
else if (T < 15 && countdown <= 0) {
PWM = 0; // stop the fan if the machine is critically cold
}
else {
PWM = 25; // minimum fan speed while operating normally
}
}
else if (T >= 30+DeltaT && T < 40+DeltaT) {
PWM = 2*T - (35+2*DeltaT); // first part of the fan curve
}
else if (T >= 40+DeltaT) {
PWM = 5*T - (155+5*DeltaT); // second, steepest, part of the curve
}
// these variables are used to average the value over 10 cycles before sending it to the fan
PWM9 = PWM8,
PWM8 = PWM7;
PWM7 = PWM6;
PWM6 = PWM5;
PWM5 = PWM4;
PWM4 = PWM3;
PWM3 = PWM2;
PWM2 = PWM1;
PWM1 = PWM;
OCR0B = (PWM9+PWM8+PWM7+PWM6+PWM5+PWM4+PWM3+PWM2+PWM1+PWM)/30; // average and send value to timer
}