PWM only works in 4 pin intel fan at 70-100% duty cycle

I am controlling a 12v 4pin fan using arduino uno pwm.

I didnt do anything regarding frequency change, only coneected the 12v power source and the arduino to the same ground and the PWM control worked fine, tough with one problem.

70% is the minimum i can get. Below that, the fan stays at 70%, doesnt go down more thant this.

I wish i could shutdown the fan using 0% pwm and make it turn slowly to.

There is no strange noise caused by low frequency as some people report.

Any help?

Not sure how you have everything connected. It's always nice to see a schematic, that's how we do stuff. (It's not been described verbally, but my eyes always glaze over when people try that.)
It's an electronic assembly, it's more than a motor with a fan blade. So, PWM has a limited effect.
You'll likely have to use one of those other wires (google research that} - "four lead fan control", "4 wire fan control", or similar.

The assembly is pretty simple:

Arduino Uno
12v Power Source
4 pin fan

Uno groud connected to 12v ground.

4 pings:
-12v and ground fan pins connected to 12v source

-pwm and tachometer pins connected to arduino

pwm activated trough "analogWrite(pin, value)"

I can measure speeds going from 1200 rpm to 2200 rpm.
I read the datasheet after doing this and it said it should responde to 30/20% pwm.

Photo:

EDIT: 4 pin specification: Motherboard Form Factors

I read the datasheet after doing this and it said it should respond to 30/20% pwm.

One might wonder why you didn't link that datasheet.

What exactly does that mean ? Does it mean the maximum variation of dutycycle possible is 30%, as in
70% to 100% ?

raschemmel:
One might wonder why you didn't link that datasheet.

What exactly does that mean ? Does it mean the maximum variation of dutycycle possible is 30%, as in
70% to 100% ?

"Minimum specified RPM must be 30% or less "

Wich means there should be variation from at least 30 to 100%

This:

Minimum specified RPM must be 30% or less

means this:

Which means there should be variation from at least 0 to 30%

this:

Wich means there should be variation from at least 30 to 100%

would be
this:

Minimum specified RPM must be 30% or MORE

raschemmel:
This:

means this:

this:

would be
this:

Im basd on this pic:

Perhaps you could post the code you are using to generate the 21 kHz to 28 kHz PWM signal. I didn't know an Arduino could do that range. edit -now I know, I googled "25 khz pwm arduino" and saw lots of good stuff, including this Setting up arduino Pwm for 25khz at 50% duty cycle - SparkFun Electronics

I believe it's done by changing the Timer configuration . Nick Gammon has a tutorial on that.

dmjlambert:
Perhaps you could post the code you are using to generate the 21 kHz to 28 kHz PWM signal. I didn’t know an Arduino could do that range. edit -now I know, I googled “25 khz pwm arduino” and saw lots of good stuff, including this Setting up arduino Pwm for 25khz at 50% duty cycle - SparkFun Electronics

Thanks for the PWM library. Changing the frequency to 25khz didnt change anything.

I did an pulse response test code and it seems that when i set the PWM to 30% it goes to 50% the speed. I did the calculations wrongly before, its going to 50 minimum not 70 (i am getting the same output with or without the frequency change code).

Maybe my fan in particular is limited to 50% minimum, even if the datasheet says it should be 30%.

Code:

#include<PWM.h>

int fanPulse = 0;
int fanPin = 3;
unsigned long pulseDuration;

int32_t frequency = 25000; 

void setup()
{
  Serial.begin(9600);
  pinMode(fanPulse, INPUT);
  digitalWrite(fanPulse,HIGH);
  bool success = SetPinFrequencySafe(fanPin, frequency);
  if(success) {
    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);
  }
}

void readPulse() {
  pulseDuration = pulseIn(fanPulse, LOW);
  double frequency = 1000000/pulseDuration;
  

  Serial.print("RPM:");
  Serial.println(frequency/2*60);

}

void loop()
{
  int i = 0;

  analogWrite(fanPin,80);
  Serial.println("PWM SET TO 30%...");
  delay(1000);
  Serial.println("Set point speed: ");
  readPulse();
  delay(1000);
  Serial.println("PWM set to 100%, GO!");
  analogWrite(fanPin, 255);
  for (i = 0; i <= 100 ;i++){
    

    readPulse();

    delay(10);
    
  }
  Serial.println("Test completed, restarting to 30%...");
  analogWrite(fanPin,80);
  delay(5000);
  
}

Here is the output:

PWM SET TO 30%…
Set point speed:
RPM:1290.00
PWM set to 100%, GO!
RPM:1290.00
RPM:1350.00
RPM:1440.00
RPM:1560.00
RPM:1620.00
RPM:1710.00
RPM:1770.00
RPM:1830.00
RPM:1860.00
RPM:1920.00
RPM:1950.00
RPM:2010.00
RPM:2040.00
RPM:2070.00
RPM:2100.00
RPM:2160.00
RPM:2160.00
RPM:2220.00
RPM:2250.00
RPM:2280.00
RPM:2310.00
RPM:2340.00
RPM:2370.00
RPM:2400.00
RPM:2430.00
RPM:2430.00
RPM:2460.00
RPM:2460.00
RPM:2490.00
RPM:2490.00
RPM:2490.00
RPM:2520.00
RPM:2520.00
RPM:2520.00
RPM:2520.00
RPM:2550.00
RPM:2550.00
RPM:2550.00
RPM:2550.00
RPM:2550.00
RPM:2550.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2580.00
RPM:2610.00
RPM:2580.00
RPM:2580.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
RPM:2610.00
Test completed, restarting to 30%…

I think you're supposed to count the tach pulses over a period of time, at 2 pulses per revolution, not measure the pulse width.

Does this help ?

dmjlambert:
I think you're supposed to count the tach pulses over a period of time, at 2 pulses per revolution, not measure the pulse width.

Measuring the pulse width is more reliable in my understanding, shorter pulses mean more speed... (i got the rpm measuring code from top 1 result in google). And the RPM values make sense to the way these fans operate when they are in a Intel CPU.

When i put something in the way of the fan and it slows down or stops (i know i shouldnt do this but it for the sake of testing) the values measured go down accordigly.

raschemmel:
Does this help ?

This is the code i used for the speed sensor. And it works better then the guy in the post, only limited to 50% minimum pwm...

I am starting to think this is a limitation from my fan. Thanks for the help you all. If you have any other ideas...

The data sheet also mentions you need to pull the tach pin high. It says pull it to 12 V but I don't know if that would be critical. If you did pull it to 12 V then I guess you could make a voltage divider to read it. I am kind of wondering if you are reading noise and not getting an accurate RPM reading.

dmjlambert:
The data sheet also mentions you need to pull the tach pin high. It says pull it to 12 V but I don't know if that would be critical. If you did pull it to 12 V then I guess you could make a voltage divider to read it. I am kind of wondering if you are reading noise and not getting an accurate RPM reading.

I did the pull to 5v and it didnt change anything in speed readings. It only stabilizes the readings to 0 when the pin is disconnected.

Measuring the pulse width is more reliable in my understanding,

You understand incorrectly.

Measuring the pulse width means the measurement has to be more accurate to gain a sense of the speed than measuring a number of pulses over a period of time. You are also likely to see more variations.

That's guys math involving 1000000/pulseDuration and RPM=frequency/2*60 looks interesting. I'm not sure how long that pulse stays high when it goes high, and you're only measuring the time it is low. I think you would have to measure the beginning of pulse going low to the beginning of the next pulse going low, or count the pulses, to be accurate. But this math probably does tag a wag at it.

You could make some code which counts the pulses and get an RPM you know is accurate, then simplify the code by going back to using pulse width but calibrate the reading by adjusting the numerator from 100000 to a number which gives you the accurate frequency. For best results make sure the calibration is accurate at different RPMs.

Just an update for everybody that helped me (thanks), i managed to implement an PID control on the fan (thats what i wanted) from 50% of the speed to 100%. Thats enough i think, you can mark this as solved.

Just an update for everybody that helped me (thanks), i managed to implement an PID control on the fan (thats what i wanted) from 50% of the speed to 100%. Thats enough i think, you can mark this as solved.

FYI, it is customary on the forum to post your solution if you arrive at it by yourself as opposed to posting something like 'I tried the last suggestion and it worked".

A lot of people spent time trying to help you and I am sure they would like to know how you arrived at your solution. I understand you implemented PID control but could you please take the time to post your code and explanation as a courtesy to those who tried to help you ? (not to mention all those out there with a similar problem looking for a solution . Stating you managed to solve your problem isn’t going to be much help to them.