Getting wrong reading from Tacho from PC-Fan

Heey,

I hope anybody here has an idea what is wrong.

I have two fans connected to the Arduino Mega2560
Both fans get their 12v power from an external power supply.
One fan is a PWM fan that I control with PWM the other is a standandard fan without PWM.

I have the Tacho from the fans connectd with pin 22 en 24.
The code I use to read the Tacho is the following (based on an example I found online).

  int fanPulse = 22;
  unsigned long pulseDuration;

  int fanPulse2 = 24;
  unsigned long pulseDuration2;

 int fanPin = 2;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(fanPulse, INPUT);
  digitalWrite(fanPulse,HIGH); /*Use internal reistor*/

  pinMode(fanPulse2, INPUT);
  digitalWrite(fanPulse2,HIGH); /*Use internal reistor*/
  
  pinMode(2, OUTPUT);
  pinMode(13, OUTPUT);

}

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

Serial.print("pulse duration:");
Serial.println(pulseDuration);

Serial.print("time for full rev. (microsec.):");
Serial.println(pulseDuration*2);
Serial.print("freq. (Hz):");
Serial.println(frequency/2);
Serial.print("RPM:");
Serial.println(frequency/2*60);

/* Second fan reader */
pulseDuration2 = pulseIn(fanPulse2, LOW);
double frequency2 = 1000000/pulseDuration2;

Serial.print("pulse duration 2:");
Serial.println(pulseDuration2);

Serial.print("time for full rev. (microsec.) 2:");
Serial.println(pulseDuration2*2);
Serial.print("freq. (Hz) 2:");
Serial.println(frequency2/2);
Serial.print("RPM 2:");
Serial.println(frequency2/2*60);

}

void loop() {
  // put your main code here, to run repeatedly:
  /*analogWrite(fanPin, fanSpeed);*/

  digitalWrite(13, LOW);
  analogWrite(fanPin,20);
  delay(5000);
  readPulse();
  digitalWrite(13, HIGH);
  analogWrite(fanPin,50);
  delay(5000);
  readPulse();
  digitalWrite(13, LOW);
  analogWrite(fanPin,100);
  delay(5000);
  readPulse();
  digitalWrite(13, HIGH);
  analogWrite(fanPin,150);
  delay(5000);
  readPulse();
  digitalWrite(13, LOW);
  analogWrite(fanPin,200);
  delay(5000);
  readPulse();
  digitalWrite(13, HIGH);
  analogWrite(fanPin,255);
  delay(5000);
  readPulse();
  
}

The problem is that the readings I get from the Tacho are incorrect. Here are a few lines from the output.

pulse duration:3897
time for full rev. (microsec.):7794
freq. (Hz):128.00
RPM:7680.00
pulse duration 2:6
time for full rev. (microsec.) 2:12
freq. (Hz) 2:83333.00
RPM 2:4999980.00
pulse duration:2644
time for full rev. (microsec.):5288
freq. (Hz):189.00
RPM:11340.00
pulse duration 2:1263
time for full rev. (microsec.) 2:2526
freq. (Hz) 2:395.50
RPM 2:23730.00

Does any of you have an idea why I get these strange readings?

You can only use pulseIn to make a reliable tachometer if the duty cycle is exactly 50%. Do you know what it does?

aarg:
You can only use pulseIn to make a reliable tachometer if the duty cycle is exactly 50%. Do you know what it does?

This is my first Arduino project, so correct me if I am wrong.

Duty circle at 50% means in this case half power (AnalogWrite at 127), equal high and low on the PWM-pin right?

The tachometer simply 'returns a Low pulse' (draws voltage) once every half spin of the fan (in case of PC case fans's). With the PulIn method I can then get the time (in microseconds) between two of those pulses (so half a spin).

That would then allow me to calculate what the current RPM of the fan is.

One of the two fans is not even a PWM fan, that is supposed to always get a strait 12v (100% duty cycle).

So why would is need to have a duty cycle of exactly 50%. In case of the second fan I can not even do that... well I can, but that is off-topic.

Or where do I make a mistake?

Devata:
This is my first Arduino project, so correct me if I am wrong.

Duty circle at 50% means in this case half power (AnalogWrite at 127), equal high and low on the PWM-pin right?

The tachometer simply 'returns a Low pulse' (draws voltage) once every half spin of the fan (in case of PC case fans's). With the PulIn method I can then get the time (in microseconds) between two of those pulses (so half a spin).

That would then allow me to calculate what the current RPM of the fan is.

One of the two fans is not even a PWM fan, that is supposed to always get a strait 12v (100% duty cycle).

So why would is need to have a duty cycle of exactly 50%. In case of the second fan I can not even do that... well I can, but that is off-topic.

Or where do I make a mistake?

The duty cycle of the feedback sensor, not the duty cycle of the fan drive! But my mind slipped, I was thinking of frequency measurements. Think about it, there is a low and a high part of the signal. If you add the high and low part, you get the total period, from which you can get the frequency.

If the high part is very short, you can ignore it and just use the length of the low part to get the frequency. But it's a little bit short. Thus the frequency will read a little high.

So perhaps you are reading the wrong pulse polarity. But it is much better to configure a pin for interrupts RISING or FALLING, and count the time between interrupts with an ISR. For more than only that reason.

aarg:
The duty cycle of the feedback sensor, not the duty cycle of the fan drive! But my mind slipped, I was thinking of frequency measurements. Think about it, there is a low and a high part of the signal. If you add the high and low part, you get the total period, from which you can get the frequency.

If the high part is very short, you can ignore it and just use the length of the low part to get the frequency. But it's a little bit short. Thus the frequency will read a little high.

So perhaps you are reading the wrong pulse polarity. But it is much better to configure a pin for interrupts RISING or FALLING, and count the time between interrupts with an ISR. For more than only that reason.

I did try reading the Highs, but that did also not work. I kinda lost you here "But it is much better to configure a pin for interrupts RISING or FALLING, and count the time between interrupts with an ISR. For more than only that reason."

Also the pulses that I am reading seems to be going everywhere. Look in my output at RPM 2 That fan is always running at a constant speed, but the results I get are completely different all the time.

There could be noise on your inputs. Can you post a schematic and/or photos of your wiring? How are the grounds connected? A link to the online example you are using?

aarg:
There could be noise on your inputs. Can you post a schematic and/or photos of your wiring? How are the grounds connected? A link to the online example you are using?

You might be on to something.

I can explain the connection, if it's still not clear I can try to make a picture.

I have a external power-supply that I use to power both fans (parallel), they have a plus and a ground obviously.

Other then that, the PWM fan has the Tacho connected to pin 22 and PWM connected to 2. The other fan has the Tacho connected to 24.

That is it. I have no other ground connected.

No pull up resistor on the input? No link to where you got the instructions?

I really hate verbal descriptions. Most people here do, as they have a nasty habit of leaving out the thing that is wrong! Please make a drawing and post it.

aarg:
No pull up resistor on the input?

No. I do digitalWrite(fanPulse,HIGH); That is supposed to use the internel pull up resistor?

According to this page at least: https://www.arduino.cc/en/Reference/Constants

A pin may also be configured as an INPUT with pinMode(), and subsequently made HIGH with digitalWrite(). This will enable the internal 20K pullup resistors, which will pull up the input pin to a HIGH reading unless it is pulled

Yes, that should enable the internal pull up resistor. But it's not as straighforward as using:

pinMode(fanPulse, INPUT_PULLUP);

aarg:
Yes, that should enable the internal pull up resistor. But it's not as straighforward as using:

pinMode(fanPulse, INPUT_PULLUP);

I did pinMode(fanPulse, INPUT)
digitalWrite(fanPulse,HIGH);

That does not do the trick?

Should I put a resistor between the Tacho an the input? And if so, how do I know how much Ohm is has to be?

Devata:
I did pinMode(fanPulse, INPUT)
digitalWrite(fanPulse,HIGH);

That does not do the trick?

Should I put a resistor between the Tacho an the input? And if so, how do I know how much Ohm is has to be?

I told you, it will work. It's just not up to date, it's a form that was used with the older IDE versions. Let's not dwell on this. Where's the rest of the stuff I asked for?

I can make a picture later today, but you probably don't see much more then what I explained. It's really straightforward.

Here are the pictures you asked for.

I hope this helps.

There is no connection to the ground on the Mega.

To where?

Is there no danger from connecting the Arduino board to the 12 v ground?

And on the topic of using the internal pull-in resistor. That is also safe? I did read something about if using no resistor you could damage the board. But the intern resistor should prevent that right?

Devata:
To where?

To the fan system ground. In other words, the negative wire from the 12 volt supply, which also goes to both ground connections on the fans.

Thanks that seem to have done the trick. While the speed indication is twice of what it should be, so I am guessing that both Tacho's gives a Low 4 times every full cycle?

What is strange, because everywhere I read these fans normally return one or two signals per cycle. Here I am with two completely different ones and they both give 4? And if that is different all the time, how does a mobo know if it's 1, 2 or 4?

Nonetheless, the RPM I am now getting (based on 4 Lows per cycle) is correct. So for me I got what I wanted.

Thanks!

I think your pulseIn polarity is wrong. You are using:

pulseDuration = pulseIn(fanPulse, LOW);

That means you are measuring the length of the tach pulse itself. Because the tach sensor output is an open drain output that becomes active when the magnet passes. When it is connected to a pull up resistor, it will be normally HIGH, and LOW when the magnet passes.

You should be measuring the cycle time , which is neither the HIGH state nor the LOW state alone, but the sum of the two. I mentioned this before briefly, in reply #3.

This explains your erroneous readings. I don't think that just dividing by 2 would give an accurate result. But if you're happy with believing that halving it will make it right, then fine... :slight_smile:

aarg:
I think your pulseIn polarity is wrong. You are using:

pulseDuration = pulseIn(fanPulse, LOW);

That means you are measuring the length of the tach pulse itself. Because the tach sensor output is an open drain output that becomes active when the magnet passes. When it is connected to a pull up resistor, it will be normally HIGH, and LOW when the magnet passes.

You should be measuring the cycle time , which is neither the HIGH state nor the LOW state alone, but the sum of the two. I mentioned this before briefly, in reply #3.

This explains your erroneous readings. I don't think that just dividing by 2 would give an accurate result. But if you're happy with believing that halving it will make it right, then fine... :slight_smile:

I will play around with it a little. But the RPM results seem to be right. The max RPM of the fan is 1800, and when I put the PWM at 255 that is what I get. thanks for the help.