Arduino Flowmeter

Thanks to Eric Rosenthal, Teague Labs, and Koolance, I have a handy fluid flow meter, that is cheap, flexible, and hopefully reliable.

Starting with Teague’s DIY Arduino Watermeter, I’ve made some modifications to the code to compensate for the fact that I’m not using a Yellowjacket Arduino with WiFi, and the need to preserve precious digital I/O lines for actual I/O, and not use them as ground lines.

And more importantly, I have found and solved a significant problem in their implementation: if the wheel in the Koolance meter comes to rest with the magnet close to the Hall Effect sensor, the sensor will be stuck ‘on’—and read as though it is continuously spinning.  This requires a double-latching arrangement, to detect the spinning wheel by picking up first a HIGH signal (magnet) then a LOW signal (no magnet).

Latching Code (Arduino):

//latching arrangement for pin A
//must receive signal then no signal to indicate spin
int signalA = digitalRead(FLOW_PIN_A);
//detects tachometer signal, flow pin goes high every time the magnet spins past the sensor NOTE: must be integer
if(signalA==1){
latchA1=true;
//set first latch
}
if(signalA==0){
latchA2=true;
//set second latch
}
if(latchA1==true and latchA2==true){  //if both latches are enabled, increment counters
countA++;
totalCount++;
//reset latches
latchA1 = false;
latchA2=false;
}

Full Code (Arduino):

This is set up for two meters, and can be expanded to more, or easily adapted to only read one flowmeter.

inline void digitalInputWithPullup(byte pin, boolean b) {  //enables pullups
  pinMode(pin, INPUT);
  digitalWrite(pin, b?HIGH:LOW);
}

#define FLOW_PIN_A 2
#define FLOW_PIN_B 3
//#define FLOW_PIN_X_GND Y //if you want to use a digital IO pin as a ground, enable this line, and modify X and Y

unsigned long totalCount = 0;
unsigned long previousCount = 0; //used for interlocking the counter 

unsigned long windowCountA=0;

//storage variable for the timer
unsigned long previousMillis=0;
int interval=1000; //in milliseconds

//counters for each flowmeter
unsigned long countA = 0;
//latches so the counter doesn't get stuck counting if the magnet stays next to the sensor
boolean latchA1 = false;
boolean latchA2 = false;

unsigned long countB = 0;
boolean latchB1 = false;
boolean latchB2 = false;

void setup()
{
  Serial.begin(19200);
  digitalInputWithPullup(FLOW_PIN_A, true);
  digitalInputWithPullup(FLOW_PIN_B, true);
//  pinMode(FLOW_PIN_X_GND, OUTPUT);  //for using digital I/O pins as ground lines
//  digitalWrite(FLOW_PIN_X_GND, LOW); 
}

void loop(){

//latching arrangement pin A: must receive signal then no signal to indicate spin
  int signalA = digitalRead(FLOW_PIN_A); //detects tachometer signal, flow pin goes high every time the magnet spins past the sensor. NOTE: must be int.
  if(signalA==1){
    latchA1=true;
  }
  if(signalA==0){
    latchA2=true;
  }
  if(latchA1==true and latchA2==true){
    windowCountA++; //increment window counter (counts/unit time)
    countA++; //cumulative count for flowmeter A
    totalCount++; //total count on all meters
    //reset latches
    latchA1=false;
    latchA2=false;
  }

//latching arrangement pin B
  int signalB = digitalRead(FLOW_PIN_B);
  if(signalB==1){
    latchB1=true;
  }
  if(signalB==0){
    latchB2=true;
  }
  if(latchB1==true and latchB2==true){
    countB++;
    totalCount++;
    latchB1=false;
    latchB2=false;
  }

/*
//debugging code to see if signals are present (will display a 1 if there is signal)
Serial.print(signalA);
Serial.print("|");
Serial.println(signalB);
*/

//cumulative totals output
  if (totalCount > previousCount){
    Serial.print(countA);
    Serial.print(" | ");
    Serial.print(countB);
    Serial.print(" || ");
    Serial.println(totalCount);
    previousCount = totalCount; //stores L<-R, updating previousCount so it recycles
  }

/*  
//window counters
  unsigned long currentMillis = millis(); //set storage variable currentMillis to current time
  if (currentMillis - previousMillis > interval) { //if within the rolling window [interval]
    previousMillis = currentMillis;     //save last time the clock updated in previousMillis
    Serial.print(currentMillis); //timestamp
    Serial.print(" | ");
    Serial.println(windowCountA); //count of 'clicks' within the window
    windowCountA=0; //reset window counter, cumulative counters unaffected.
  }
*/

}//end loop
Advertisements

11 thoughts on “Arduino Flowmeter

  1. Pingback: The measure of the (washing) machine « DaveBMiller

  2. Hi,

    Would you mind telling me how you interfaced with the flowmeter, I am trying to do something similar, for example, are you supplying it with 6v or will it take more than that?

    Thanks,

    Matt

    • The flowmeters connect to the Arduino board with one wire to ground, and the other to a digital I/O pin set as a digital input with pullup:

      void digitalInputWithPullup(byte pin, boolean b) {
      pinMode(pin, INPUT);
      digitalWrite(pin, b?HIGH:LOW); // if b is true, set that pin HIGH (+5V), if b is false, set that pin LOW (0V)
      }

      void setup(){

      //enable pullups for the flow pins
      digitalInputWithPullup(FLOW_PIN_A, true); //must set the pullup boolean to true to enable the pullup

      //rest of setup
      }

      what you’re doing there is setting the digital pin to HIGH (+5V) then detecting when it is shorted to ground (the hall effect sensor is activated by the magnet in the flowmeter).

  3. Cheers Dave, really useful. Did you also supply +6v and -6v to the flowmeter separately or is that not necessary, i.e. just for the led etc? I am making a garden watering device and am aiming to track how much water it is using.

    Thanks again,

    Matt

  4. The Koolance FM17N flowmeter does not need any other power, just one wire to ground, the other to the I/O configured as an input with pullup (+5V). More than 5V on one of the digital I/O pins on an Arduino will burn it out.

    The Arduino needs to be powered (either by USB or with a DC power supply).

  5. Hello,

    I’m very new with Arduino. I wonder if we could also pick this code and make energy measurements (enthalpy). We will need two more temperature sensors and basic calculation. With this we can measure the about of energy passing in a pipe for air conditioning. the final calculation would be: Q (kW) = m (flowmeter) * cp (water constant) * (T2 – T1).

    The T1 and T2 sensors would be the temperatur before and after the counter. By that we would have energy measurement!

    Can anyone help with the code? Thank you. Miguel

  6. The Koolance flow meter uses a read switch not a Hall effect sensor. Also consider attaching the meter to one of the interrupts on the Arduino and configure using FALLING, to avoid the latching problem.

  7. Nice project. Thanks for sharing.

    I was about to give you a hint to the interrupt as well, but someone was faster. However, before I learned about the interrupt function, which is much simpler for one or two meters, I made your code a little more pretty (and faster) by avoiding necessary statements and by using functions. Maybe you or anyone who is working on a similar project can use it. The code reads two flow meter (but can be used with as many digitals pins you have) and then calculates a frequency that I use somewhere else (its not the complete code). It’s easy to adapt and the void loop is MUCH MUCH more organized and easier to understand (3 lines of code…).

    //constants———————————————————————
    const int FLOW_PIN = 2;
    const int INTERVAL = 1000;

    //declaration——————————————————————-
    void detectFlowmeterRotation(int flow_pin);
    void calculateFlowmeterFrequency();
    void printInfoToSerial();

    boolean latch1_, latch2_ = false;

    unsigned int window_count_ = 0;
    unsigned long total_count_ = 0;

    unsigned long current_millis_ = 0;
    unsigned int current_frequency_ = 0;

    //——————————————————————————
    void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);
    }

    //——————————————————————————
    void loop() {
    detectFlowmeterRotation(FLOW_PIN);
    calculateFlowmeterFrequency();
    printInfoToSerial();
    }

    //definition ——————————————————————-
    void detectFlowmeterRotation(int flow_pin){
    if(digitalRead(flow_pin))
    latch1_=true;
    if(!digitalRead(flow_pin))
    latch2_=true;

    if(latch1_ && latch2_){//only true after a rotation
    latch1_ = false;
    latch2_ = false;
    window_count_++;
    total_count_++;
    }
    }

    void calculateFlowmeterFrequency(){
    static unsigned long previous_millis_;

    if (millis() – previous_millis_ > INTERVAL) { //if within the rolling window INTERVAL
    previous_millis_ = millis(); //save last time the clock updated in previous_millis_
    current_frequency_ = window_count_ * (1000/INTERVAL);
    window_count_ = 0; //reset window counter, cumulative counters unaffected.
    }
    }

    void printInfoToSerial(){
    static unsigned long previous_millis_;

    if (millis() – previous_millis_ > INTERVAL) { //if within the rolling window INTERVAL
    previous_millis_ = millis(); //save last time the clock updated in previous_millis_
    Serial.print(“total_count_: “);
    Serial.print(total_count_);
    Serial.print(” | “);
    Serial.print(“window_count_: “);
    Serial.print(current_frequency_);
    Serial.println();
    }
    }

  8. Dave,
    Thanks for putting this on the web, I’m slowly building a MPG /KPL meter for my 1980 Diesel Rabbit, I’m going to try using a pair of Futurelec FLOWFUEL30L0 sensors one in the input line (supply) of the Injection pump & 1 in the return line to the fuel tank. Subtract the return reading from the supply reading should give the actual consumption in Gallons or Liters, with a clock input you could get consumption by the hour. Then use a speedometer sensor input for miles /kilometers which would be divided by the fuel consumption for the period to give you a MPG or KPL reading.
    Bill Higdon

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s