Running Total calculated from flow rate

I have a sensor that will tell me the flow rate of a liquid using a hall effect sensor and propeller.

I’d like to also display the total liquid “processed”.

I thought of simply keeping time and dividing it by the flow rate. The problem is if the flow rate is constantly changing that wont be accurate.

Any thoughts on how to attack this?

heres the current code.

// 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 / 7.5); //(Pulse frequency x 60) / 7.5Q, = flow rate in L/hour
  Serial.print (Calc, DEC); //Prints the number calculated above
  Serial.print (" L/hour\r\n"); //Prints "L/hour" and returns a  new line
}

using this sensor: http://www.seeedstudio.com/depot/g12-water-flow-sensor-p-635.html?cPath=144_151

hmm some more thinking and I came up with this:

totaldispensed += (Calc / 3600);
  Serial.print ("total dispensed: ");
  Serial.println (totaldispensed);

code doesnt work but I think the field types are different or something so I have to deal with that.
any better ideas welcome.

To get the total amount you need to integrate the flow rate over time.

Measure the flow rate. Measure the elapsed time since the previous flow measurement.Multiple the flow rate by the elapsed time to get the amount that flowed in that time interval. Add that to your running total.

You want the measurement interval to be relatively small, but not so small that the resolution of your time measurement or flow rate measurement become significant. Sampling once a second would probably be reasonable. Sampling once a millisecond or once a minute probably wouldn’t.

Well this seems to work. I need to hook it up to a pump and see if the values are anywhere near accurate.
This keeps a running total and displays it on a sparkfun LCD

// 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
#include "SparkSoftLCD.h"
#define LCD_TX 3
SparkSoftLCD lcd = SparkSoftLCD(LCD_TX);
int incomingByte = -1;
int val = 0; 
char code[10]; 
int bytesread = 0;
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;  
int hallsensor = 2;    //The pin location of the sensor
float totaldispensed;
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

   // setup lcd
   
 pinMode(LCD_TX, OUTPUT);
 lcd.begin(9600);
 lcd.clear();
 Serial.begin(9600);
   // hidden cursor
 lcd.cursor(0);
}
// 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
   lcd.clear();
    
      // block-style blinking cursor
    lcd.cursor(0);
    
  Calc = (NbTopsFan * 60 / 7.5); //(Pulse frequency x 60) / 7.5Q, = flow rate in L/hour
  lcd.print (Calc, DEC); //Prints the number calculated above
  lcd.print (" L/hour"); //Prints "L/hour" and returns a  new line
 lcd.cursorTo(2,1);
 totaldispensed +=((float)Calc / 3600);
  lcd.print ("total: ");
  
  
int intValue = (int)totaldispensed; // convert float PHValue to tricky int combination
  float diffValue = totaldispensed - (float)intValue;
  int anotherIntValue = (int)(diffValue * 1000.0);
  
  
  lcd.print (intValue);
  lcd.print (".");
  lcd.print (anotherIntValue);
  lcd.print ("L");
  
}

PeterH:
To get the total amount you need to integrate the flow rate over time.

Measure the flow rate. Measure the elapsed time since the previous flow measurement.Multiple the flow rate by the elapsed time to get the amount that flowed in that time interval. Add that to your running total.

You want the measurement interval to be relatively small, but not so small that the resolution of your time measurement or flow rate measurement become significant. Sampling once a second would probably be reasonable. Sampling once a millisecond or once a minute probably wouldn't.

Yup its sampling using a 1 second interrupt and looping and im including the total in the loop. nothing else is happening in the loop other than the display.
Now what I dont know is if I add a bunch of "stuff" that happens outside the 1 second interrupt how badly ill start drifting from accurate.

My only other plans are to add button presses and a relay. So you can for example enter 20 and hit go and it turns on a pump for 20L.

I wouldn't use an interrupt for that. Just use the technique described in the 'blink without delay' example sketch to run your code once per second.

when integrating the sum values become larger and you might consider using unsigned longs for

volatile int NbTopsFan; //measuring the rising edges of the signal

An int wraps at 32767 pulses
An unsigned int at 65535
An unsigned long at 4 billion++ pulses

An unsigned long has 10 digits of precision where floats have around 7 d.o.p.

robtillaart:
when integrating the sum values become larger and you might consider using unsigned longs for

volatile int NbTopsFan; //measuring the rising edges of the signal

An int wraps at 32767 pulses
An unsigned int at 65535
An unsigned long at 4 billion++ pulses

An unsigned long has 10 digits of precision where floats have around 7 d.o.p.

probably why when I got home from dinner the total had creeped up even though there was no flow.
Ill give your way a shot.
thanks!

totaldispensed += (Calc / 3600);
  Serial.print ("total dispensed: ");
  Serial.println (totaldispensed);

as Calc is an int the value of Calc/3600 is also an int and if Calc <3600 the value will be 0.

You can divide by 3600.0 to force floating math.

PeterH, you say;

I wouldn't use an interrupt for that. Just use the technique described in the 'blink without delay' example sketch to run your code once per second.

I would disagree with this statement, as using an interrupt potentially can keep accumulating totals far more accurate.
To simply rely on some timer checking, say in the main loop, I say you run the risk of not getting sensor data input and or doing the calculations needed at the required time, especially if the program gets caught up being busy somewhere else at that point in time. It needs careful attention that that this section of code will run and I think using an interrupt just makes this process an independent process and therefor inherently more reliable and accurate data.
I am not saying you can not do it without interrupt, just that it needs good program structure.

Paul

rockwallaby:
To simply rely on some timer checking, say in the main loop, I say you run the risk of not getting sensor data input and or doing the calculations needed at the required time, especially if the program gets caught up being busy somewhere else at that point in time. It needs careful attention that that this section of code will run and I think using an interrupt just makes this process an independent process and therefor inherently more reliable and accurate data.

You don't need to run the scheduled functions on an interrupt. In fact if you did, you would run the risk that this interrupt interfered with the pulse counting.

All you need to do is schedule the code to read the pulse count and calculate the speed. The calculation is not time-critical and there is no need to carry it out in real time as long as it happens at about the desired frequency. The calculation is completely independent of the arrival of additional pulses, and of course you would code it to do the calculation based on when it actually ran, not when it was scheduled to be run.