Flow Meter Sensor start and stop detection

Hello,

I'm new to this forum. I've been using the adafruit 1/2" brass flow meter sensor and its code provided. However, has anyone tried to use that code to write start and stop detection for the sensor??

There is a frequency counter that does this application, but i'm trying to get this done for a flow meter sensor. :frowning:

Thanks.

When the frequency is zero, the flow has stopped.

thats true, but when I pull up the serial monitor using the opensource code for the flow meter:

/**********************************************************
This is example code for using the Adafruit liquid flow meters.
Tested and works great with the Adafruit plastic and brass meters
------> http://www.adafruit.com/products/828
------> http://www.adafruit.com/products/833
Connect the red wire to +5V,
the black wire to common ground
and the yellow sensor wire to pin #2
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
**********************************************************/

#include "LiquidCrystal.h"
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

// which pin to use for reading the sensor? can use any pin!
#define FLOWSENSORPIN 2

// count how many pulses!
volatile uint16_t pulses = 0;
// track the state of the pulse pin
volatile uint8_t lastflowpinstate;
// you can try to keep time of how long it is between pulses
volatile uint32_t lastflowratetimer = 0;
// and use that to calculate a flow rate
volatile float flowrate;
// Interrupt is called once a millisecond, looks for any pulses from the sensor!
SIGNAL(TIMER0_COMPA_vect) {
uint8_t x = digitalRead(FLOWSENSORPIN);

if (x == lastflowpinstate) {
lastflowratetimer++;
return; // nothing changed!
}

if (x == HIGH) {
//low to high transition!
pulses++;
}
lastflowpinstate = x;
flowrate = 1000.0;
flowrate /= lastflowratetimer; // in hertz
lastflowratetimer = 0;
}

void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
}
}

void setup() {
Serial.begin(9600);
Serial.print("Flow sensor test!");
lcd.begin(16, 2);

pinMode(FLOWSENSORPIN, INPUT);
digitalWrite(FLOWSENSORPIN, HIGH);
lastflowpinstate = digitalRead(FLOWSENSORPIN);
useInterrupt(true);
}

void loop() // run over and over again
{
lcd.setCursor(0, 0);
lcd.print("Pulses:");
lcd.print(pulses);
lcd.print(" Hz:");
lcd.print(flowrate); //lcd.print(flowrate);

Serial.print("Freq: ", flowrate, "Pulses: ",pulses);

// if a plastic sensor use the following calculation
// Sensor Frequency (Hz) = 7.5 * Q (Liters/min)
// Liters = Q * time elapsed (seconds) / 60 (seconds/minute)
// Liters = (Frequency (Pulses/second) / 7.5) * time elapsed (seconds) / 60
// Liters = Pulses / (7.5 * 60)
float liters = pulses;
liters /= 8.1;
liters -= 6;
liters /= 60.0;

/*
// if a brass sensor use the following calculation
float liters = pulses;
liters /= 8.1;
liters -= 6;
liters /= 60.0;
*/

Serial.print(liters);
Serial.println(" Liters");
lcd.setCursor(0, 1);
lcd.print(liters); lcd.print(" Liters ");

delay(1000);
}

the code keeps running in a loop each second. I'm still new to writing code and I guess what I'm asking is that if i can get this data running only when the flow meter has fluid flowing in the valve and when no fluid is running the data stops running. But right now the loop has it running continuously. I'm trying to use this data and eventually log it

Probably not. If the data stopped running when the fluid is not flowing, how would it know when the fluid starts flowing again?

this open source works when you run the serial monitor function for a frequency counter:

// Frequency timer using input capture unit
// Author: Nick Gammon
// Date: 31 August 2013

// Input: Pin D4 on YUN Bill Gilbert 20141015_13:44 Works

#include “Bridge.h”
#include “Console.h”

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect

ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;

// if just missed an overflow
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
overflowCopy++;

// wait until we noticed last one
if (triggered)
return;

if (first)
{
startTime = (overflowCopy << 16) + timer1CounterValue;
first = false;
return;
}

finishTime = (overflowCopy << 16) + timer1CounterValue;
triggered = true;
TIMSK1 = 0; // no more interrupts for now
} // end of TIMER1_CAPT_vect

void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;

TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don’t get a bogus interrupt
TCNT1 = 0; // Counter to zero
overflowCount = 0; // Therefore no overflows yet

// Timer 1 - counts clock pulses
TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select (rising on D8)
interrupts ();
} // end of prepareForInterrupts

void setup ()
{
// initialize serial communication:
Bridge.begin();
Console.begin();

while (!Console) {
; // wait for Console port to connect.
}
Console.println(“You’re connected to the Console!!!”);
delay(1000);

Console.begin();
Console.println(“Frequency Counter”);
// set up for interrupts
prepareForInterrupts ();
} // end of setup

void loop ()
{
// wait till we have a reading
if (!triggered)
return;

// period is elapsed time
unsigned long elapsedTime = finishTime - startTime;
// frequency is inverse of period, adjusted for clock period
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 nS at 16 MHz

Console.print ("Took: “);
Console.print (elapsedTime);
Console.print (” counts. ");

Console.print ("Frequency: “);
Console.print (freq);
Console.println (” Hz. ");

// so we can read it
delay (500);

prepareForInterrupts ();
} // end of loop}

However, i’m trying to get this type of function to run for a flow meter.

dmusketstem2015:
However, i’m trying to get this type of function to run for a flow meter.

I think you should be a bit more clear about what your problem is, why you think you have one, and what you are really trying to do. Both programmes appear to be for a flow meter, the first because it says it is, the second because it looks like one.

Looking back

But right now the loop has it running continuously. I’m trying to use this data and eventually log it

The loop has to run continuously, that is what loops do. If you want to do something with the data, you include the relevant commands in the loop, and the interrupt keeps counting in the meantime.

/**

  • Water Flow Gauge
  • Uses a hall-effect flow sensor to measure the rate of water flow
  • Copyright 2009 Jonathan Oxer jon@oxer.com.au
  • Copyright 2009 Hugh Blemings hugh@blemings.org
    */

#include <LiquidCrystal_I2C.h>
#include “Wire.h”
#include <SD.h>
#define DS1307_ADDRESS 0x68
LiquidCrystal_I2C lcd(0x27,20,4);

File myFile;
char filename = “00000000.CSV”;
#include “Wire.h”

byte sensorInterrupt = 0; // 0 = pin 2; 1 = pin 3
byte sensorPin = 2; //

// The flow sensor outputs approximately 4.5 Hz/litre/minute of flow.
float calibrationFactor = 9.0;

volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;

int second, minute, hour, weekDay, monthDay, month, year;
int daily, maxflow, yesterday;

void setup()
{
lcd.setCursor (0,0);
lcd.print(“Initializing”);
delay(2000);
lcd.setCursor (0,1);

pinMode(10, OUTPUT);

if (!SD.begin(4))
{
lcd.print(“failed!”);
delay (2000);
return;
}
lcd.print(“init. OK!”);
delay(2000);

lcd.clear();

lcd.setCursor(0, 0);
lcd.print("Flow: ");
lcd.setCursor(11, 0);
lcd.print(“L/min”);

lcd.setCursor(0, 1);
lcd.print("Total: ");
lcd.setCursor(14, 1);
lcd.print(“Litres”);

lcd.setCursor(0, 2);
lcd.print(“daily”);
lcd.setCursor(14, 2);
lcd.print(“Litres”);

// Initialize a serial connection for reporting values to the host

// Set up the pair of counter reset buttons and activate internal pull-up resistors

pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);

pulseCount = 0;
flowRate = 0.0;
flowMilliLitres = 0;
totalMilliLitres = 0;
oldTime = 0;

attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

void loop()
{
GetClock();
if (hour == 6 && minute == 0 && second <2)
{
filewrite();
}

if((millis() - oldTime) > 1000) // Only process counters once per second
{
// Disable the interrupt while calculating flow rate and sending the value to
// the host
detachInterrupt(sensorInterrupt);

flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

oldTime = millis();

// Divide the flow rate in litres/minute by 60 to determine how many litres have
// passed through the sensor in this 1 second interval, then conv. to ml.
flowMilliLitres = (flowRate / 60) * 1000;

// Add the litres passed in this second to the cumulative total
totalMilliLitres += flowMilliLitres;

unsigned int frac;
frac = (flowRate - int(flowRate)) * 10;

lcd.setCursor(6, 0);

if(int(flowRate) < 10)
{
lcd.print(" ");
}
lcd.print((int)flowRate); // Print the integer part of the variable
lcd.print(’.’); // Print the decimal point
lcd.print(frac, DEC) ; // Print the fractional part of the variable
lcd.setCursor(7, 1);
lcd.print(int(totalMilliLitres / 1000));

// Reset the pulse counter so we can start incrementing again
pulseCount = 0;

// Enable the interrupt again now that we’ve finished sending output
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
}

/**

  • Invoked by interrupt0 once per rotation of the hall-effect sensor. Interrupt
  • handlers should be kept as small as possible so they return quickly.
    */
    void pulseCounter()
    {
    // Increment the pulse counter
    pulseCount++;
    }

byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}

void GetClock(){
// Reset the register pointer
Wire.beginTransmission(DS1307_ADDRESS);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);

second = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
weekDay = bcdToDec(Wire.read()); //0-6 → sunday - Saturday
monthDay = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
}

void filewrite() {
daily=totalMilliLitres-yesterday;
yesterday=totalMilliLitres;

myFile = SD.open(filename, FILE_WRITE);//<<<<<<<<<<<<< OPEN
myFile.print(year);
myFile.print(":");
myFile.print(month);
myFile.print(":");
myFile.print(monthDay);
myFile.print(",");

myFile.print(int(daily / 1000));
myFile.print(",");
myFile.println(int(totalMilliLitres / 1000));
myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
}

Please use code tags {/}.

The pulseCounter handler can remember the current time of the impulse. When that time is too far in the past, the flow has stopped.

Hi,
What do you want to get from your flow sensor.
Flowrate/ --yes or no
If there is any flow or not? – yes or no.

The loop has to keep operating so that it can check if the flow has started or not.

The fact that your monitor screen is being updated all the time does not mean that there is or isnt flow.

The Adafruit program prints a value called “flowrate”, if it is zero then no flow.

Does this value =0 when you have no flow?

Tom… :slight_smile:

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html