Quick Fun Speed Lab
Closed Loop Motion Control — Ardu_Serie#44
An 80mm cooling fan has a built-in brushless DC motor, a controller, and a tachometer output for measuring the fan speed, making it an excellent tool for studying closed-loop motion-control (CLMC).
We’ll use a common 80mm computer cooling 3-wire fan in these experiments:
Make sure you get the kind with three wires. The third wire is the tachometer output and makes the measuring part a lot easier :)
For this experiment, we measure the fan’s speed using Arduino Multi-Function Shield. The fan-selected for this purpose is intended to run on 12V but still spins, albeit at a much more leisurely pace when powered from only 5V. Some 12V fans won’t even start to spin at 5V, but a lot of them will.
In order to use a fast connection, we can choose to enable the direct power pins on the Arduino IO pins; Know that the energy delivered to the load is about one-third lower.
Luckily the Arduino Multi-Function Shield (MFS) has a busbar for pin 5 of the Arduino.
To begin with, we supply +5V to the red wire and connect the black wire to ground. Not all fans have the same color scheme when it comes to wiring, but it shouldn’t be hard to figure out. When the Arduino is powered up, the fan begins to spin, if everything is connected properly.
The yellow wire is the open-collector tachometer output, and it needs a pull-up resistor. Luckily, you know how to do that. Connect the yellow wire to digital pin D5. This pin was selected because it can be used as the clock input for Timer/Counter 1 if properly configured.
You let Timer/Counter 1 count the number of pulses coming from the fan’s tachometer. You then use Timer/Counter 2 to give you a precise time base to use for your measurements.
My fan runs at a speed of approximately 870 RPM @ 5V w/ MFS;)
This type of fan reaches the speed of ~1200RPM @12V
The setup() function turns on the pull-up resistor on digital pin D5, which is connected to the open collector tachometer output. The tachometer output changes state for every 90° of fan rotation. This produces two full cycles, or ticks, for every complete rotation of the fan blade.
Timer/Counter 1 is configured to operate in the normal mode with no PWM duties. You set the pre-scaler to advance the counter on every rising edge of T1 (instead of using a derivative of the system clock), which happens to be PD5 in AVR-speak, and which is known in Arduino Land as digital pin D5.
Timer/Counter 1 is a 16-bit counter and now acts as the fan’s odometer, recording the total number of tachometer ticks that you receive via T1.
The odometer will eventually overflow, starting back over at zero, but due to the peculiarities of unsigned integer math, you’ll never notice. You’re only interested in the difference between one odometer reading and the next one, and not the cumulative figure.
Setting up Timer/Counter 1 to be your fan odometer is straightforward. Setting up Timer/Counter 2 to be your precise one-second time base is a little trickier. This is because Timer/Counter 2 has only an 8-bit counter at its disposal, and even with the maximum system clock pre-scaler (divide by 1,024), you still get a timer clock of 15,625Hz. You divide that frequency further by using a software pre-scaler in the interrupt handler.
To obtain an exact one-second time base, you break up 15,625 into two, smaller numbers. By a happy coincidence, the square root of 15,625 is 125, which works out great for an 8-bit hardware counter (being less than 255).
Didn’t you understand? Here’s the math again: the Arduino is in a frequency of sixteen megahertz (16000000); dividing by the maximum prescale of one thousand twenty-four (/1024) we obtain fifteen thousand six hundred and twenty-five hertz (=15,625Hz); dividing by twenty-five (/125) we have 125 Hz which represents a period of 0.008 seconds which in turn is multiplied by 125 resulting in exact 1 second. realized?
It’s often helpful when dealing with integer multipliers and pre-scalers to look at these big numbers in terms of their prime factors. The number 15,625 has only a single prime factor: 5. Five to the sixth power (56) = 15,625.
Now that I know it then just set the timer to 125 Hz and wait 125 times to dial 1 second precisely :)
I tried to use the interrupts and display the reading on the 7-segment display; unfortunately, it was not possible, because the code already makes use of Timer1 for calculations and the MFS library did not work.
To make an extension of this lab I added another Arduino to the project and collected the information through the analog pins.
I did not come to any conclusion so I did not post it here. Instead, I added the files on my Google drive for future inquiries … who knows how to present this graphic with oscilloscope… anyway, there is the graph:
The codes are:
_44_Tachometer_Reading_Ticks_02 (one Arduino)
_44_Tachometer_Graph_Generator_Code_03 (two Arduinos)
Are you ready to put all this fancy book-learning to good use? You’ll find several interesting projects in this book: Arduino Internals!
Credits & References