Fan RPM With Internal Hall Effect Sensor and Arduino (Intro to Hardware Interrupt and LCD Display)





Introduction: Fan RPM With Internal Hall Effect Sensor and Arduino (Intro to Hardware Interrupt and LCD Display)

About: A Researcher, an Engineer and an electronics enthusiast

For my other project for work, i had to measure the rotational speed of rotor in Revolutions Per Minute (RPM) of one modified computer fan. It had three wires coming out and that ticked me that may be it has some way to control its speed. With some 'googling' i found such fans have internal Hall effect sensor (HES) that can be used to measure its rotating speed. (And for 4 pin connections fan, the fourth pin is to control the speed of fan using PWM signals.)

This project gives quick intro to-

1) Using Interrupts of arduino boards (here arduino Due)

2) Interfacing internal Hall effect sensor of fan with arduino

3) Displaying real time information on LCD display (here 16 x 2)

4) Implement basic logic in programming arduino (here i used RGB LED to change color depending upon the different range of rotating speed)

Step 1: Introduction: @ Hall Effect Sensor and 3 Pin Computer Fans

Hall effect sensor (HES) works on the principle of interaction of magnetic field with electrons flowing in the conductor and subsequent generation of secondary voltage known as Hall voltage. Read more here. Using hall effect sensor generally speed ranges upto 100 kHz or 100 thousand ticks per second can be measured.

Source of HES animated image -

In three pin fans with internal hall effect sensor, generally yellow colored wire is output of HES. Most of the time it requires external pull-up resistor of few kohm values depending on supply voltage. Instead of external resistor, internal pull-up resistor of our arduino board pins can be used. digitalWrite(pinno, HIGH); in setup() function enables this internal pull-up resistor. Using this technique, HES output wire can be directly connected to interrupt pin (here pin 12) without using an external 10kohm pull-up resistor. I have used external pull-up resistor.

With every rotation of rotor, depending on type of fan i.e. number of magnets attached to rotor, we get 1, 2 or 4 ticks per revolution of rotor as output signal from HES. Read more here. We will pick up these ticks by interrupting our arduino program using "hardware interrupts". Interrupts help in letting our arduino do its regular job until some signal is received at interrupt pins. This lets us use arduino perform other tasks while waiting for signal at interrupt pins.

Step 2: Connection Diagram and Components


CAUTION: Arduino due has 3.3V tolerant pins. If higher than 3.3V is given to any pin of due, it will damage that pin or probably entire board.

1) 16 x 2 LCD 1602 display runs on 5V power supply, I have supplied 5V from Arduino due 5V output pin. The SCL and SDA pins are directly connected to I2C to LCD driver board. It worked perfectly without using any step down voltage regulator.

2) The fan motor is powerd by 12 volt power supply from power supply adapter of an old wifi modem. Depending on your fan rating, you can use 3V, 5V or 12V etc. Make sure you do not connect such high voltage to any of the pins of LCD or Arduino.

3) The ground lines of 12V power supply, Arduino and LCD should all be connected together.

4) In above sketch i have shown all ground lines in black color, 5V supply with brown color, 3.3V with orange color and 12V with red color.

5) If you do not have pull up resistor, internal pull-up resistor of arduino can be enabled as described here. But I am skipping it here to make is easier for beginners.

6) To have some fun, one RGB LED has been added which changes color depending on the speed ranges.

Instead or RGB LED, normal 2 pin LEDs can be used by connecting all ground pins to the resistor as shown in figure.

Bill of materials:-

1) Arduino due board ( or other boards can be used, provided interrupt pins are selected accordingly- read more )

For Uno, Nano, Mini, other 328-based boards- pins 2,3

For Mega, Mega2560, MegaADK- pins 2, 3, 18, 19, 20, 21

For Micro, Leonardo, other 32u4-based- pins 0, 1, 2, 3, 7

For Zero, MKR1000- pins all digital pins, except 4

For Due- all digital pins

2) Resistors - 10k and 470 ohm (you can use any other resistors in similar ranges)

3) PC fan or any other motor with inbuilt hall effect sensor (Or externally connected HES)

4) LCD display with I2C interface ( you can use parallel LCDs too, but pinout and code needs to be slightly modified). For installing I2CLibrary and getting I2C address, check my video -

5) Power supply as per used fan/motor (here it is 12V DC) Fan running at full speed.

6) 3 LEDs or single RGB LED, to use as optical indicator of fan RPM range

Step 3: Working and Code

The working is simple in principle. The hall effect sensor generates signal when the magnets connected to its rotor shaft (internally). Depending on number of magnets connected, for each 360 degree rotation of rotor, 1,2,4 signals will be generated. These signals are picked up by arduino pin (here pin 12). To calculate revolutions per minute or RPM, we count number of signals received in 1 second multiplied by 60 and the result divided by number of signals received in 1 rotation.

Line 74: Speed = ((ticks * 60)/fanspace[fan].fandiv);

In my fan I have two magnets attached, hence I get two signals per revolution. I have selected {1,2} in following part of my code-

Line 33: fanspec fanspace[3]={{0,1},{1,2},{2,8}}; char fan = 1; it means fan type 1 having 2 signals per revolution.

Current algorithm and code gives reasonable accuracy of around 10 RPM and update speed of around 1 second. By optimizing code both can be optimized for faster response and higher accuracy. This will be discussed in future projects.

In the beginning I had problem of having leading zeros or LCD display retaining old digits for lower speed e.g. actual speed comes down from 330 rpm to 60 rpm, it was still showing 360 rpm. This is standard problem of left padding or leading zeros. To overcome this I have added following code-

Line 87: // Converting integer Speed to an ASCII string of 4 characters padded left

char SpeedString[4]; // Buffer to store string of 4 chars + 0 termination

sprintf(SpeedString, "%4d", Speed); // change this to %3, 4 ,5 etc depending upon your max speed lcd.print(SpeedString);

Here I have converted the calculated speed in integer form to string form and then sent to LCD, in this way LCD prints speed considering all digits as one single string or text data.

The final code is available on my github page here.

Have fun with arduino...................................................................


//original code by Crenn from

//original project by Charles Gantt from



    • Woodworking Contest

      Woodworking Contest
    • Clocks Contest

      Clocks Contest
    • Oil Contest

      Oil Contest

    We have a be nice policy.
    Please be positive and constructive.




    Me podrías pasar la programación para hacerlo con Arduino uno

    컴파일하는 동안 왜이 오류가 발생합니까?

    'analogWriteResolution'이 (가)이 범위에서 선언되지 않았습니다.

    I would like to apply it to wood crusher.

    The normal rpm of the wood crusher is 1800rpm, but when the load is applied during operation, it falls to 1500rpm. Stopping the engine so that the engine will not turn off after detecting this. Stop the tub turning to the right, turn it to the left a little bit,

    The rest will be applied well, but there is an error during compilation.

    This is Korea Cheongju Thank you


    Dear TheElectromania

    Hi, As I found out, this line of code line 33: fanspace[3]={{0,1},{1,2},{2,8}} relates to the definition of three types of fan. Each of them has 1, 2 and 8 magnets, right?

    1 reply

    Dear TheElectromania

    As you said in the text, we are
    waiting for you to optimize the code for faster response and higher
    accuracy. I think the following links are useful for doing this.

    I had a question. Do Hard Drive
    (HDD) motors have Hall Effect sensor. These motors are more suitable for some projects because they have higher

    2 replies

    hi I had not much time past months to work on projects hence havent updated anything further.
    HDD might have hall sensors too I am not sure though, once I had opened old hdd or cd drive and found hall sensor.
    but instead you can buy hall sensor and use for hdd motor rpm. depending on what exactly you want to do.
    good luck



    Thank you for the answer. I've come up with another question. As i found out for each magnet, we have a pulse at the sensor output. I did not understand this line of code (line 33: fanspace[3]={{0,1},{1,2},{2,8}}). Can you explain this to me more? I have studied a little about the structure of "typedef struct".

    Shouldn't your variable "ticks" be declared as a volatile? It is being updated in the ISR. Any variable updated by the ISR should be declared as volatile.

    1 reply


    This is really interesting! I was wondering, if the fan are not energized, will it works as an anemometer? What modifications are necesary? Thanks!

    1 reply

    to the best of my understanding the output of hall sensor is from open collector ... if fan is not energized everything is just OFF

    Where can I get the lcd ic2 library ?

    1 reply


    in step two I have given link to my video giving details of library and installation procedure.
    good luck.


    I have one magnet in my fan, how would I change the fan type?

    1 reply

    if i remember correctly, you should change the fan type to 0 i.e. your code on Line 33: should be

    fanspec fanspace[3]={{0,1},{1,2},{2,8}}; char fan = 0;

    change fan = 1; to fan = 0;

    good luck

    it is already given at the end of step 3. it is link for my github page and the link is working properly.