Hall effect sensor limits ?

Hi

Ive been using a hall effect sensor to measure the rotation speed of a spinning spherical neodymium magnet, using the code I found on DIYHACKS arduino-hall-effect-sensor-tutorial using their code

/*
Arduino Hall Effect Sensor Project
by Arvind Sanjeev
Please check out http://diyhacking.com for the tutorial of this project.
DIY Hacking
*/

volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
void setup()
{
Serial.begin(115200);
attachInterrupt(0, magnet_detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
half_revolutions = 0;
rpm = 0;
timeold = 0;
}
void loop()//Measure RPM
{
if (half_revolutions >= 20) {
rpm = 30*1000/(millis() - timeold)*half_revolutions;
timeold = millis();
half_revolutions = 0;
Serial.println(rpm,DEC);
}
}
void magnet_detect()//This function is called whenever a magnet/interrupt is detected by the arduino
{
half_revolutions++;
//Serial.println("detect");
}

Its the [Sunfounder Hall Switch](SunFounder focuses on STEAM education with Open-Source robots hall sensor) everything goes well, I am getting my read out as a rediculously long list of numbers, the question is can anyone point at either the code, the hall sensor or the actual arduino, as to why can I only get to 25000 rpm and nothing above that displays even though the sphere is gaining speed beyond that number ?

Thanks in advance

Nik

Even though it is very simple, the ISR takes a finite time to execute. As you increase the frequency of interrupts, you are using more and more CPU time. Eventually, you reach a point where a pulse is arriving before the ISR has even finished its execution and return. Then your system freezes.

What you could do, is simply feed the sensor pulses into a binary counter, to reduce the frequency by a large power of 2. Then to the interrupt input.

While aarg is correct that interrupts have an upper limit, I do not believe that is the cause of your problem.

25000rpm with 2 pulses per revolution is 833.3 pulses per second or 1.2 ms per pulse. The execution time of your simple ISR should be less than 10 microseconds.

Here's Nick Gammon's analysis of the entry and exit from an external interrupt

I count 82 cycles there (5.125 µS in total at 16 MHz) as overhead plus whatever is actually done in the supplied interrupt routine. That is, 2.9375 µS before entering your interrupt handler, and another 2.1875 µS after it returns.

I believe that something else may be going on, possibly related to signal quality. I tested your code by using a clean test signal instead of a hall sensor, and I can easily read 50,000 rpm with your code as posted

void setup()
 {
   Serial.begin(115200);
   attachInterrupt(0, magnet_detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
   half_revolutions = 0;
   rpm = 0;
   timeold = 0;

   tone(2,1666);//will put test signal on pin 2 1666 pulses/sec
 }

Can you get the magnet closer as it passes the sensor? Try the interrupt with FALLING instead of RISING. Try declaring pinMode(2,INPUT_PULLUP).

Can you verify that the pull up resistor on the board R3 is indeed connected to 5v and the signal pin?

There are some other problems with you code at the high rpms due to the use of millis()rather than micros() and the 20 count intervals. You will also want to make rpm unsigned long. The code below was reading 240,000 rpm with a tone(2,8000) test signal.

/*
Arduino Hall Effect Sensor Project
by Arvind Sanjeev
Please check out  http://diyhacking.com for the tutorial of this project.
DIY Hacking
*/


 volatile byte half_revolutions;
 unsigned long rpm;
 unsigned long timeold;
 void setup()
 {
   Serial.begin(115200);
   attachInterrupt(0, magnet_detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
   half_revolutions = 0;
   rpm = 0;
   timeold = 0;

   tone(2,8000);//will put test signal on pin 2 8000 pulses/sec
 }
 void loop()//Measure RPM
 {
   if (half_revolutions >= 200) { 
     rpm = 1000ul*30*1000/(micros() - timeold)*half_revolutions;
     timeold = micros();
     half_revolutions = 0;
     Serial.println(rpm,DEC);
   }
 }
 void magnet_detect()//This function is called whenever a magnet/interrupt is detected by the arduino
 {
   half_revolutions++;
   //Serial.println("detect");
 }

Sunfounder Hall Switch or Sounfounder Analog Hall Sensor? Did you connect to the AO or DO pin of the Sunfounder module?

aarg:
Sunfounder Hall Switch or Sounfounder Analog Hall Sensor? Did you connect to the AO or DO pin of the Sunfounder module?

Hi its the Hall Switch not the analog :slight_smile:

Nik

How about a photo of the experimental setup?

Which polarity of the magnet is facing the sensor? Try reverse that. The Sunfounder
Website vaguely refers to two models being available. One will be to face a North Pole, and the other one to face a South.

cattledog:
Which polarity of the magnet is facing the sensor? Try reverse that. The Sunfounder
Website vaguely refers to two models being available. One will be to face a North Pole, and the other one to face a South.

Hi its a sphere so both poles rotate past the sensor :slight_smile:

Hi its a sphere so both poles rotate past the sensor

I don't think you want that. If you have an axially magnetized spherical magnet
you want to point one or the other poles at the sensor depending upon what kind of sensor it is.

aarg:
to reduce the frequency by a large power of 2. Then to the interrupt input.

will you save power is you use a small power of 2 ?
any benefit of using a medium power of 2 ?

cattledog:
I don't think you want that. If you have an axially magnetized spherical magnet
you want to point one or the other poles at the sensor depending upon what kind of sensor it is.

the Hall effect requires the change from positive to negative do read the value

How often does "volatile byte half_revolutions" overflow while calculating RPM and using the serial monitor?