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:
Pinout [Solder onto LCD shiled is preferred ] :
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++;
}; |
Top Comments