4 pulse arduino RPM sensor

Hello all,

I am having some trouble with my current project, it is an RPM sensor for my 9 inch electric motor. On the shaft of this motor is a small ring with 4 magnets inside. I want to use a simple hall effect sensor that you can find all over ebay and amazon in this project as it will be in a car and will be more reliable than an optical reading.

I found this code online that is for an arduino RPM sensor using an interrupt (see below)

The only problem is my shaft has the ring with 4 magnets inside, so should I just divide the RPM calculated by 4? Is there a better way to do this?

Thanks so much in advance!

-Adam

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

      counter++;

 }
void setup()

 {Serial.begin(9600);

   //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.print("RPM=");

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

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

  }

Yes just divide rpm by 4

Thanks for the reply.

Right before it sends the rpm data thru serial to the monitor, I divided the rpm by 4 but for some reason it is giving me crazy RPM readings like 6574 rpm when the motor is going probably 70 rpm! It’s really strange!

Does the Hall sensor signal swing High and Low properly? Use INPUT_PULLUP?

Try printing "counter" (before resetting to 0....) and see if it makes sense. At 70 RPM you should expect 4 or 5 pr second. (about 25% accuracy).

I would also put "passedtime = 0" just before "attachInterrupt(..." and perhaps put in a small delay to make sure Serial.print is finished before activating interrupts.

On the shaft of this motor is a small ring with 4 magnets inside. I want to use a simple hall effect sensor ... will be more reliable than an optical reading.

Optical sensors are notoriously bad at detecting magnets, so you are correct :wink:

You will not get good accuracy with this code at slow revs. I suggest you need to time a number of detections, from rising edge to rising edge, for example, using micros(). No interrupts are necessary.

I assisted someone with a similar problem recently on the forum. I will try to find that thread and post a link here.

What range of revs do you need to measure and how accurately (%)?

Thank you all for the replies! I will try a few of those ideas suggested.

My RPM range is about 0-5000 or so, it’s in an electric car and doesn’t need to be entirely accurate really, even +- 100 rpm would be fine with me!

Here is that other thread. It's 4 pages long, but work skimming through and stealing the later sketches posted.

As Railroader says, are you getting the pulse you think you should be getting.
What is the hall effect type/number?
Are the magnets indeed the correct polarity?

Thanks for the link to that post, I’ll check it out!

Yes the magnets have the correct polarity, this has the small Hall effect sensor on a little breakout board with an LED so I can see it flashing as the motor is spinning. Also note it pulls low whenever it senses a magnet, which is why I changed the interrupt in the sketch from rising to falling type.

YoungestEVer:
Also note it pulls low whenever it senses a magnet, which is why I changed the interrupt in the sketch from rising to falling type.

That won't help at all. To be able to reliably detect an edge, either rising or falling, the input signal must be capable of being high or low. Your signal can only be low or "undefined". When the sensor is actvated, it pulls its pin low. But at other times, the signal simply "floats" and can read high or low at random because there is nothing to force it to be high. That's why you need a pull-up resistor. Either external to the Arduino (10K or 4K7 is ok) or internal (by setting mode to INPUT_PULLUP as railroader suggested in post #3).

Oh ok, I see what you're saying. Yes I forgot to mention I am using a 10k pull up resistor externally, so not the one in the arduino. So the value won't float between high or low like you were saying.

Did you post a link to the type of hall sensor you are using? Some have an analog/linear output, others have digital outputs and some of them have some hysteresis built-in. It's the digital-with-hysteresis type you want.

Many of the modules sold on eBay for use with Arduino use the linear type and have a comparator to give a digital output. These won't have any hysteresis built in. So I am concerned that your sensor is "bouncing" a little like a mechanical switch does, and you need to "denounce" in your code.

To do this, you need to work out what the minimum length of time you expect your sensor to be activated, as the magnet passes it. Then change your code to reject any further edges with, say, 75% of that minimum time.