Reading Hall-sensor

Hi

I'm stucked with reading the state of a Hall-Sensor (Cherry GS100502)
For some reason the state is just bouncing up and down automatically and the result is erroneous.

I've connected the signal wire to the pin number 2 (next to TX and RX pins) and I've taken the power and ground from the board. With digital multimeter everything seems to be working fine (state changes from 0v to 5v when something ferrous is set near to it).

CHERRY
(+)----------> 5v
(-)----------> GND
(S)----------> pin2

I'm using the following code to read the input:

const int pin2 = 2;
const int led = 13;
int value = LOW;

void setup()
{
  Serial.begin(9600);
  
  pinMode(led, OUTPUT);
  pinMode(pin2, INPUT); 
}

void loop()
{
  value = digitalRead(pin2);
  Serial.println(value);
  digitalWrite(led, value);

  delay(50);
}

The led is blinking even though I'm not doing anything and sometimes it might work correctly. I've also checked that the signal wire gets contact to pin of the board.

Later if I would get this working I could use interrupts for reading the state and build an RPM measurement system.

I know there are other threads about Hall sensors too, but I haven't found answer from them.

Thanks in advance.

I've been thinking of that could the sensor require external pull-up resistor? I thought that the software controlled pull-up resistor would work?

Hi riksa,

to enable the builtin pull-up, you have set the pin to HIGH (after setting it to input mode):

 digitalWrite(pin2, HIGH);

MikeT

Thank you very much. I wasted so much time when I didn't understand that the pull-up resistor is set in that matter.

Now it works flawlessly, as do interrupts too. Thank you once more :smiley:

Hi

I'm having problems again with this.

I should be reading the RPM with the sensor, but for some reason the maximun frequency is about 1Hz. In other words I can't trigger hall more than a once in a second, or otherwise arduino will not register the triggering.

Why is arduino handling the signal so slowly? Also, is it allowed to input +12v to digital input?

My current code

#include <MsTimer2.h>

volatile unsigned int Counter1 = 0;
void setup()
{
  Serial.begin(9600);
  MsTimer2::set(1000, printCounters);
  MsTimer2::start();

  attachInterrupt(0, increaseCounter1, FALLING);
}

void loop()
{

}

void increaseCounter1()
{
  Counter1++;
}

int returnCounter1()
{
  int c;
  uint8_t SaveSREG = SREG;   // save interrupt flag
  noInterrupts();   // disable interrupts
  c = Counter1;  // access the shared data
  Counter1 = 0; // reset Counter1 to 0
  SREG = SaveSREG;   // restore the interrupt flag
  
  return c;
}

void printCounters()
{
  Serial.println(returnCounter1());
}

Hi riksa,

just a guess: you should avoid to call Serial.print() when interrupts are disabled because then other interrupts are blocked. I would move the print code to the main loop() and not within a timer interrupt, something like this:

void loop()
{
  printCounters();
  delay(1000);
}

MikeT

It could also be that the sensor is designed to not respond to fast changes, do you have a data sheet for the sensor?

Lefty

It is designed exactly to work with high speed.

I actually demoed the input, by just connecting GND with wire to the the input.

Would this be caused that I haven't used pull-up resistor or defined it for the port, so state change will take too long? Unfortunately I do not have oscilloscope etc. to measure real input.

Mike: You're right with that.

I tried it, here is the whole code in it's simplicity:

volatile unsigned int Counter1 = 0;

void setup() {
  Serial.begin(9600);
  [glow]pinMode(2, INPUT);[/glow]
  [glow]digitalWrite(2,HIGH);[/glow]
  attachInterrupt(0, increaseCounter1, FALLING);
}

void increaseCounter1() {
  Counter1++;
}

int returnCounter1() {
  int c;
  uint8_t SaveSREG = SREG;   // save interrupt flag
  noInterrupts();            // disable interrupts
  c = Counter1;              // access the shared data
  Counter1 = 0;              // reset Counter1 to 0
  SREG = SaveSREG;           // restore the interrupt flag
  return c;
}

void loop() {
  Serial.println(returnCounter1());
  delay(1000);
}

And currently I'm testing it just by connecting wire from GND to pin 2. I also tried to make changes with hihglighted with yellow, but no success. Actually, now when I use the highlighted code, I get values but they are much much higher than should (around hundreds even I just connect the wire once). And since I use just wire, there shouldn't be false triggers etc.

One more reply :smiley:

I must have something wrong with the board, since the following example code is not working correctly either. If I try to connect it to either GND or +5 it changes the state arbitrary.

volatile int state = LOW;

void setup() {
  pinMode(13, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}

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

void blink() {
  state = !state;
}

I have connected a wire into pin 2 and connecting it to either GND/+5

Hi riksa,

even for this test sketch, you should enable the internal pullup because otherwise you will gets the effects you describe:

void setup() {
  pinMode(13, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
  digitalWrite(2, HIGH);
}

MikeT

Thanks a lot Mike T that you are willing to help me with this.

I tried the code, my current code is:

volatile int count = 0;

void setup() {  
  Serial.begin(9600);
  attachInterrupt(0, blink, RISING);
  digitalWrite(2, HIGH);
}

void loop() {
  Serial.println(count);
  delay(500);
}

void blink() {
  count++;
}

Still I have the problem that interrupt is triggered multiple time, when I trigger the wire to the GND. Would external pull-up resistor or some kind of delay help with this?

when I trigger the wire to the GND

Just touching a wire to ground is a potentially noisy, bouncy event - it isn't surprising (to me) you're seeing multiple events.

For test purposes, can you connect a transistor to the interrupt pin, and use the Arduino to switch the transistor. This would be much cleaner than poking a bit of wire, and more like the sort of switch I'd expect to see from a Hall effect switch.

Hi

That would be nice, but currently I do not have any transistors. However, now I can trigger the interrupt more than a once in a second, so I think the original problem is solved.

I were also able to remove most of the bouncing with the following code:

void blink() {
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 10ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 10)
  {
    count++;
  }
  last_interrupt_time = interrupt_time;
}

However, one thing that amazes me is that I get an interrupt when I either connect or disconnect the wire. So I get two interrupts with each connect.

I'm using the following interrupt:

  attachInterrupt(0, blink, RISING);

Unfortunately I can't test the system with Hall sensor until weekend so I can't verify the changes. Of course I will not need the bouncy ignoring system with Hall sensor I guess?

Your sensor looks like it works in exactly the same way as the sensor I'm using (mine is just an IC, it's not in a fancy package like yours).

You definitely need the pull-up resistors (the datasheet you linked to earlier shows a resistor between Vcc (supply) & Output. If you're supplying the sensor from the Arduino's 5v line, then the internal pull-up resistors will work fine. If you're using an external supply, you need to put a resistor between that supply & the sensor's output.

It looks to me like your sensor is optimised for 12v? I notice earlier in the thread you asked if the Arduino could cope with a 12v input; so my guess is you're supplying the sensor with 12v. If your arduino has survived so far, then clearly it's absorbing the extra voltage somewhere, but I'd be really worried about lumping 12v into it... it's definitely going to be happier with 5v (standard TTL voltage). Consider adding an opto-isolator which can cope with 12v to protect your Arduino. At the very least, add a voltage divider between the device & the Arduino's pin.

You should be able to use some of the code from this thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1274834441 But you need to be sure of your hall sensor first...

I made this little fella to hold my hall device (click the pic for the full-sized version):

Note that the underside picture has been mirror-imaged to put the leads in the same order as the topside picture. The pull-up resistor drags the device back up to high (off). The LED indicates the state of the device (off when a magnet is in range) independently of the Arduino, ideal for debugging sensor issues. The decoupling cap is in there because the datasheet recommended it. It should be 100nF really, but I didn't have one handy, so 10nF it is.

Here's the rig on my "test platform", the magnet is not in range yet:

When the magnet passes under the device, the LED goes out:

When the LED comes back on, the Arduino spots it & records the time, etc.

HTH!

Oh, thank you very much of your post.

Well I could clear some thing out. The spec says that 4.5-24v is OK for the hall. First I was supplying it with Arduino board near to 5V. But beacause my setup didn't seem to work correctly. I thought that the magnet field wouldn't have been strong enough due to low voltage etc.

I tried to supply 12 volts only to Hall-sensor, and therefore output was changing from 12V-0V. That's why I asked how much voltage the input can take, so that I would know have I broken something :smiley:

So, I will be using the arduino to supply the Hall and will be using internal pull-up too.

I could try to add the de-coupling capacitor to my setup too.

However, thanks for everyone for supporting me with this. If I'm not able to get this functioning next weekend (Then I can test the setup again) I must be a real dumb. Since, I still have experience of both hw and sw side.

If I get it working I'll post you some reference about my setup etc.