modify a computor fan to build a small centrifuge

Hey guys,
I am currently working on a project using arduino to control computer fans. I saw a video by Andreas Spiess on Youtube(#24 Controlling a Fan by Measuring its Speed and Supplying a PWM Signal - YouTube) and did a similar one. I used a Potentiometer and ReadAnalog function of Arduino and Timer1 library to generate a 25 kHz PWM signal to control fan. The controlling part works OK and I can control the speed the fan by adjusting the potentiometer.
But when I tried to measure the fan speed using the interrupt function of Arduino I found that the tacho signal from the fan is contaminated by the 25 kHz PWM signal. Even after using the DM7414N Schmitt Trigger, the tacho signal is still contaminated by the 25kHz PWM signal. I then used a electrolytic capacitor to connect between the output of DM7414N and Ground. In this way the high frequency PWM signal would be bypassed and then a got a much cleaner signal, at the price of changing the square wave to a triangular wave.
The code I use was try to catch time difference between the rising slop of the tacho signal from the fan ("duratAnem" in the code). I posted my code here. I could not get a reading of the time difference ("duratAnem") when running the code on my arduino micro. And each time a restart the Arduino Micro, the readings from the serial monitor was different.
My goal is to control and measure the speed of the fan simultaneously so I can made a small centrifuge out of the old four wire computer fan. I want to have the speed reading updated every 0.5 second.

// This example creates a PWM signal with 25 kHz carrier.
//
// Arduino's analogWrite() gives you PWM output, but no control over the
// carrier frequency.  The default frequency is low, typically 490 or
// 3920 Hz.  Sometimes you may need a faster carrier frequency.
//
// The specification for 4-wire PWM fans recommends a 25 kHz frequency
// and allows 21 to 28 kHz.  The default from analogWrite() might work
// with some fans, but to follow the specification we need 25 kHz.
//
// http://www.formfactors.org/developer/specs/REV1_2_Public.pdf
//
// Connect the PWM pin to the fan's control wire (usually blue).  The
// board's ground must be connected to the fan's ground, and the fan
// needs +12 volt power from the computer or a separate power supply.

const int fanPin = 9;
const int Tacho_INT =1;
float dutyCycle;
int const potenMeterpin = A0;
volatile unsigned long lastAnem = micros();
volatile boolean validAneo = false;
volatile unsigned long duratAnem = 0;
volatile float CPM =0;

void setup(void){
  //Tachometer
  Timer1.initialize(40);  // 40 us = 25 kHz
  Serial.begin(9600);
  lastAnem = micros();
  pinMode(Tacho_INT, INPUT);
  attachInterrupt(Tacho_INT, RotationSpeed, RISING);
}

void loop(void)
{
    dutyCycle = analogRead(potenMeterpin);
    Serial.print("PWM Fan, Duty Cycle = ");
    Serial.println(dutyCycle);
    Timer1.pwm(fanPin,dutyCycle);
    Serial.print("Fan Speed =");    
    Serial.println( CPM );
    Serial.print("timelapse =");
    Serial.println (lastAnem);
    /*Serial.print("Rising Slope interval=");
    Serial.println(duratAnem);*/
    delay(500);
}
void RotationSpeed (void)
{
  long tt =micros() - lastAnem;
  if (tt > 0) duratAnem = tt;
  lastAnem = micros();
  validAneo = true;
}
float Speed() {
  if (validAneo == true){
  float cpm =1000000/( 2 * duratAnem);
  CPM = cpm;
  validAneo = false;
  }
  return CPM;
}

It's not usually that difficult. Do you have a good power supply? Those brushless fans can draw a lot of current and overload simple power supplies for very short pulses. Maybe add a number of filter capacitors to the power wires. Use different sizes of capacitors to cover different frequencies. If you don't already have an assortment of capacitors in your parts bin, it's time to buy one.

Thanks a lot. I will try your suggested methods. I am now trying to solve the problem with the interrupt function.

Hi,
OP diag.


You are using pin1 as an input, this is not advisable as it is a programming pin.

Try another pin other than pin1 or pin0.

Can you draw your circuit with the power supplies shown?

http://pighixxx.com/micropdf.pdf

Tom.. :slight_smile:

Hi,
Have you got the gnd of the Micro and the gnd of the fan supply connected together?

Tom... :slight_smile:

A tach output won't work properly without pull up 5volt.

Remove that 7414.
Connect the tach output directly to an Arduino input pin with internal pull up enabled.
pinMode(tachPin, INPUT_PULLUP);
Leo..

Hey Guys, I tried another method. In this trial, I remove the capacitor and keep the DM7414. The method that I used to overcome the contaminating PWM signal is the so called "Pulse Stretch method".

Below is my code.

#include <TimerOne.h>

// This example creates a PWM signal with 25 kHz carrier.
//
// Arduino's analogWrite() gives you PWM output, but no control over the
// carrier frequency.  The default frequency is low, typically 490 or
// 3920 Hz.  Sometimes you may need a faster carrier frequency.
//
// The specification for 4-wire PWM fans recommends a 25 kHz frequency
// and allows 21 to 28 kHz.  The default from analogWrite() might work
// with some fans, but to follow the specification we need 25 kHz.
//
// http://www.formfactors.org/developer/specs/REV1_2_Public.pdf
//
// Connect the PWM pin to the fan's control wire (usually blue).  The
// board's ground must be connected to the fan's ground, and the fan
// needs +12 volt power from the computer or a separate power supply.

const int fanPin = 9;
const int Tacho_INT =2;
float dutyCycle;
int const potenMeterpin = A0;
volatile unsigned long lastAnem = 0;
volatile boolean validAneo = false;
volatile unsigned long duratAnem = 0;
volatile float RPM = 0;

void setup(void){
  //Tachometer
  Timer1.initialize(40);  // 40 us = 25 kHz
  Serial.begin(9600);
  lastAnem = micros();
  pinMode(Tacho_INT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(Tacho_INT), RotationSpeed, RISING);
}

void loop(void)
{
    dutyCycle = analogRead(potenMeterpin);
    //Serial.print("PWM Fan, Duty Cycle = ");
    //Serial.println(dutyCycle);
    Timer1.pwm(fanPin,dutyCycle);
    //Serial.print("TachoInterval=");    
    //Serial.println(duratAnem);
    //Serial.print("timelapse =");
    //Serial.println(lastAnem);
    delay(2000);
    Timer1.disablePwm(fanPin);
    digitalWrite(fanPin,LOW);
    delay(50);
    Speed();
    Serial.print("Rotation Speed =");
    Serial.println(RPM);
}
void RotationSpeed (void)
{
  long tt =micros() - lastAnem;
  if (tt > 0) duratAnem = tt;
  lastAnem = micros();
  validAneo = true;
}
float Speed() {
  if (validAneo == true){
  float cpm = 60000000/( 2 * duratAnem);
  RPM = cpm;
  validAneo = false;
  }
}

The problem with 'pulse stretching' is that during pulse stretching, I should write 5 volts signal rather than 0 volts to the PWM pin of the fan. In this way, the 25 kHz signal diminished, while the Tacho signal become crystal clear. However, since if I wrote 0 volts to the PWM pin during pulse-stretching, the Tacho signal vanished. So, in order to have a Tacho signal, The PWM pin must be 5 volts. This, however, does not influence the rotation of the fan at high speed. At low speed, the pulse of 5 volts on PWM pin, even though persists for 50 micro seconds, can significantly accelerate the fan, causing significant speed fluctuation of the fan. So, my conclusion is that, in order to have the fan working smoothly, an external Hall elements chip must be used.
I have another question, so, did anyone know if there's a fan that constantly produce Tacho signal without the need of 5V on PWM pin of the fan?
Thanks a lot!

Hi,
Please answer post#4.

This is interesting about 4 wire fan control.

and something usefull from fritzying

http://fritzing.org/projects/connect-control-and-read-an-4-wire-fan
it has code and all.

Tom... :slight_smile:

Hi,Tom,I did connect the 12 v ground and 5 v ground together. Thanks for your information.:slight_smile:

Maybe the "contamination" is a wiring error, or due to improper grounding.