commit 882f751219082793c9a1ea8405f6246c0f91e880 Author: Barb Date: Fri Jun 16 16:08:06 2023 +0200 first commit, functinal attiny code diff --git a/25KHz_PWM_Tiny.ino b/25KHz_PWM_Tiny.ino new file mode 100644 index 0000000..1243fce --- /dev/null +++ b/25KHz_PWM_Tiny.ino @@ -0,0 +1,77 @@ +// normal delay() won't work anymore because we are changing Timer1 behavior +// Adds delay_ms and delay_us functions +#include + +// 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 +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..a3da7f1 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +DIY fan controller for ThinkPads (should be adaptable to other laptops/desktops). + +Introduction/Rationale: +Newer ThinkPads are dumb, their fan controllers use an obscure method of communication with the kernel, that does not give direct access to PWM frequency. The fan(s) is(are) either off, or on in one of 2 or 3 levels, making for very jarring transitions that are clearly audible. + +This project aims to replace the built-in PWM controller with an attiny or other arduino compatible board containing a custom fan curve. The controller reads a temperature value from a thermocouple and sets the fan accordingly, proportionally to the given temperature. + +Future goals: +- add serial/usb communication +- add buttons/switch to choose between fan curves +- add software control mode (with fallback to default built-in curve when serial is down) \ No newline at end of file