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
}
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.
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.
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.