False hall effect sensor readings

Hello again. I try to count how many times a magnet passes in front of a hall effect sensor (in order to build my scooter speedometer). I am using a keyes ky-024 hall sensor and an interrupt in order to count passes of the magnet. The problem I face is that each time the magnet passes by the sensor I get a reading that does not correspond to reality.

Hall sensor has 4 pins. AO, -, +, DO. I have connected - to GND, + to 5v and DO to digital pin 2.

I run this code.

int peristrofes;
void setup()
 {
   Serial.begin(115200);
   attachInterrupt(0, magnet_detect, RISING);
   peristrofes = 0;
 }
void loop()
{
   Serial.println(peristrofes);
   delay(3000);
 }
 
 void magnet_detect()
 {
   peristrofes++;
 }

For 10 quick passes of the magnet in 10 seconds (~1pass/sec) I get these readings in the serial monitor

0
706
1162
2181
2645
3572
4841
5408

How can I make arduino increment each pass by 1?

How can I make arduino increment each pass by 1?

There may be a pullup on the module, but try setting pin2 as INPUTPULLUP. Try adding a 10K pullup from D0 to 5V.
Try adjusting the big blue potentiometer to a setting with better response.
Try placing a 100nf capacitor between D0 and GND.

cattledog:
There may be a pullup on the module, but try setting pin2 as INPUTPULLUP. Try adding a 10K pullup from D0 to 5V.
Try adjusting the big blue potentiometer to a setting with better response.
Try placing a 100nf capacitor between D0 and GND.

I have already tested all of your recommendations except for the 100nf cap advice.

int peristrofes;

The variable needs to be declared as a volatile int.

Hi,

The sensor has 3 main components on its circuit board. First, the sensor unit at the front of the module which measures the area physically and sends an analog signal to the second unit, the amplifier. The amplifier amplifies the signal, according to the resistant value of the potentiometer, and sends the signal to the analog output of the module.
The third component is a comparator which switches the digital out and the LED if the signal falls under a specific value.
You can control the sensitivity by adjusting the potentiometer.

Have you tried adjusting the sensitivity?
How close does your magnet pass?
How is your magnet oriented? You have a pole pointed at the hall device?

Can you post a picture of your assembly so we can see your component layout?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
How are you powering your project?

Thanks..Tom.. :slight_smile:

TomGeorge:
Hi,
Have you tried adjusting the sensitivity?
How close does your magnet pass?
How is your magnet oriented? You have a pole pointed at the hall device?

Can you post a picture of your assembly so we can see your component layout?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
How are you powering your project?

Thanks..Tom.. :slight_smile:

I tried to change the sensitivity but nothing changes. Just the range of the sensor increases/decreases.
The magnet gets really close but even if it does not the behaviour is the same. The magnet is not mounted in a rotating object. I move the magnet near the sensor.

I have a round magnet (like a coin) for testing. When the sensor senses the magnet a led lights up.

Here is the the circuit. Not a cad but you get the point.

Hi,
Can you try this code, it doesn't use interrupts, it is purely to detect the rising output of your hall sensor and update the displayed number.
It should advance one count with each pass of the magnet.

//Simple code to detect the rising edge of an input.
//Serial display is only updated on rising edge.
//Tom George  24/01/2018

int peristrofes;
byte pickupPin = 2;
bool pickupState = LOW;
bool oldpickupState = LOW;
void setup()
{
  Serial.begin(115200);
  pinMode(pickupPin, INPUT);
  peristrofes = 0;
}

void loop()
{
  pickupState = digitalRead(pickupPin);
  if (pickupState == HIGH && oldpickupState == LOW) // checks to see if input has gone HIGH
  {
    peristrofes = peristrofes + 1;
    Serial.print(" Input Count   ");
    Serial.println(peristrofes);
    oldpickupState = pickupState;
  }
  if (pickupState == LOW && oldpickupState == HIGH) // checks to see if input has gone back to LOW
  {
    oldpickupState = pickupState;
  }
}

It compiles, but I am at work and have not been able to test it.
Tom.. :slight_smile:

Hi,
Just looking at your code in your first post, you have not declared pinMode for the input pin.

Also you need to check your attachinterrupt, you are looking at pin0.

https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

Tom... :slight_smile:

I am also at work right now so I will test your code later.

I have not declared pin 2 as input because it is set as input pin by default.

Also interrupt 0 refers to digital pin 2 in my board (arduino uno).

cabrinha:
I am also at work right now so I will test your code later.

I have not declared pin 2 as input because it is set as input pin by default.

Also interrupt 0 refers to digital pin 2 in my board (arduino uno).

Have you read the reference I posted a link to?

https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

Here is the very informative example code, using pin 2.

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

Tom... :slight_smile:

I have read it and I will do the recommended method. Thats not a problem. To be honest although I dont think it will make any difference.

Normally you should use digitalPinToInterrupt(pin), rather than place an interrupt number directly into your sketch. The specific pins with interrupts, and their mapping to interrupt number varies on each type of board. Direct use of interrupt numbers may seem simple, but it can cause compatibility trouble when your sketch is run on a different board.
However, older sketches often have direct interrupt numbers. Often number 0 (for digital pin 2) or number 1 (for digital pin 3) were used.

Have you tried the capacitor between D0 and Ground? Other low cost modules using the lm393 comparator without hysteresis feedback have demonstrated the same problem.

The capacitor has been a simple fix.

cattledog:
Have you tried the capacitor between D0 and Ground? Other low cost modules using the lm393 comparator without hysteresis feedback have demonstrated the same problem.

The capacitor has been a simple fix.

I have not found so small cap yet. Can I use 1μF cap?

Can I use 1μF cap?

Try it, better than nothing, not as good as a ceramic.

Tried it using an 1μF cap, nothing changed. Same behaviour.

Hi,
Did you try my code ,with and without the cap?

Tom.. :slight_smile:

Try setting up your hall without the arduino. Use an led and resistor from the supply to D0.

Maybe try this code specifically written for this sensor?

// Sensor Keyes KY024 (chip ss49E)
 // Type: Analog
 // External Libraries: no
 // Magnetic field sensor analog HALL effect
 // -------------------------------------------------------------------------
 // Supply 5V
 // Connections Arduino
 // V = ​​5V
 // G = mass
 // S = A0

 const int SIGPIN = A0;
 const float GAUSS_PER_STEP = 2,713;
 
 float rawValue = 0.0;
 float value = 0.0;
 zeroLevel float = 537.0;
 
 void setup () 
 {
  Serial.begin (9600);
  pinMode (SIGPIN, INPUT);
  Serial.println ("KY024 - Linear Hall Sensor - Test program.");
 }

 void loop () 
 {
  rawValue = analogRead (SIGPIN) - zeroLevel;
  Serial.print ("Read Raw");
  Serial.println (rawValue);
  // Reading positive relative to the South Pole, the North Pole negative
  value = rawValue * GAUSS_PER_STEP;
  // Serial.print ("Reading Calibrated in Gauss:");
  // Serial.println (value);
  delay (1000);
 }

quamikazee:
Maybe try this code specifically written for this sensor?

https://github.com/R2D2-2017/R2D2-2017/wiki/Keyes-KY-024-Hall-Sensor

// Sensor Keyes KY024 (chip ss49E)

// Type: Analog
// External Libraries: no
// Magnetic field sensor analog HALL effect
// -------------------------------------------------------------------------
// Supply 5V
// Connections Arduino
// V = ​​5V
// G = mass
// S = A0

const int SIGPIN = A0;
const float GAUSS_PER_STEP = 2,713;

float rawValue = 0.0;
float value = 0.0;
zeroLevel float = 537.0;

void setup ()
{
 Serial.begin (9600);
 pinMode (SIGPIN, INPUT);
 Serial.println ("KY024 - Linear Hall Sensor - Test program.");
}

void loop ()
{
 rawValue = analogRead (SIGPIN) - zeroLevel;
 Serial.print ("Read Raw");
 Serial.println (rawValue);
 // Reading positive relative to the South Pole, the North Pole negative
 value = rawValue * GAUSS_PER_STEP;
 // Serial.print ("Reading Calibrated in Gauss:");
 // Serial.println (value);
 delay (1000);
}

The OP is using the digital output rather than the analog.
Tom... :slight_smile:

I managed to solve the problem. A little debouncing makes things work great. I will post the sketch later. I have completed the speedo part of my project.

Thank you all!