Flow sensor - rising edge detection using interrupt not working

I'm using a Gems flow sensor (173940-C) to measure the amount of water flowing through a drinking fountain

I'm using 10k pull up resistor between the signal pin and the 5v pin

The according to the data sheet 1 pulse = 1 ml of water for this particular model

I have confirmed the sensor is working by simply displaying the digital pin's state and saving the data using Cool term which I later then counted in excel and for a 500ml bottle I get approx 500 pulses

The issue is, when i try to count the pulses using a rising edge Interrupt within Arduino, I dont get the same amount of pulses, its always a lot higher, I suspect that the interrupt is being triggered too often or incorrectly, does anyone know why this could be?

Thanks in advance

#define debugSerial Serial

const int flowPin = 2;    //This is the input pin on the Arduino
volatile unsigned int PulseCount = 0; //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.
unsigned long currentTime ;
unsigned long StartTime = 0;

void setup() {

  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(flowPin, INPUT);           //Sets the pin as an input
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2), Flow, FALLING);  //Configures interrupt 0 (pin 2 on the Arduino Uno) to run the function "Flow"
}
void loop() {

  currentTime = millis();
  if (currentTime >= (StartTime + 1000)) //occurs every 1 seconds - take a reading
  {
    Serial.print ("Pulse Count: ");
    Serial.println (PulseCount);
    StartTime = millis();
  }
}

void Flow() {
  PulseCount++; //Every time this function is called, increment "PulseCount" by 1
}

If you're triggering on a rising input, shouldn't your resistor be configured as a pull-down instead?

wildbill:
If you're triggering on a rising input, shouldn't your resistor be configured as a pull-down instead?

Yhhh I'll change that now however that still doesnt resolve the issue I'm having, the pulse count is out by a factor of approx two.

I have noticed that the method described in the original post:

"I have confirmed the sensor is working by simply displaying the digital pin's state and saving the data using Cool term which I later then counted in excel and for a 500ml bottle I get approx 500 pulses"

is polling as I'm simply using digitalread(2) to constantly print the pin state

whereas the method I'm trying to implement is ISR, why would polling give me the correct value but not ISR?

I’m attempting to read the output of a flow sensor, when I use an interrupt to detect a pulse and increment a variable, the output isnt giving the expected answer however when I poll the pin , export the data using cool term and count the pulses, I get the correct value why would this be??

code for interrupt:

#define debugSerial Serial

const int flowPin = 2;    //This is the input pin on the Arduino
volatile unsigned int PulseCount = 0; //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.
unsigned long currentTime ;
unsigned long StartTime = 0;

void setup() {

  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(flowPin, INPUT);           //Sets the pin as an input
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2), Flow, FALLING);  //Configures interrupt 0 (pin 2 on the Arduino Uno) to run the function "Flow"
}
void loop() {

  currentTime = millis();
  if (currentTime >= (StartTime + 1000)) //occurs every 1 seconds - take a reading
  {
    Serial.print ("Pulse Count: ");
    Serial.println (PulseCount);
    StartTime = millis();
  }
}

void Flow() {
  PulseCount++; //Every time this function is called, increment "PulseCount" by 1
}

code for polling:

void setup() {

  pinMode(2, INPUT);           //Sets the pin as an input
  Serial.begin(9600);
}
 
void loop() {
  Serial.println(digitalRead(2));
}

Switch might be bouncing. You don't really give any information on how the one is wrong, is it too many or too few. But I bet it is too many. The serial print in the second probably slows things down enough that the switch bounce gets missed.

if (currentTime >= (StartTime + 1000))

That's a bug. You should rewrite that with subtraction the way it is in the Blink Without Delay example.

If you were polling and printing every pulse, depending on how much text, it's possible that your slow Serial speed may have interfered with your initial test results. Running at 115200 would be safer. Better yet, just count the pulses and print them periodically as you did above.

Have you verified that the part you have is actually a 73940-C?

Delta_G:
Switch might be bouncing. You don't really give any information on how the one is wrong, is it too many or too few. But I bet it is too many. The serial print in the second probably slows things down enough that the switch bounce gets missed.

if (currentTime >= (StartTime + 1000))

That's a bug. You should rewrite that with subtraction the way it is in the Blink Without Delay example.

Sorry I forgot to add more context,

I've got a 10k pull up resistor between the signal pin and the 5v pin which I assume eliminated the floating/debounce issue but maybe I've misunderstood how it works

When I use ISR method, I get too many pulses, near double what I'm expecting

In terms of "if (currentTime >= (StartTime + 1000))" being a bug, could you elaborate a bit more please? I'm happy to switch it to subtraction but I just want to know why.

Thanks

whizz5:
I’ve got a 10k pull up resistor between the signal pin and the 5v pin which I assume eliminated the floating/debounce issue but maybe I’ve misunderstood how it works

The pull-up resistor (why didn’t you use the one built into the chip?) only solves the floating problem. You still have to deal with switch bounce either in software by ignoring any presses that happen within a certain time or by using external circuitry like a capacitor across the switch pins.

whizz5:
When I use ISR method, I get too many pulses, near double what I’m expecting

Yup, it’s bouncing. Google switch bounce or debounce and see what you can learn.

whizz5:
In terms of “if (currentTime >= (StartTime + 1000))” being a bug, could you elaborate a bit more please? I’m happy to switch it to subtraction but I just want to know why.

Thanks

Let’s say the StartTime now is 429496700 Then StartTime + 1000 is going to be 704 (rollover). So before your interval is even up, currentTime is greater than that. So once you get close to the point of millis rollover, your timing loop starts running every time and not timing.

IF you write like this in the same condition:

if(currentTime - StartTime >= 1000)

Now when you do the subtraction the rollover happens in that subtraction math instead and everything is safe. See any of the hundreds of tutorials on Blink Without Delay for more on how that works.

I didnt use the internal pull up resistor as I originally thought that it was the culprit for my bad readings but I'm starting to realise that this is not the case now

Ok I understand bouncing and how it affects a switch or button but my input is a hall effect flow sensor (Gems flow sensor 173940-C) which from my understanding wouldn't be subject to the same issue but I'll look into that now and implement one of the fixes suggested

Thanks for the clarification on the timings, I never even considered roll over

This won't be atomic on an 8-bit processor:

Serial.println (PulseCount);

You should copy PulseCount to a local variable and protect the access by turning interrupts on/off:

noInterrrupts();
localPulseCount = PulseCount;
interrupts();
Serial.println (localPulseCount);

wildbill:
If you were polling and printing every pulse, depending on how much text, it's possible that your slow Serial speed may have interfered with your initial test results. Running at 115200 would be safer. Better yet, just count the pulses and print them periodically as you did above.

Have you verified that the part you have is actually a 73940-C?

I'm confident that the results obtained by polling are accurate as they align with the datasheet (1ml = 1 pulse) and I've been using bottles and cups with known volumes to conduct tests.

I'd rather not use polling because there are other processes I want to run and ultimately I would like to make this a battery powered device and from my understanding, polling is quite power inefficient compared to using an ISR

I can confirm that the sensor is the 73940-C model

Someone suggested that this could be a bounce issue however I thought that was only applicable to buttons and switches, I'm using a hall effect flow sensor so I will have to go away and research some more

whizz5:
but my input is a hall effect flow sensor (Gems flow sensor 173940-C)

An important tidbit of information. Would have been nice if it was in your very first post. Don't you think?

whizz5:
I'm using 10k pull up resistor between the signal pin and the 5v pin

I'm not familiar with this type but, apart from the price, it seems like any other hall effect flow sensor, and they usually connect to Arduino pin 2 via a 10k series resistor - no pull up, no pull down.

gfvalvo:
This won't be atomic on an 8-bit processor:

Serial.println (PulseCount);

You should copy PulseCount to a local variable and protect the access by turning interrupts on/off:

I'm relatively new to a lot of this so I'll look this up now

gfvalvo:
An important tidbit of information. Would have been nice if it was in your very first post. Don't you think?

Looool I did mention I was using a flow sensor but I guess I could have been more explicit

@OP

I have tested your interrupt driven original program using a ~54Hz (555-based) oscillator. You can see the the output of your program in the following screenshot (Fig-1). Why is the output getting count added in every second? It should always be close to ~54 (Fig-2).
scrshot-2.png
Figure-1: Output of the incorrect program

scrshot-3.png
Figure-2: Output after correcting the mistakes of the program

scrshot-2.png

scrshot-3.png

@GolamMostafa

Not too sure what you’ve done but I’ve run the code and didnt have the same issue (see attached screenshot), there’s nothing within the code that adds the pulse count to itself so could you please explain what it is that you’ve “corrected”

Just to clarify I’m running this on a TTN UNO board (based on an Arduino Leonardo)

What @Golam is getting at is that you are still being a bit vague in how these value differ from what you expect. He thinks that maybe you want the number of pulses per second and are seeing that the number of pulses just keeps counting up and up and up. Not sure what he did in the program, but you could accomplish that by simply setting pulseCount back to 0 when you print it (in a critical section of course).

I would like you to note though how he posted his results for everyone to see and explained what we were looking at instead of just calling them "unexpected" and leaving it at that. If you want people to be able to help you, never be shy on the details.

When I use ISR method, I get too many pulses, near double what I'm expecting

What are you expecting, and how have you calibrated the sensor?

Delta_G:
Not sure what he did in the program, but you could accomplish that by simply setting pulseCount back to 0 when you print it (in a critical section of course).

Exactly, this is what I have added with OP's program.