Hall sensor - Servo conflict

Mys project involves reading the speed of a wheel using a Hall sensor, calculating the speed of the wheel, and moving a gauge needle using a servo to indicate the speed. The wheel has 5 button magnets to trigger the Hall sensor.

**The code snippets below are reduced to bare minimum to illustrate the problem I am having. The problem being that the first bit of code works perfectly, but when I add the servo code in the second bit of code, the program still works while the wheel is moving, but if the wheel stops with a magnet and Hall sensor aligned, the interrupt service routine is continuously triggered. Move the wheel slightly off the sensor and the ISR triggering stops.
Any ideas why this is happening?
**

**// Hall_test_no_servo** **This code works correctly**
int n_rev;
int magnets_per_rotation=5; 
int n_magnets = 5;

void setup()
{
    Serial.begin(115200);
    attachInterrupt(0, detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
    n_rev = 0;
}

void loop()//Measure RPM
 {
    Serial.print("n_rev=");
    Serial.println(n_rev);
} // end void loop

//This function is called whenever a magnet/interrupt is detected by the arduino

void detect() { n_rev++; }

**// Hall_test_servo** **This code does not work correctly**

#uncategorized include <Servo.h>
int n_rev;
int magnets_per_rotation=5; 
int n_magnets = 5;
int servo_pin=4;
int low_pwm=450; // use low and high to set range
int high_pwm=2400; // of motion of speedo servo

Servo myservo; // create servo object to control a servo

void setup()
{
    Serial.begin(115200);
    attachInterrupt(0, detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
n_rev = 0;

// adding this line of code causes the problem to occur whenever a magnet stops directly in line with the Hall sensor
myservo.attach(servo_pin,low_pwm,high_pwm);

}

void loop()//Measure RPM
{
    Serial.print("n_rev=");
    Serial.println(n_rev);
} // end void loop

//This function is called whenever a magnet/interrupt is detected by the arduino
void detect() { n_rev++; }

What Arduino are you using? If it is an UNO or any board using ATMega328 you need to declare n_rev with the volatile keyword and also disable interrupts to read or write n_rev in loop() or you could get a corrupted value.

Is the servo near the hall sensor? The motor in a servo will generate magnetic fields that the hall sensor might pick up.

Thanks for the suggestions. I tried the volatile keyword - no change. I cannot disable interrupts because my code requires that all of the magnet passes be recorded. The Hall sensor is 5' from the servo so that was not causing the problem.
After several days of trying everything I could think of, I noticed that the ground cable from the Hall sensor had a shield wire connected to the the ground wire, which was also connected to an Arduino GND pin. I removed the shield wire and everything now works correctly.

I wouldn't expect a change for this version of code. However as your code becomes more complex, the optimizer needs to know that n_rev can be modified in an ISR otherwise it may optimize functionality out. All data shared between ISR and non-ISR code should always be declared using the volatile keyword.

Again, if this is an 8-bit Arduino and you plan to read or modify n_rev in your loop() code you need to disable interrupts because an int is a multi-byte variable and an interrupt can happen while you are reading or modifying the variable. Here is an example of making a copy of the variable before printing it:

  int temp_n_rev;
  noInterrupts();
  temp_n_rev = n_rev;
  interrupts();
  Serial.print("n_rev=");
  Serial.println(temp_n_rev);

Here is an example of resetting the counter variable:

  noInterrupts();
  n_rev = 0;
  interrupts();

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.