When getting info from a Hall Effect Transducer

When you are getting data from a Hall Effect Transducer (I'm getting flow rate) why should I stop counting just to do the reporting calculation? Won't it just be based on the best data at that time anyway.

It doesn't seem like it should take long to multiply the counter times some other number. I've read everything I can find on getting the data from a hall effect transducer for flow rate (counting the on/offs via an interrupt). I just can't figure out why they always want to turn off the interrupts during the calculation. The calculation is only one line with the possibility of one millis() call if you want rate instead of total flow; that just doesn't seem like it will take very long.

Thanks for any thoughts on this subject.

I just can't figure out why they always want to turn off the interrupts during the calculation.

A guess without seeing the code that does this is that they are turned off during a calculation that involves manipulation of more than one byte, such as an int or larger data type.

Imagine what would happen if the processor were part way through such a calculation and an interrupt occurred that caused the values being used in the calculation being changed.

Suppose your interrupt was incrementing an int size variable (0 to 65535) and the current count was 255, when a new pulse arrived the ISR would add 1 to to the current value causing the the low byte to roll over to 0, but another interrupt happens before the high byte is incremented from 0 to 1, then your count would be 0 instead of 256. Now imagine your variable was a long (4 bytes), there would be 3 chances for another interrupt to occur before the variable was fully updated.

I was hoping that the actual code wouldn't really be an issue to answer, I understand UKHeliBob's answer but I just find it hard to believe that the short time it would take to make the calculation would cause an issue. Here is an example piece of code (not mine) that shows what most people do.

// reading liquid flow rate using Seeeduino and Water Flow Sensor from Seeedstudio.com
// Code adapted by Charles Gantt from PC Fan RPM code written by Crenn @thebestcasescenario.com
// http:/themakersworkbench.com http://thebestcasescenario.com http://seeedstudio.com
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;
int hallsensor = 2; //The pin location of the sensor
void rpm () //This is the function that the interupt calls
{
NbTopsFan++; //This function measures the rising and falling edge of the
hall effect sensors signal
}
// The setup() method runs once, when the sketch starts
void setup() //
{
pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
Serial.begin(9600); //This is the setup function where the serial port is
initialised,
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop ()
{
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
sei(); //Enables interrupts
delay (1000); //Wait 1 second
cli(); //Disable interrupts
Calc = (NbTopsFan * 60 / 5.5); //(Pulse frequency x 60) / 5.5Q, = flow rate
in L/hour
Serial.print (Calc, DEC); //Prints the number calculated above
Serial.print (" L/hour\r\n"); //P

I'm trying to build a library (object) that can do the heavy (OK, not that heavy) lifting as an object. I wanted to be able to start and stop the totalizer (the total amount of fluid) by calling methods when I wanted to start and stop. I was fine stopping the interrupts while I returned this data, as there was no interesting data during that calculation anyway. But I would like to intermittently give the flow rate. It doesn't have to be super accurate so I was thinking of not turning off the interrupt so that the total volume over the long haul would not be effected.

I'm happy to share what I've written to date, but it's a .h and .cpp, and I think the important idea is not in the code but in the concept of not stopping counting the interrupts to give an idea of the flow rate in the middle of a valve being open.

Any thoughts would be greatly appreciated!!!

Cheers!!

So it sounds like the problem would be that if the interrupt happened during accessing the counter, part of the number would be read, but when the calculation resumed the part of the counter that would next be read would make the counter be a really weird number?

I have to say that does make some sense!!!

So I have to make a decision; am I more worried about a possibility of an occasional weird flow rate result or missing a click on the counter for the total amount of fluid? Does that sum up the collective thoughts?

THANKS!!!!

I just find it hard to believe that the short time it would take to make the calculation would cause an issue.

The whole point of an interrupt is that it could happen at [u]any[/u] time.

Your ISR should look something like:

void rpm()
{
   nointerrupts();
   NbTopsFan++;
   interrupts();
}

And do the calculating and printing outside of the ISR, the ISR should be as brief and quick as possible.

   nointerrupts();

Interrupts are automatically disabled when in an ISR

void rpm()
{
  anInterruptOccured = true;
}

Then deal with it outside of the ISR

mhessel: I was hoping that the actual code wouldn't really be an issue to answer

When in programming is the actual code ever not the issue?

The term that concisely describes the issue is Atomic. On an 8-bit machine accesses to 16 (and 32) bit integers are not atomic. So, an interrupt can disrupt it before finished.

mhessel: // reading liquid flow rate using Seeeduino and Water Flow Sensor from Seeedstudio.com // Code adapted by Charles Gantt from PC Fan RPM code written by Crenn @thebestcasescenario.com // http:/themakersworkbench.com http://thebestcasescenario.com http://seeedstudio.com volatile int NbTopsFan; //measuring the rising edges of the signal int Calc; int hallsensor = 2; //The pin location of the sensor void rpm () //This is the function that the interupt calls { NbTopsFan++; //This function measures the rising and falling edge of the hall effect sensors signal } // The setup() method runs once, when the sketch starts void setup() // { pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input Serial.begin(9600); //This is the setup function where the serial port is initialised, attachInterrupt(0, rpm, RISING); //and the interrupt is attached } // the loop() method runs over and over again, // as long as the Arduino has power void loop () { NbTopsFan = 0; //Set NbTops to 0 ready for calculations sei(); //Enables interrupts delay (1000); //Wait 1 second cli(); //Disable interrupts Calc = (NbTopsFan * 60 / 5.5); //(Pulse frequency x 60) / 5.5Q, = flow rate in L/hour Serial.print (Calc, DEC); //Prints the number calculated above Serial.print (" L/hour\r\n"); //P

The above code is no good. First, because it does too much (including Serial.print) while interrupts are disabled. Second, using delay() in loop() at the same time you’re using interrupts for real-time processing is just dumb. It should look more like this:

volatile unsigned int NbTopsFan = 0;
const int hallsensor = 2;
unsigned long previousMillis;
const unsigned long measurementPeriod = 1000;

void setup() {
  /*
  .
  . Other setup() stuff goes here
  .
  */
  
  previousMillis = millis();
  attachInterrupt(digitalPinToInterrupt(hallsensor), rpm, RISING);
}

void rpm () {
  NbTopsFan++;
}

void loop() {
  unsigned int localCount;
  unsigned long elapsedTime;

  elapsedTime = millis()-previousMillis;
  if (elapsedTime >= measurementPeriod) {
    noInterrupts();
    localCount = NbTopsFan;
    NbTopsFan = 0;
    interrupts();
    previousMillis += measurementPeriod;

    /*  Here is where you do processing of measurement using localCount and elapsedTime 
     *  Interrupts are enabled -- won't miss any pulses
     */
  }
}

Finally, disabling interrupts does not prevent the event from being registered, it simply prevents the ISR from being called. As soon as interrupts are re-enabled, the ISR will fire. So, unless you get two or more pulses in the few microseconds that interrupts are disabled, you won’t miss any of them. If you do, then you’re measuring one hellacious high RPM!!!