15 December, 2016

Improving cooling a powerful notebook graphics with a transistor and Arduino

Laptops that come with powerful graphics have an usually badly designed thermal control; This is the case of my dear Acer 5930G (already I spoke above ) wearing a removable Geforce graphics card.
Engineers Acer believed it was enough to regulate the fan with the processor temperature, since the sink joins both, but the graphics consume more, which can reach 70 easily while the CPU is 40 and the fan medium gas.
We'll see how we regulate the fan directly 5V , depending on the temperature of the area that interests us, with the advantage of being able to use any fan that can be coupled to our team, plus you can customize the level of cooling in the Arduino code. 

The result : I got him down more than 20 to the graph regarding the regulation of factory, from 70 to about 45 ° C at rest. And in 90 games at maximum 70 ° C. You hear more, because almost constantly is 100% , but if that win in durability, I welcome the resulting hiss. Another advantage is that by taking the power from the USB port, turn it off when no temperature peaks but still cooling off while connected to the grid, until it cools completely and stops. 

Materials Needed:
- Chip ATtiny85 
- Transistor NPN 50V typical and 5Vgs ( 2N4401 I used myself). 
- Capacitor 220uF 6V and min. 
- Diode 5V and minimum hold 200mAh. 
- Tubing.





As we saw recently, we can regulate fans (and we want) with a small chip , ideal for small projects where few inputs / outputs, the ATtiny85 are required. 
In this case, reusing the code, instead of sending a signal to the chip PWM fan, will regulate directly the 5V voltage it receives, so that the minimum start on 1V. 
But we can not do directly with the Attiny, but we have to use a small NPN transistor , with a small positive signal at its base, acting regulator current flow between the collector and emitter.

Note: It is called NPN because we regulate a negative signal (N negative), and the base will deliver a positive signal for it.
This is the code, also on Github :

 /*  ==================================================================

  Sketch control ventilador por PWM con ATTiny85 económico termistor NTC.
  Configurado para ventilador genérico; con autolimpieza al arranque.
  
    Autor: David Losada, basado en trabajos de Rafael Torrales y Antonio Moles.
  Version: 1.0
  Fecha: Octubre 2016. Última actualización 13/10/2016
  Compilado con Arduino 1.6.9

    ==================================================================   */

#include  //Instalar esta rutina si no la tenéis; está en el repositorio general de Arduino 1.6.9
//Si anduviéramos cortos de memoria, habría que eliminar la librería EEPROM y el código relacionado

//******************* A CAMBIAR SEGÚN TU CONFIGURACIÓN ********************************
//Control temperatura
const float resistor = 6800; //El valor en ohmnios de la resistencia del termistor a 25ºC
const float voltage = 5.0; // El voltaje real en el punto 5Vcc de tu placa Arduino

//Deltas de temperatura
int tempMin = 30; //Temperatura mínima de activación del ventilador
int tempMax = 50; //temperatura a la que funcionará al 100%
//0,85V=velocidad mínima de vent. PS3 y 1,25V vel. máxima
double PWMMin = 0.8; //Voltaje PWM de funcionamiento con temp. mínima (el de la PS3 se pone en marcha con 0,8V)
double PWMMax = 5; //Voltaje PWM de funcionamiento al máximo ventilador
//Hay que tener en cuenta que los voltajes se ajustan a las temperaturas pero no se ciñen a ellas,
//es decir, que a tempMin el voltaje será PWMMin, pero a menor temp. el voltaje bajará, y lo mismo
//con el voltaje máximo; si sigue subiendo la temperatura, el voltaje PWM aumentará en consecuencia,
//hay que tener cuidado porque podríamos dar más voltaje del necesario al ventilador

//Definición pines digitales para activar relés
int TempPIN=1; //En el ATTiny85 las entradas son (1)=P2; (2)=P4; (3)=P3; (0)=P5 -> Pin al que conectamos el termistor
int placaPIN=0; //
//(Entre el GND y ése pin soldaremos una resistencia del mismo valor del termistor)
int motorPWM=4; //Pin PWM de control motor; P0, P1, P4 el en ATTiny85
const int frecseg = 1; //Tiempo en segundos entre cada ejecución del programa (recomendado entre 1 y 5 segundos)
int ledPIN=1; //Según la placa, en este caso el LED del ATTiny85 B es el 1

//********************************************************************************
//Variables
float Temp= 0; //Valor entrada sensor temp
int fanSpeed= 0; //Velocidad de motor
long timeLED=0; //Para almacenar tiempo
unsigned long millisInicio=0; //Para comprobar paso de horas

//Parte del cálculo temperatura
//Para ahorrar cálculos lo definimos como constante en esta parte del programa
const float K= 273.15; //Para pasar a grados Kelvin
const float e = 2.718281828459045; //Constante matemática 
//const float B = log(RPto2/RPto1)/(1/(TPto2+K)-(1/(TPto1+K))); //Valor Beta de tu termistor calculado de dos puntos
const float B = 3850; //Valor Beta del Datasheet; comentar esta línea si se meten los datos de los dos puntos
const float unodivr = 1/(resistor * pow(e,(-B/298.15))); //Con pow elevamos e al resultado

float T = 0; //Declaramos la variable Temperatura
int grados, decimas; //Para ponerle coma al resultado (en español)

void setup()   { 
//Resetea la EEPROM la primera vez que la usamos
EEPROM.setMemPool(0,512); //Establecemos inicio y tamaño de EEPROM de la tarjeta utilizada
EEPROM.setMaxAllowedWrites(128); //Mínimo para que pueda hacerse el primer borrado completo
//rellenamos de 0 los datos de EEPROM
//Attiny85 tiene 512 Bytes de EEPROM; ajustar según el que uséis
if (EEPROM.readLong(508)!=7091976) { //En ese punto, preferiblemente al final, guardo un valor para saber si ya la he reseteado
  for(int i=0; i<502 -="" 0="" 10000="" 10="" 16="" 1:="" 25ms="" 2:="" 2="" 3:="" 3="" 5="" 5v="" :="" a="" acar="" actuamos="" alimentar="" anal="" analogwrite="" and="" ara="" arte="" b="(RPto2/RPto1);//(1/(TPto2+K)-(1/(TPto1+K)));" basandose="" beta.="" calcular="" caracteres="" coja="" con="" consecuencia="" consola="" convertimos="" correcta="" corresponde="" de="" dejamos="" del="" delay="" desde="" divisor="" ecoge="" ecuaci="" eeprom.update="" eeprom="" efinir="" egla="" el="" emp="" emppin="" en="" enciende="" entre="" erial.println="" espera="" filas="" final="" float="" for="" forma="" funcionamiento="" gico="" ha="" i="" if="" indicando="" indicativo="" inicializado="" input="" int="" justar="" la="" lcd.begin="" lecturas="" led="" ledpin="" leemos="" limpieza="" lmacenamos="" lo="" loop="" los="" ltima="" m="" media="" mediante="" medias="" mero="" millisinicio="millis();" motor="" motorpwm="" n="" o="" omprobamos="" onemos="" onvertimos="" orrado="" output="" pantalla="" para="" parar="" parte="" pines="" pinmode="" placapin="" ponemos="" posici="" progresiva="" puerto="" pwm="" pwmmax="(255*PWMMax)/5;" pwmmin="(255*PWMMin)/5;" que="" r1="r1a" r1a="(voltage*float(resistor))/v2;" rango="" resistance="" resistencia="" resistor="" revoluciones="" sacar="" se="" seg="" segundos="" so="" sobre="" speramos="" steinhart-hart="" t="B/log(r1*unodivr);" tama="" tarda="" temp="T-273.15;" temperatura="" tenemos="" terminado="" thermistor="" tope="" total="" tres="" un="" v2="(R2*V)/(R1+R2)" valor="" valores="" veces="" ventilador="" void="" voltage="4.83" voltaje="" voltios.="" voltios="" voltmax="" volvemos="" x="" ximas="" y="" ya="">=tempMin) { //No nos interesa ponerlo en marcha a menos que se alcance la temp. mínima
  analogWrite(ledPIN,150);//Marcamos indicando que activamos el ventilador
  fanSpeed = doubleMap(Temp, tempMin,tempMax,PWMMin,PWMMax); // Calcula la velocidad a la que corresponde estar
  //(Necesitamos que según aumente la temperatura, lo haga fanSpeed)
  //Valor PWM de 255 en el ATTiny85=5V
  analogWrite(motorPWM, fanSpeed);  // Modifica la velocidad para bajar temp
  delay(100);
  analogWrite(ledPIN,0);
}
else {
  analogWrite(motorPWM, 0);
}
  //DEBUG por serial (no disponible en el aTTiny)
  //Serial.print("Temp: ");
  //Serial.println(Temp);
  //Serial.print("Velocidad: ");
  //Serial.println(fanSpeed); 
  //Serial.print("V: ");
  //Serial.print(fanSpeed*5/255);
  //Serial.print(",");
  //Serial.print(int(fanSpeed*5/2.55));
  //Serial.println("V ");
  //Serial.print("Tiempo encendido: ");   

  //Hacemos parpadear al LED comprobando el tiempo desde la última activación
  if (timeLED>millis()) { //Cuando pasen 50 dias resetear
    timeLED=millis();
  }
  if ((millis()-timeLED)>frecseg*1000*2) {
      analogWrite(ledPIN,50); //enciende LED indicando funcionamiento
      timeLED=millis();
  }
    if ((millis()-timeLED)>frecseg*1000) {
      analogWrite(ledPIN,0); //apaga led
    }

//Si ha pasado una hora desde la puesta en marcha, comprobamos si >= Horas limpieza
//Y si es así, ponemos al tope el ventilador 5 segundos
if ((millis()-millisInicio)>3600000) { //Ha pasado una hora
  millisInicio=millis(); 
  EEPROM.update(0,EEPROM.readLong(0)+1); //Añadimos una hora
}

  delay(frecseg*900); //Ponemos en espera al Atmel
}

// *************** RUTINA MAP MEJORADA (admite fracciones)
double doubleMap(double x, double in_min, double in_max, double out_min, double out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}  

First of all, we open the fan zone, and took the opportunity to remove accumulated dust in recent months with an old brush teeth or the like:



Uauh! Amazing what comes to capture in a short time.
As we discussed above, for the thermistor sensor-we have to place between ground and the input resistance of the same value as the thermistor at 20 ° C ; in this case one of 6K8 ohms.


In my program I regulo the base of NPN 4401 with PIN 4, in the image preparing welding heat shrink tubing:

In the photo the thermistor is misplaced; one of the legs of the thermistor will 5V, not to GND, then changed

First of all relevant evidence should be made; in this case using two Li-ion batteries, total feeding 8V regulator ATtiny85, and the fan feeding the 5V regulated output and the negative connected to the emitter of NPN transistor 4401 positive:


Then I spent an afternoon watching to see how he could feed the 5V fan; I tried unsuccessfully to 11V that the plate has at some points, but had very few mAh and the fan barely moved.
So in the end the only solution was to use directly the 5V  regulated used to power the USB and most of the plate, and opened completely computer and looking at the plate connecting 5V I found it easy to weld to connector side; if you have to look at your team the point, usually near the battery connection, where some voltage regulators are responsible for lowering the power to 5V:


Here we must be careful not to attach pins other than 5V, have to work without battery and power off:


Once you 've got the 5V, directly feed the chip 5V on pin (not the VIN, where would feed through the regulator because there need between 6 and 12V to get 5V).


For good thermal transfer I used thermal grease, but we can also stick with a drop of silicone to remain in contact with the surface to be measured:



Here you can see it with black tape to hold while drying her silicone:


Then I realized the buzz that got the engine to resonate the PWM pulses at low speed transistor; To avoid this simply a capacitor of 10V and a 470uF enough (just less well), it also is advisable to place a diode between positive and negative so that redirect power to the fan itself when disconnected (is covered by heat shrink in the Photo):

This capacitor is a bit cumbersome, smaller also applies
I am very happy with the result; yes it is almost constantly working to stop but do not bother me, it's pretty quiet. This time I did not take final photo with the rush, another day to clean it will update the entry.

1 comment :

  1. really unnecessary. Better with a pair of resistors and a bjt transistor.

    ReplyDelete