Frequency measurement with hall sensor

Hi everyone,

I'm trying to make simple frequency measurement with my arduino. Everytime digital pin 3 goes to LOW the magnet attached to the rotating shaft passed by the hall sensor.

The problem is that i have never coded in C++ and i'm probably making a lot of errors, but right now i'm stuck upon "expected unqualified-id before string constant". The error is given at the line " Void ISR()..."

unsigned long timer;
unsigned long prevtimer;
unsigned long deltat;
unsigned long frequency;
void setup() {
pinMode(3,INPUT);
Serial.begin(9600);
timer=0;
prevtimer=0;
deltat=0;
frequency=0;
attachInterrupt(digitalPinToInterrupt(3),ISR,LOW);
}

void loop() {
  if deltat!=0{
    frequency=1/deltat;
  }
  Serial.println(frequency);
  delay (500);
  
  
}

void ISR() {
  timer=millis();
  deltat=timer-prevtimer;
  prevtimer=timer;
}

any ideas?

Thanks a lot and sorry if it's a really dumb question.

There were many problems with the code.

  1. failure to use "volatile" with a globally defined variable used in an interrupt

  2. incorrect if statement format

  3. integer divide: 1/deltat will always be zero, if deltat is > 1

  4. in my Arduino IDE, digitalPinToInterrupt() seems not to defined, so I substituted interrupt #1 for pin 3.

  5. I try to avoid using keywords like ISR (they might be defined elsewhere)

  6. I did not analyze the logic and I have some doubt that it will work -- not sure why you would want to use delay(500)

Try this (untested):

unsigned long timer;
unsigned long prevtimer;
volatile unsigned long deltat;
float frequency;

void setup() {
  pinMode(3,INPUT);
  Serial.begin(9600);
  timer=0;
  prevtimer=0;
  deltat=0;
  frequency=0;
  attachInterrupt(1,cal_delta,LOW);
}

void loop() {

  if (deltat!=0) frequency=1.0/deltat; //force floating point divide

  Serial.println(frequency);
  delay (500);


}

void cal_delta() {
  timer=millis();
  deltat=timer-prevtimer;
  prevtimer=timer;
}

Hi Jeremy,

Thanks a lot! I was arleady expecting a lot of troubles, since i've never coded in C++ and only coded in python before.

I'm going to try your code this evening, I just have a few questions about it.

  1. You call deltat a volatile unsigned long, is that because it's used inside of the subfunction and in the main loop?

  2. I got the digitalPinToInterrupt() straight from the page with an explanation about attachinterrupt(), i'm not really sure what it does exactly either :). But i don't understand your code a this point you change that to a 1, so you're looking for an interrupt at pin 1 but earlier you stated that pin 3 is your input pin?

  3. the delay is to prevent my log window from being spammed like crazy.

Thanks

A common approach is to use the interrupt facility. This applies to tachometers, flow meters, and probably what you are doing. Google jaycar freetronics flow

Hi again,

I tested it and made a small adaptation to your code, i put the pin to interrupt to pin 2, that seems to be the only working pin for interrupts on my arduino. Right now he's calling cal_deltat but he won't go into the if loop in the main loop.

I can even print deltat in the main loop and it print's something greater then 0 but still he won't go into the if loop. Here's the current code

unsigned long timer;
unsigned long prevtimer;
volatile unsigned long deltat;
float frequency;

void setup() {
 pinMode(2,INPUT);
 Serial.begin(9600);
 timer=0;
 prevtimer=0;
 deltat=0;
 frequency=0.0;
 attachInterrupt(digitalPinToInterrupt(2),cal_deltat,RISING);
}

void loop() {
 if (deltat>0.0)    Serial.println(deltat);//frequency=1.0/deltat; //1.0 for float division
 
 Serial.println(1.0/deltat);
 delay (500);
 
 
}

void cal_deltat() {
 timer=millis();
 deltat=timer-prevtimer;
 prevtimer=timer;
}

On the Arduino Uno or similar, digital pin 2 corresponds to interrupt #0. Digital pin 3 corresponds to interrupt #1. You have both possibilities, but your code has to be consistent.

Any variables shared between interrupts and other parts of the program must be declared volatile.

he won't go into the if loop

I don't know what this means. There is no "if loop" in the program.

Hi,

I meant the if statement, if (deltat>0.0)...

But nevermind i reuploaded it and now it works fine :slight_smile: Thanks for all the help!