Hall effect sensor help

I have a linear actuator that has a built in hall effect sensor. Aside from the motor power wires (it's 12V and you just reverse polarity to change direction as it's made for automotive applications), it has three more wires. +VCC, GND, and PULSE. It says +VCC can be anything from 5-20VDC.

So I have it powered from the 5V out pin on an Arduino Leonardo. The PULSE line is connected to IO pin 2, and GND is connected to the Arduino. When I run the actuator (manually, it's not controlled by the Arduino yet), I see the following on my oscilloscope:

That leads me to believe, if I remember my theory properly, that I've got about a 20Hz pulse output (10ms per graduation would be about 50ms long for a full pulse which is 20Hz) as it runs (and thus I could measure distance over time and get a distance per pulse if I were so inclined).

Now, the problem is I need to sense and count these pulses. Seems like a perfect job for an interrupt. So I tried the following code and the LED appears to blink rapidly as I move the actuator as it probably should:

int pin = 13;
volatile int state = LOW;
int counter = 0;

void setup()
{
  Serial.begin(9600);
  attachInterrupt(1, talk, CHANGE);
}

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

void talk()
{
  state = !state;
  Serial.print(counter);
  counter++;
}

20Hz is pretty fast, but it looks like about 20Hz.

So then I go a step further and try to see some serial output of what's going on because ultimately I want to control the actuator via serial (or the network, but my guess is that still means serial to some network device). So I do the following:

volatile byte half_revolutions;
 void setup()
 {
   Serial.begin(115200);
   attachInterrupt(1, magnet_detect, CHANGE);  //Initialize the intterrupt pin (Arduino digital pin 2)
   half_revolutions = 0;
 }
 void loop()
 {
   
 }
 void magnet_detect()//This function is called whenever a magnet/interrupt is detected by the arduino
 {
   half_revolutions++;
   Serial.println("detect");
 }

Now, yes, I realize that the serial speed is different in the above two examples, but I've tried 9600 and 115200 in BOTH and it seems to make no difference.

In the second code example, when I run the actuator once for maybe a half second, I see a few "detect" words spit to the serial terminal. If I run it a second time, I may or may not get any. And after that, nothing. No output at all.

What could be going on here? Is this interrupting too fast to reliably work with serial output since both use interrupts? Or am I missing something else?

--Donnie

void magnet_detect()//This function is called whenever a magnet/interrupt is detected by the arduino
 {
   half_revolutions++;
   Serial.println("detect");
 }

You are calling Serial.print() from within an ISR. Interrupts are disabled within the ISR but Serial.print() uses them. Set a flag within the ISR and then within the loop check the flag status, print results and clear the flag.

cattledog:
You are calling Serial.print() from within an ISR. Interrupts are disabled within the ISR but Serial.print() uses them. Set a flag within the ISR and then within the loop check the flag status, print results and clear the flag.

That makes sense. I keep finding and trying to use code snippets from the 'net, and have found SEVERAL that do a serial print from within an ISR. My guess is that it can be relatively okay to do if things are simple enough and slow enough, or people keep posting code that they don't know is broken yet. :slight_smile:

Thanks, will work on that.

--Donnie

That was it completely. Thanks so much for the tip. Should have read the docs for attachInterrupt() fully!

Not only did the code I found on the 'net (that supposedly worked!) use Serial routines, it also used millis() for debouncing. His code was for a reed switch which needed debouncing whereas I have a hall effect sensor that does not appear to need it, but still. That was TWO things that aren't supposed to be in ISRs. sigh

--Donnie

A very large fraction of the code posted on the web either has serious flaws and/or is essentially useless. Think of it as a challenge!