Go Down

Topic: Converting flow meter to output in gallons instead of liters (Read 2574 times) previous topic - next topic


I'm trying to put together a setup to control the amount of water to put into kettles. I'm using a water flow meter (Specifically this one) that reads 450 pulses per liter (Flow rate pulse characteristics: Frequency (Hz) = 7.5 * Flow rate (L/min)) and the code I am trying to use is from http://www.practicalarduino.com/projects/water-flow-gauge

For now I have it setup to display both Liters and Gallons. The issue I'm having is figuring out how to convert the numbers from liters to gallons. It isn't measuring anything even close to correct for the gallons (assuming the liters is correct for my sensor).

Code: [Select]

* Water Flow Gauge
* Uses a hall-effect flow sensor to measure the rate of water flow and
* output it via the serial connection once per second. The hall-effect
* sensor connects to pin 2 and uses interrupt 0, and an LED on pin 13
* pulses with each interrupt. Two volume counters and current flow rate
* are also displayed on a 2-line by 16-character LCD module, and the
* accumulated totals are stored in non-volatile memory to allow them to
* continue incrementing after the device is reset or is power-cycled.
* Two counter-reset buttons are provided to reset the two accumulating
* counters. This allows one counter to be left accumulating indefinitely
* as a "total" flow volume, while the other can be reset regularly to
* provide a counter for specific events such as having a shower, running
* an irrigation system, or filling a washing machine.
* Copyright 2009 Jonathan Oxer <jon@oxer.com.au>
* Copyright 2009 Hugh Blemings <hugh@blemings.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. http://www.gnu.org/licenses/
* www.practicalarduino.com/projects/water-flow-gauge
1239.4L 8073.4L
// 3.78541 = Liters in a gallon

#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7,8,9,10,11,12);

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

volatile byte pulseCount;
unsigned long oldTime;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;
float calibrationFactorGallons = 4.5;  //4.755105;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitresA;
unsigned long totalMilliLitresB;

float flowRateGallons;
unsigned int flowGallons;
unsigned long totalGallonsA;
unsigned long totalGallonsB;
float literToGallons = 3.78541;

void setup()
  // 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;
  totalMilliLitresA = 0;
  totalMilliLitresB = 0;
  oldTime           = 0;
  flowRateGallons  = 0.0;
  flowGallons      = 0;
  totalGallonsA    = 0;
  totalGallonsB    = 0;
  // The Hall-effect sensor is connected to pin 3 which uses interrupt 1.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

void loop()

  if((millis() - oldTime) > 1000)    // Only process counters once per second
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    flowRateGallons = ((literToGallons / (millis() - oldTime)) * pulseCount) / calibrationFactorGallons;
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    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 multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    flowGallons = (flowRateGallons / 60) * literToGallons;
    totalGallonsA += flowGallons;
    //totalGallonsB += flowGallons;
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitresA += flowMilliLitres;
    totalMilliLitresB += flowMilliLitres;
    // During testing it can be useful to output the literal pulse count value so you
    // can compare that and the calculated flow rate against the data sheets for the
    // flow sensor. Uncomment the following two lines to display the count value.
    lcd.setCursor(10, 3);
    lcd.print(pulseCount, DEC);
    lcd.print("    ");
    //Serial.print("  ");
    // Write the calculated value to the serial port. Because we want to output a
    // floating point value and print() can't handle floats we have to do some trickery
    // to output the whole number part, then a decimal point, then the fractional part.
    unsigned int frac;
    unsigned int gfrac;   
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("Flow: ");
    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.print(" L");
    lcd.setCursor(0, 1);
    lcd.print(int(totalMilliLitresA / 1000));
    lcd.setCursor(8, 1);
    lcd.print(int(totalMilliLitresB / 1000));

//Output in gallons
    lcd.setCursor(0, 2);
    lcd.print("                ");
    lcd.setCursor(6, 2);
    if(int(flowRateGallons) < 10)
      lcd.print(" ");
    lcd.print((float)flowRateGallons);   // Print the integer part of the variable
    //lcd.print('.');             // Print the decimal point
    //lcd.print(gfrac, DEC) ;      // Print the fractional part of the variable
    lcd.print(" G");
    lcd.setCursor(0, 3);
    lcd.print(float(totalGallonsA / literToGallons));
    lcd.print(" G  ");
    // lcd.setCursor(6, 3);
    // lcd.print(int(totalGallonsB / 0.26417));
    // lcd.print("G");

    // 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


You've got flowRate as a float variable, so why don't you just divide it by the number of liters per gallon to get it in gallons instead of liters?


That seems to work. Thanks, It's not counting the total value for gallons but I just need to keep looking into that.


You've got way too much stuff going on with the interrupt handler detached. All that you should be doing is making a copy of the variables that the interrupt handler modifies. Do all the processing AFTER reattaching the interrupt handler.
The art of getting good answers lies in asking good questions.

Go Up