Tachometer Using Arduino and Hall Effect Sensor

Introduction to Tachometer

In this project we will make a tachometer using Arduino. It is a device which is used to measure the RPM (revolution per minutes) of rotating objects like a shafts or wheels etc. This project differ from other projects present around web as it uses a Hall Effect sensor rather an IR LED  sensor which means it can be used in any prevailing ambient conditions.


  • Hall Effect Sensor
  • Arduino Uno
  • Rotating Shaft (Who’s RPM to be measured)
  • Small magnet
  • Connecting wires

Let us first start with the principle of a Hall Effect sensor. Click on link to learn about Halls Effect sensor and working.

NOTE: This tutorial makes use of the Timer Interrupts of Arduino Uno defined in previous article to measure the RPM more precisely and accurately rather than other prevailing methods present. If you are not familiar with this concept than check out that article first.


The setup for making this project is very simple.

  • A small magnet is placed (fixed) on the shaft/wheel whose RPM is to be measured.
  • The detector of Hall Sensor placed in the proximity of the shaft (perpendicular to axis of shaft).
  • Hookup the Vcc and Gnd pin of the hall sensor to Arduino’s 5V and Gnd respectively using jumpers.
  • We will use the Timer0 of Arduino Uno for this project, so, after connecting Vcc and Gnd pin of the Sensor connect its output pin to the pin 2 of Uno for readings.

The setup to measure shaft RPM is shown in figure below:

Techometer using Arduino and Hall effect sensor using interrupts of microcontroller. (Circuit Configuration)
Figure: Techometer Circuit Configuration


int hallsensor = 2;                // Hall sensor at pin 2

volatile byte counter;

unsigned int rpm;

unsigned long passedtime;

void isr()


   //Each rotation, this interrupt function is run twice, so take that into consideration for

   //calculating RPM

   //Update count


void setup()


   //Intiates Serial communications

   attachInterrupt(0, isr, RISING); //Interrupts are called on Rise of Input

   pinMode(hallsensor, INPUT); //Sets hallsensor as input

   counter = 0;

   rpm = 0;

   passedtime = 0; //Initialise the values

 void loop()
   delay(1000);//Update RPM every second

   detachInterrupt(0); //Interrupts are disabled

   rpm = 60*1000/(millis() - passedtime)*counter;

   passedtime = millis();

   counter = 0;


   Serial.println(rpm); //Print out result to monitor

   attachInterrupt(0, isr, RISING);   //Restart the interrupt processing



Most of the code is clear from the comments mentioned.


The code as mentioned above makes use of the Arduino Interrupts. Now as we know the Interrupts execute a set of instruction when called no matter what the Arduino was doing before. Here, Interrupts are called when the magnet passes through the detector.

We use Interrupts here to count the number of times the Hall sensor detects the magnet. Whenever there is a hike in Input pin the Interrupt routine (ISR function) named as “isr” is called which increment the counter value and thus makes a count.

Use of Interrupts increases the accuracy of reading as Interrupt is called every time the magnet passes and Uno counts it this is different from other methods in which the Arduino has to wait for whole code to be finished before getting back to read the Sensor reading again and if the code is large due some other reasons the reliability of the reading decreases drastically.

The Interrupts in Arduino Uno are initiated or called on either using Falling, Rising or Logic type. In our Program we have used the Rising type Interrupt initiator; Rising type calls the Interrupt every time the detector pin detects a rise in input from LOW to HIGH.

If you are using an IR LED based sensor you can also use Falling type, in this case the Interrupt will be called every time the detector pin detects a fall in the input i.e. from HIGH to LOW.

Another thing to note is the formula for the rpm calculation; it is based on simple math and unitary method to calculate number of revolution made by the shaft-

 i.e. RPM= No. of counts / Time taken to count

Time taken to count will be measured through millis function of Arduino. Study complete article about millis function here.

Delay Function:

The delay(1000) is used in the code it determine after how much time the value to be changed on your display, you can set it according to your needs.

The display device used in this tutorial is the Serial Monitor of the Arduino itself; instead of this you can also use 16*2 LCD or LED shields to display the RPM values using the respective libraries and hardware.


The value obtained from this project can further be used for measuring the speed of the wheel/disc to which the shaft is connected using the relation-(3.14*D*N)/60 here, D is diameter of the wheel/disc and N is the RPM. This relation will give the speed in m/s. This speed further can be converted to Kmph or Mph.

The value obtained can also be used in positioning of some other components relative to shaft or for feedback and control.

Feel Free to contact us, comment below and provide us with your feedback to improve our services. Like our facebook page for more posts.

14 thoughts on “Tachometer Using Arduino and Hall Effect Sensor”

  1. Syra J’s comments reagarding the (millis()-passedtime ) is pertinent, we are measuring the revs in 1 sec
    Why determine again .What i also fail to understand is why 2 interrupts in 1 rev, are you using 2 magnets?
    I used IR sensor , with 1 pulse per rev, the rpm calculation in which case requires to be divided by 2
    This progarm/sketch requires a lot of fine tuning to give useful results

  2. Hi, I have a question, how close needs to be the magnet from the hall sensor in order to read the signal. I know it depends on how powerful the magnet is. Does anybody knows if it is possible to make it work if the space is around 10mm and with a plastic sheet in between. In case the fun is inside a housing and the sensor outside.

    Thanks 🙂

  3. this code is not accurate.your code gives the average value in 1 second. what if there are 10 rotation in 1 second and all of different rpm, but the final value will be the average more or less than the accurate value.

    1. One thing i must clear here that all the code available here are working and for educational purposes and provide basics of that topic. For further modifications you learn from that provided basic code and design and/or change accordingly.
      Or you can directly email to the author (contact details are provided at the end of article)


  4. What? How is someone asking a question about a project to soneone who posted said project considered to be “blame” them for something or not being “thankful”?
    There must be some sort of language barrier, or some kind of misunderstanding that I’m missing… Either that or people are just becoming alarmingly soft if they think asking someone a question about something they posted publicly somehow is equal to blaming them for who knows what -_-

  5. this is just estimates brother. don’t expect too much from devices. nothings perfect. you shoukd work around your code in order to be close to reality, i mean don’t blame the original coder, you should be thankful that he shared an idea

  6. Any idea why it only increments by 100, or is that by design? For instance if I just drag a magnet over the hall effect sensor once or twice it outputs 100rpm. If i do it faster 200, etc. instead of like 8, 12, 60, etc.
    A bigger issue I’m experiencing is that beyond 2800rpm it simply pops out random, absolutely incorrect values, like values in the 30-50k range which is impossible for what im testing with. My code is exactly as above, except I’ve added the necessary code to use a TFT display rather than serial monitor.
    I’ve also tried adding a .1uf cap between VIN and GND at the sensor so some people recommend this, I’ve also tried different length leads to get the Arduino as far away as possible to avoid any possible interference, and even tried using the code with a reed switch instead, which works however it does the same thing when the speed increases above ~2800rpm.
    I’d be extremely grateful for any suggestions you may have!

    1. SyraJ:
      Try changing “volatile byte counter” to “volatile int counter” this will allow it to read over 7800 rpm.
      Also make this your main loop:

      void loop()

      delay(999); //Update RPM every second, used 999 cause it takes about a millisecond to do the calculations

      detachInterrupt(0); //Don’t process interrupts during calculations

      rpm = 60*counter;

      counter= 0;


      Serial.println(rpm); //Print out result to monitor

      attachInterrupt(0, isr, RISING); //Restart the interrupt processing


      I don’t know why the original code tries to calculate the elapsed time, because we already know the elapsed time is one second (actually 999 ms in my code).

      If you want to test the accuracy, you can set one of the spare pins eg pin3 to output a pwm square wave using pinmode and analogwrite and connect it to the input pin 2, it should read 29400 rpm.

  7. there is a slight miscalculation in your sketch:
    rpm = 60*1000/(millis() – passedtime)*counter;
    rpm = 60*1000*counter/(millis() – passedtime);
    as multiplications finish before divisions

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.