A updated Flow meter monitor to incorporate a LCD shield, log min and max flow rates.

 

If you want to incorporate some error logging [water loss or burst pipe] see the last blog for setting error flags.

 

LCD Shiled that it will work with:

 

LCD

 

Pinout [Solder onto LCD shiled is preferred ] :

 

pinout

 

Ignore external pull up, we are doing that in software instead

 

 

Header 1

 

/* This script is used to make sense of the output from a hall effect water flow meter and make a note of any problems

 

 

Michael Ratcliffe  Mike@MichaelRatcliffe.com

  

    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.

 

 

    This program is distributed in the hope that it will be useful,

    but WITHOUT ANY WARRANTY; without even the implied warranty of

    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

    GNU General Public License for more details.

 

 

    You should have received a copy of the GNU General Public License

    along with this program.  If not, see <http://www.gnu.org/licenses/>.

  

  

  

  

    Components:

    See main folder for sensor data sheets, required liabaries and extra information: [can be downloaded via www.michaelratcliffe.com]

  

    All power systems should be powerd of DC voltage of below 48v for safter [water is around] 12v is prefferable and cheapest. As always this is a DIY project and done at your own risk.

  

  

    >Arduino Uno

    >Hall Effect Water Flow Meter 5v

    >LCD button Shield [Hobby tronix]

 

 

  

*/

// including some libraries for interfacing with harware

#include <LiquidCrystal.h> //Standard LCD Lbrary

 

 

 

 

 

 

//******************************** User Defined Variables *******************************************************//

 

 

#define Water_pin 2

 

 

/*/####### Meter Specs ####//

Most meters are shipped with a forumla to work out flow rate

F=X*Q

Q=Flow rate in L/min [make sure its in L/min and not L/hr]

F=Frequency

X= variable

To work out click per L  Clicks = 60*X

*/

 

 

float Click_Per_L = 450; // this depends on your flow meter

 

 

 

 

//*********************8* Setting up LCD ************************//

// select the pins used on the LCD panel

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

 

 

// define some values used by the panel and buttons

int lcd_key     = 0;

int adc_key_in  = 0;

int button =0;

#define btnRIGHT  1

#define btnUP     2

#define btnDOWN   3

#define btnLEFT   4

#define btnSELECT 5

#define btnNONE   6

 

 

int Screen =1;

 

 

//used to debounce input button

int buttonLast=0;

 

 

//********************** Some Variables For Loging Min/Max Values ********************************//

float MinFLOW=100;

float MaxFLOW=0;

 

 

 

 

//************************** Just Some basic Definitions used for the Up Time LOgger ************//

long Day=0;

int Hour =0;

int Minute=0;

int Second=0;

int HighMillis=0;

int Rollover=0;

 

 

 

 

//***************************** End Of User Defined Variables **************************************************//

 

 

unsigned long PulseCount=0;  //counter for water meter pulses

unsigned long Current_PulseCount=0; // the one we will be doing maths on

int Last_Reading=0;

int Readings=0;

float Water_Used=0;

float Flow_Rate= 0;

unsigned long Last_Count =0;

 

 

 

 

//**************************** Setup Routine , Runs Once and Sets used pins to correct value *******************//

void setup() {

Serial.begin(9600); // starting Serial Com's

 

//Stoping noise from being a problem, pin is high untill hall sensor pulls it low

pinMode(Water_pin, INPUT);

digitalWrite(Water_pin, HIGH);// saves having an external pullup

    

//External Interrupts: This is what the watr meter pulse count is collected from     

attachInterrupt(0, WaterCounter, FALLING);  //watermeter pulse output connected to pin3

 

//************* Splash Screen *******************//

// Maybe change this to your details to add that finishing touch [max of 16 charictors per line]

 

 

lcd.begin(16, 2);              // start the library

lcd.setCursor(0,0);

delay(1000);

lcd.print("Water Meter          ");

lcd.setCursor(0,1);

delay(1000);

lcd.print("Mike Ratcliffe");

lcd.setCursor(0,1);

delay(1000);

lcd.setCursor(0,1);

lcd.print("Free Software   ");

delay(1000);

lcd.setCursor(0,1);

lcd.print("Mike Ratcliffe");

delay(1000);

lcd.setCursor(0,1);

lcd.print("Free Software   ");

delay(3000);

  lcd.setCursor(0,0);

lcd.print("To Navigate         ");

  lcd.setCursor(0,1);

lcd.print("Use Up-Down     ");

delay(3000);

 

 

 

 

//Clearing LCD SCREEN

lcd.setCursor(0,0);

lcd.print("                                   ");

lcd.setCursor(0,1);

delay(1000);

lcd.print("                                    ");

 

 

 

 

};

 

 

 

//************************************** Main Loop that will continualy run ******************************************//

void loop(){

 

 

//calls uptime function below main loop

uptime();

 

 

 

 

//************** If Statment that will run every second ******************//

            if (Last_Reading!=Second) {

            Last_Reading=Second; //Makes note of the last second

            Readings=1;          //Tell serial there is data to transmit

 

 

            //Turn off interupt while we take a quick note of it and then turn it back on

            detachInterrupt(0); //

            Current_PulseCount=PulseCount; // making note of pulse count

            attachInterrupt(0, WaterCounter, FALLING);  //watermeter pulse output connected to pin3

          

            Flow_Rate=((Current_PulseCount-Last_Count)/Click_Per_L); 

            Water_Used=(1/(Click_Per_L/Current_PulseCount)); //cant recall why I did it this way, maybe to retain float capabilities

          

            Last_Count=Current_PulseCount;                   // Makes a note of the last reading

 

 

                                    };

 

 

 

 

read_LCD_buttons();

LogFlow();

PrintReadings();

 

 

 

 

    

delay(10);

};

//*************************************************END OF LOOP ******************************************************//

 

 

 

 

//******************* Uptime Counter **************************************************//

//WE need an uptime counter to verify our total flow readout is valid

 

 

void uptime(){

//** Making Note of an expected rollover *****//

if(millis()>=3000000000){

HighMillis=1;

 

}

//** Making note of actual rollover **//

if(millis()<=100000&&HighMillis==1){

Rollover++;

HighMillis=0;

}

long secsUp = millis()/1000;

Second = secsUp%60;

Minute = (secsUp/60)%60;

Hour = (secsUp/(60*60))%24;

Day = (Rollover*50)+(secsUp/(60*60*24));  //First portion takes care of a rollover [around 50 days]                 

};

 

 

 

 

//******************************* LOGS Min/MAX Values and Uptime Counter*******************************//

void LogFlow(){

 

  if(Flow_Rate>=MaxFLOW)  MaxFLOW=Flow_Rate;

  if(Flow_Rate<=MinFLOW)  MinFLOW=Flow_Rate;

};

 

 

 

 

 

 

 

 

 

 

 

 

//****************************** Reading LCd Buttons ****************************//

void read_LCD_buttons(){

  adc_key_in = analogRead(0);      // read the value from the sensor

// my buttons when read are centered at these valies: 0, 144, 329, 504, 741

// we add approx 50 to those values and check to see if we are close

if (adc_key_in > 1000)  button =0;

 

 

else if (adc_key_in < 50)   button =1;

else if (adc_key_in < 250)  button =2;

else  if (adc_key_in < 450)  button =3;

else if (adc_key_in < 650)  button =4;

else if (adc_key_in < 850)  button =5;

 

 

 

 

//Second bit stops us changing screen multiple times per input

if(button==2&&buttonLast!=button){

Screen++;

 

 

}

else if (button==3&&buttonLast!=button){

Screen--;

};

 

 

if (Screen>=3) Screen=3;

if(Screen<=1) Screen=1;

 

 

buttonLast=button;

};

 

 

 

 

 

 

 

 

 

 

//**************This Loop Is called From Main Loop- Prints to serial usefull info and updates LCD *************//

void PrintReadings(){

 

 

//No Point updating if there is no new data

if (button>=1||Readings==1) {

  Readings=0;

 

 

//Printing Some Uptime Values

  Serial.print(F("Uptime: ")); // The "F" Portion saves your SRam Space

  Serial.print(Day);

  Serial.print(F("  Days  "));

  Serial.print(Hour);

  Serial.print(F("  Hours  "));

  Serial.print(Minute);

  Serial.print(F("  Minutes  "));

  Serial.print(Second);

  Serial.println(F("  Seconds"));

 

 

//Printing Some Water Flow info

  Serial.print(F("Total Water Used"));

Serial.print(Water_Used);

Serial.println(F(" L"));

Serial.print(F("Current Flow Rate: "));

Serial.print(Flow_Rate);

  Serial.println(F(" L/s"));

 

 

 

                     //First Screen is Total Flow and flowrate

                      if(Screen==1){

                      lcd.setCursor(0,0);

                      lcd.print("Volume:                ");

                      lcd.setCursor(7,0);

                      lcd.print(Water_Used);

                      lcd.setCursor(13,0);

                      lcd.print("L");

                    

                      lcd.setCursor(0,1);

                      lcd.print("FlRate:             ");

                      lcd.setCursor(7,1);

                      lcd.print(Flow_Rate);

                      lcd.setCursor(13,1);

                      lcd.print("L/s");

                      }

 

 

                   

                                           

                      }

                      //Min and Max flowrates

                       else if(Screen==2){

                      lcd.setCursor(0,0);

                      lcd.print("Min:              ");

                       lcd.setCursor(4,0);

                       lcd.print(MinFLOW);

                       lcd.setCursor(13,0);

                       lcd.print("L/s");

                      lcd.setCursor(0,1);

                      lcd.print("Max:               ");

                      lcd.setCursor(4,1);

                      lcd.print(MaxFLOW);

                      lcd.setCursor(13,1);

                      lcd.print("L/s");

                  

                       }

 

 

                       //Printing uptime

                        else if(Screen==3){

                 

                      lcd.setCursor(0,0);

                      lcd.print("Uptime Counter:              ");

                  

                      lcd.setCursor(0,1);

                      lcd.print("                                     ");//Clearing LCD

                      lcd.setCursor(0,1);

                      lcd.print(Day);

                      lcd.setCursor(3,1);

                      lcd.print("Day");

                      lcd.setCursor(8,1);

                      lcd.print(Hour);

                      lcd.setCursor(10,1);

                      lcd.print(":");

                      lcd.setCursor(11,1);

                      lcd.print(Minute);

                      lcd.setCursor(13,1);

                      lcd.print(":");

                      lcd.setCursor(14,1);

                      lcd.print(Second);

                  

                  

                       }

     

 

 

 

};

 

 

 

 

//*************Interupt routine for water meter readings - Runs everytime sensor has a pulse *************//

 

 

void WaterCounter() {

 

   // Increment the pulse counter

  PulseCount++;

 

};