Not entirely sure if it should be under hardware or software… But…
I am using pin1 to count pulses from a 12V computer fan. It returns some numbers to me where at full speed it reports 2200 rpm, which is realistic since the manufacturer says 2000 in the description for it.
However, I am a bit skeptic at how good it is at matching exact numbers… Full speed returns 2200, and on 0.15 pwm cycle it returns 760 exactly, when it changes to 0.16 on the pwm cycle it then returns 780 rpm instead, and I have a real hard time believing it is so precise.
I then suspect my code of being wrong, but I don’t see many things I can do wrong with it, but here it goes anyways
`hardware.pin1.configure(PULSE_COUNTER, 1.0, 2); //Configure pin1 as a pulse counter, count over 1.0 second and divide by 2 (fan gives two pules for one rotation)
function rpmCalculate()
{
local pulseCount = hardware.pin1.read(); //Get the pulse count from the counter
pulseCount *= 60; //Multiply by 60 to convert rotations per second into rotations per minute
server.log(“Fan is running at " + pulseCount + " rpm”); //Show what we got
imp.wakeup(60, rpmCalculate); //Do this again in 1 minute
}
rpmCalculate(); //Initial start of the function`
To get the pulses from the fan I just use the rpm wire going out of it, and having a 10k pull-up resistor on going to 3v3.
I think we’ll need more specs on the fan itself. The electronics involved in the pulse and how it’s done on the fan. A magnetic sensor? Can you give us the model number of the fan?
As it appears you have the pin1.configure statement/function set up correctly, why are you questioning your results?
I am a bit confused though as I believe PULSE_COUNTER returns an integer, and therefore pulseCount = 760 would not seem right as it’s not an appropriate multiple, (even considering the divide-by-2) … perhaps this is the value you’re questioning?
Have you looked at the pulse output / pin 1 input on a scope to make sure the signal is what you expect … i.e. a somewhat clean, appropriate logic level pulse train?
If you have access to a frequency generator (even perhaps an app with appropriate audio port output), you could use this as an input to pin 1 to verify frequency. Similarly, if you have a frequency counter (again, there is likely an inexpensive/free app), you could measure your fan output signal and compare to your imp readings.
PWM and resulting volts applied to fan motor aren’t linear against to rotation speed. In general - due to fan. It’s a bit hard to believe that you can get even rotation for 1.8V applied to 12V fan.
Look at your results and you can see:
pwm 1.0 -> 2200
pwm 0.15 -> 330 you got 760 or 760/330 = 2.303 times more
pwm 0.16 -> 352 you got 780 or 780/352 = 2.216 times more
Only thing I know about it, is that it is a “Arcitc Cooling Alpine 11 PLUS”
Only value I don’t question, is the one on full speed, because it seems about right… However, it is still strange it matches 2200 perfectly every tie… not 2201, not 2199… 2200 perfectly… I have a hard time believing it is such a accurate device…
The fan can even run on down to 0.05 pwm cycle, but then the pulses from the fan goes crazy and goes up to over 11000
You don’t believe to fan manufacturer - 2000 isn’t ok, bet yours 2200 is ok:)
And you don’t believe to imp - to steady readings:)
I don’t believe that you can start motor with 0.05pwm - 0.6V and “going down to 0.6V” sounds incorrect due to inertia and motor EDS. Typically motor control never use voltages under start-up voltage. You can get “strange” results - and you get.
Again - check the link and take a look on others about DC fans and pwm - pwm vs rotation speed.
What kind of sensor you are using to count pulses? Optical, Hall, reed switch?
And motor driving circuit - H-bridge, simple transistor switch, motor winding clamping circuit (simple diode or diode+C+R). Can motor induct impulses in to counter circuit?
Take a LED, put white spot on fan wing, connect led to imp out configured as pulse generator or 50% PWM. Light the spot with a LED. Changing frequency the spot seems to “stand still”. And then you can make calculations - simplest stroboscope. And see does the speed changes or not.
I believe the ‘stability’ in your number is likely simply due to your calculation method. It isn’t really 2200 rpm, it’s 60 *= pulseCount(rps), where pulseCount would only have certain limited (integer and half-integer) values. (At least, this is my understanding of the PULSE_COUNTER functionality … and that you have it configured to divide-by-2). So, the 2200 is esentially a ‘rounded’ (or quantized) number
Given this, I’m still having a tough time understanding where your 2200 number originates. 2200/60 = 36.666… , meaning your hardware.pin1.read() would have to return this value. I didn’t think this would occur given the way you have the pin1.configure set up. But maybe I’m just misunderstanding something. (I’d be interested in learning more about this if I’m missing something).
Anyway, I believe this is all that’s at play with the ‘accuracy’ or stability of your readings.
The pulse counter only ever returns integers. The divide-by-N feature is there for cases where you’re worried that the count will exceed 2^31 (about two billion). The code you posted will be rounding the actual RPM down to the next multiple of 60RPM.
You don't believe to fan manufacturer - 2000 isn't ok, bet yours 2200 is ok:)
And you don't believe to imp - to steady readings:)
I don't believe that you can start motor with 0.05pwm - 0.6V and "going down to 0.6V" sounds incorrect due to inertia and motor EDS. Typically motor control never use voltages under start-up voltage. You can get "strange" results - and you get.
Again - check the link and take a look on others about DC fans and pwm - pwm vs rotation speed.
I never said I could start the motor (fan?) with 0.05pwm, I start it off with full power, since the imp first needs to start and then starts to slow it down. This isn't just a dc motor either, it is a computer fan with build in pwm control, all I need to do is to give it 12V, GND, and PWM.
What kind of sensor you are using to count pulses? Optical, Hall, reed switch?
I have no idea, it is build into it and just pulls down for each pulse.
The code you posted will be rounding the actual RPM down to the next multiple of 60RPM.
Are there any way to make it not do that? Or do I need to count pulses over a longer period of time then?
I see.
Count pulses over 15 sec at least 1100 pulses for 2200 rpm or 110 pulses per 220 rpm. Better - count over 30 or 60 sec.
I suppose the PWM value here is just a reference and other is done in built in control - many IC’s do that.
In general - what is the task you try to achieve?
(Thanks for clarifying the integers only return @peter … hadn’t used this feature yet, so wasn’t sure how how the divide-by-n worked. That said, I’m not sure where some of the original post non-60 multiples are originating. Seems like something perhaps not within the posted code).
Perhaps it’s been answered previously, but what is the maximum frequency (and/or associated pulse characteristics) that can be reliably detected using PULSE_COUNTER?
As others have said, maybe print the pulses per second (as this will move in individual digits vs 60’s) and then maybe put a bit of card against the fan and check that the speed decreses.
Made some modifications to the code, added so it is possible to easy change the duration of the sampling time. Seems to do the trick with longer time.
Also makes sense it will be better to measure over more time, and why it was giving me problems… I did exactly the same on an arduino, except I used a interrupt. I then registered the millis() from when last readout was done, then just kept counting pulses until I wanted the rpm count again, it then calculated the rpm by using the pulses it had counted and calculating the time from when it started counting. So where I had 1s with the imp, I had all 60s with the arduino.
But here it is, in case anyone can use it for anything.
`rpmDuration <- 3.0;
hardware.pin1.configure(PULSE_COUNTER, rpmDuration, 2); //Configure pin1 as a pulse counter and divide by 2 (fan gives two pules for one rotation)
function rpmCalculate()
{
local pulseCount = hardware.pin1.read(); //Get the pulse count from the counter
pulseCount *= 60.0/rpmDuration; //Multiply by 60 divided by measure duration to convert rotations per second into rotations per minute
server.log(“Fan is running at " + pulseCount + " rpm”); //Show what we got
imp.wakeup(60, rpmCalculate); //Do this again in 1 minute
}
rpmCalculate(); //Initial start of the function`
Added a bit more… I now got the pulse counting in one function and the server.log stuff in another… So every 5 seconds it count pulses and calculates rpm, and also does an average with the last measured number, and every 60 seconds it sends what it got…