4-pin Intel CPU Fan Control

Hey all I got a program I found here somewhere working for controlling a fan from a computer. The wiring is pretty simple. Red supply, black ground, yellow rpm tachometer(not used in this application), and a blue control wire. The blue wire accepts a pwm control pulse train, the code is here.

void setup()
{
Serial.begin(9600);
pinMode(6, OUTPUT);
}

unsigned char speed;
unsigned int low = 1;
unsigned int high = 10;
unsigned int baseTime = 10;

void loop(){
  
     digitalWrite(6,LOW);
    delayMicroseconds(low*10);
    digitalWrite(6,HIGH);
    delayMicroseconds(high*10);

    if (Serial.available()){
      speed = Serial.read() - 48;
      low = speed;
      high = baseTime - speed;
      Serial.println(high);
    }
  }

Basically what this does is ramps the fan speed up and down depending on the input(ranging from >0 and <10) from the serial port. Now that part is working dandy. My other program is a little different. I've hit a little bump and I'm not sure if it's because I'm a dullard or if it's something more.

const int propPin = 0;
const int methPin = 1;
const int carbPin = 2;
const int propFan = 6;
unsigned char speed;
unsigned int low = 1;
unsigned int high = 10;
unsigned int baseTime = 10;
int propIn, methIn, carbIn;

  
void setup() {
  Serial.begin(9600); 
  pinMode(6, OUTPUT);
}  

void loop() {
  
  char str[7];
                    
  propIn = analogRead(propPin);
  methIn = analogRead(methPin);
  carbIn = analogRead(carbPin);  
  
  sprintf(str, "%04d", propIn);
  Serial.print(str);
  sprintf(str, "%04d", methIn);
  Serial.print(str);
  sprintf(str, "%04d", carbIn);  
  Serial.print(str); 
  
  int inByte = Serial.read();  
  
  switch(inByte){
     case 'a':
       
       break;
    
     case 'b':
       
       break;
        
     case 'c':     
          
       break;
     
     case 'd':
       
       break;
     
     case 'e':
       
       break;
       
     case 'f':
       
       break;

     case 'm':
       tone(13, 500, 1000);       
       break;
       
     default:
       if (propIn || methIn || carbIn > 500){         
         tone(13, 500, 1000);
       }
       int propFan = map(propIn, 0, 1023, 1, 9);
       for (int i=0; i < 20000; i++){
         digitalWrite(6,LOW);
         delayMicroseconds(low*10);
         digitalWrite(6,HIGH);
         delayMicroseconds(high*10);
         speed = propIn - 48;
         low = speed;
         high = baseTime - speed;
       }
  }  
}

This is basically a program to control 3 fans based on how much of a particular gas is in the air. The empty cases are for user inputs from VB6 which is finished 8-). I'll be able to assign fan speed functions inside each one as soon as I find out how to get them to work in this program. I've been trying to find the bug for hours, does anyone here have a knack for sniffing these types of things out? It's driving me nuts! >:(

Please help! :-/

done! :slight_smile:

const int propPin = 0;
const int methPin = 1;
const int carbPin = 2;
const int propFan = 6;
unsigned char speed;
unsigned int low = 1;
unsigned int high = 10;
unsigned int baseTime = 10;
int propIn, methIn, carbIn;

  
void setup() {
  Serial.begin(9600); 
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
}  

void loop() {
  
  char str[7];
                    
  propIn = analogRead(propPin);
  methIn = analogRead(methPin);
  carbIn = analogRead(carbPin);  
  
  sprintf(str, "%04d", propIn);
  Serial.print(str);
  sprintf(str, "%04d", methIn);
  Serial.print(str);
  sprintf(str, "%04d", carbIn);  
  Serial.print(str); 
  
  int inByte = Serial.read();  
  
  switch(inByte){
     case 'a':
       for (int i = 1; i < 1000; i++){
         digitalWrite(4,LOW);
         delayMicroseconds(90);
         digitalWrite(4,HIGH);
         delayMicroseconds(10);                
       }       
       break;
    
     case 'b':
       for (int i = 1; i < 1000; i++){
         digitalWrite(4,LOW);
         delayMicroseconds(65);
         digitalWrite(4,HIGH);
         delayMicroseconds(35);                
       }       
       break;
        
     case 'c':
       for (int i = 1; i < 1000; i++){
         digitalWrite(4,LOW);
         delayMicroseconds(35);
         digitalWrite(4,HIGH);
         delayMicroseconds(65);                
       }              
       break;
     
     case 'd':
       for (int i = 1; i < 1000; i++){
         digitalWrite(4,LOW);
         delayMicroseconds(10);
         digitalWrite(4,HIGH);
         delayMicroseconds(90);                
       }       
       break;
     
     case 'e':
       for (int i = 1; i < 1000; i++){
         digitalWrite(3, LOW);
         delayMicroseconds(90);
         digitalWrite(3, HIGH);
         delayMicroseconds(10);                
       }       
       break;
       
     case 'f':
       for (int i = 1; i < 1000; i++){
         digitalWrite(3,LOW);
         delayMicroseconds(65);
         digitalWrite(3,HIGH);
         delayMicroseconds(35);                
       }       
       break;
       
     case 'g':
       for (int i = 1; i < 1000; i++){
         digitalWrite(3,LOW);
         delayMicroseconds(35);
         digitalWrite(3,HIGH);
         delayMicroseconds(65);       
       break;
       
     case 'h':
       for (int i = 1; i < 1000; i++){
         digitalWrite(3,LOW);
         delayMicroseconds(10);
         digitalWrite(3,HIGH);
         delayMicroseconds(90);       
       break;
       
     case 'i':
       for (int i = 1; i < 1000; i++){
         digitalWrite(2,LOW);
         delayMicroseconds(90);
         digitalWrite(2,HIGH);
         delayMicroseconds(10);       
       break;
       
     case 'j':
       for (int i = 1; i < 1000; i++){
         digitalWrite(2,LOW);
         delayMicroseconds(65);
         digitalWrite(2,HIGH);
         delayMicroseconds(35);       
       break;
       
     case 'k':
       for (int i = 1; i < 1000; i++){
         digitalWrite(2,LOW);
         delayMicroseconds(35);
         digitalWrite(2,HIGH);
         delayMicroseconds(65);       
       break;
       
     case 'l':
       for (int i = 1; i < 1000; i++){
         digitalWrite(2,LOW);
         delayMicroseconds(10);
         digitalWrite(2,HIGH);
         delayMicroseconds(90);       
       break;
     
     case 'm':
       tone(13, 500, 1000);       
       break;
       
     default:
       if (propIn || methIn || carbIn > 500){         
         tone(13, 500, 1000);
       }
       int propFan = map(propIn, 0, 1023, 1, 9);
       
       for (int i = 1; i < 1000; i++){
         digitalWrite(4,LOW);
         delayMicroseconds(low*10);
         digitalWrite(4,HIGH);
         delayMicroseconds(high*10);                
       }
       
       speed = propFan;
       low = speed;
       high = baseTime - speed;             
  }
}

Just wanted to post this in case anyone needed an example for another application.

Cheers!

Hi CarRamRod,

Thanks for posting this code, it'll be very useful. I'm bit of noob with this stuff, so can you advise of how you connect the fan to the arduino? Does the blue pwn wire get plugged straight into digital pin 6, or is there something else that is needed? Can I just plug the black and red wires straight into my 12v power supply?

Many thanks,
Glen

Yeah you can plug it straight into the 12V(dc) power supply. Until the control wire(blue is standard, but a couple of mine were green) receives a logic low, it will run at full speed. It's safe to connect it without the controlling PWM pulse train so if you're anything like me, you'll be relieved to learn that it's pretty difficult to blow this up. :smiley:

I'd like to add that the best part of this project is controlling the "breeze of victory" when the fan is pointed at one's face.

Hope this helps ;D

I am doing something very similar to this but I'm still planning as I'm a n00b too. I have been doing electronics for almost 20 years with effects pedals and stuff. I am also a fairly competent VB.net programmer but I do flounder until my head gets round the concept.
I am hoping to create a fan controller for my PC. I am keen to create some sort of "USB" connection to the controller (whether it is a controller for other controllers or not will have to wait) from a VB program and port. May I ask for some elaboration on your VB side?
I'd like to be able to send/receive strings through a 2pin connection (inside say USB port).
Also I am wondering why we are using a digital pin but analogue read command to get the RPM feedback. Can the analogue inputs not be used for that?

Firstly, I'd like to mention that this code is sloppy and you can actually use the analog write from the PWM output in the Arduino to control the fan speed through the control wire. The reason I used digital writes with delays was because I was afraid the frequency of the analog write function wouldn't work with the fan, possibly making it go poof. :-/ However, I did eventually man up and give the analog write a shot and it succeeded wonderfully. Since analog write can be used to replace the digital writes with delays, several fans can be controlled if you really want to.

A lot of people recommend this thing called Firmata to help interface the Arduino with VB but all I did was use MS Comm Control 6.0 to send and receive data. I don't have the code with me but the concept is that data is sent if a sufficient amount of time(using a timer) has passed since data has last been received. That way the serial port is coded to do one thing at a time like it's supposed to.

I suppose this is a bit difficult to explain without posting the code and that's what you really want(I know I would ;D). Later today or tomorrow I'll grab my code from my school directory and post it here, with a halfways decent explanation to make it a bit more intuitive.

More coming, good luck. :wink:

Exactly what I wanted and feared to hear :smiley:

I just want a nice simple 2 wire in/out using a USB slot to the masterboard. Once its there I hope to make it tell any other boards what they need to do (I2C maybe). As this will be simply setting changes it should be fine. I basically plan to do a modular version of the Aquaaero system but with my specs as the real one I have doesnt work as advertised unless I buy 8 million other pieces.