//ComboTempPressFlow
//Portion adopted from: 6-13-2011  Spark Fun Electronics by Nathan Seidle
//Copyright Bob Gabriel 02/15/2024 
//https://lastminuteengineers.com/i2c-lcd-arduino-tutorial/
//SDA -> A4, SCL -> A5
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Include the required Arduino libraries:
#include "OneWire.h"
#include "DallasTemperature.h"
// Define to which pin of the Arduino the 1-Wire bus is connected:
#define ONE_WIRE_BUS 6
// Create a new instance of the oneWire class to communicate with any OneWire device:
OneWire oneWire(ONE_WIRE_BUS);
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x3F for a 16 chars and 2 line display
// Pass the oneWire reference to DallasTemperature library:
// DS18B20 1-Wire digital temperature sensor
DallasTemperature sensors(&oneWire);
int ttlgallons;
int ontime,offtime,duty;
float freq,period;
float prshr = 0.0;
float hi_prshr = 30.0;
float lo_prshr = 30.0;
const int INPUT_PIN = 7;
const int pulse_ip = 7;
const int gallon = 2;
float total = 0;
#define PUMP_LED_PIN 9
#define PUMP_PIN 3    //INTERUPT 
#define FLOW_LED_PIN 10
#define GALLON_LED_PIN 11
volatile byte ledState = LOW;
void setup() {
  pinMode(13, OUTPUT);  //Builtin LED	
  pinMode(pulse_ip,INPUT_PULLUP);  //use internal pullup 
  pinMode(gallon,INPUT_PULLUP); //gallon counter
  pinMode(PUMP_LED_PIN, OUTPUT);
  pinMode(PUMP_PIN, INPUT_PULLUP);
  pinMode(GALLON_LED_PIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(PUMP_PIN), blinkPumpLed, CHANGE);
  attachInterrupt(digitalPinToInterrupt(gallon), countGallon, FALLING);
  pinMode(FLOW_LED_PIN, OUTPUT);
  digitalWrite(PUMP_LED_PIN, LOW);
  Serial.begin(9600);
  sensors.begin();
  
  lcd.init();
  lcd.clear();         
  lcd.backlight();      // Make sure backlight is on
  
  // Print a message on both lines of the LCD.
  lcd.setCursor(0,0);   //Set cursor to character 2 on line 0
  lcd.print("PUMP-MOMA start");
  
  lcd.setCursor(0,1);   //Move cursor to character 2 on line 1
  lcd.print("  Well Monitor");
}
void loop() {
	float rawvolts = 0.0;
	float convolts = 0.0;
  float gpm = 0.0;
	//=====FLOW======================
  //timeout on waiting is 5 seconds
  ontime = abs(pulseInLong(pulse_ip,HIGH,3000000));
  offtime = abs(pulseInLong(pulse_ip,LOW,3000000));
  period = abs(pulseInLong(pulse_ip,HIGH,3000000)) + abs(pulseInLong(pulse_ip,LOW,3000000));
  
  /*
  Serial.print("ON: ");
  Serial.print(ontime);
  Serial.print("  OFF: ");
  Serial.print(offtime);
  Serial.print(" Period: ");
  Serial.println(period);  
*/
   if(period==0){ 
    freq=0;
    
  }else
    {freq = 1000000.0/period;
      duty = (ontime/period)*100; }
      if(freq<0)freq=0;
   //Serial.println(String(freq)+" Hz");
 
   
  //UPDATE FLOW_LED_PIN================
  if (freq < 2) {
      digitalWrite(FLOW_LED_PIN, LOW);
  }
  else {
      digitalWrite(FLOW_LED_PIN, HIGH);
  }
  
  //Calc GPM as (F+5/8.1)*.264
  gpm = ((freq+5)/8.1)*.264;
  //delay(1500);
  lcd.setCursor(0,0);   //Set cursor to character 0 on line 0
  lcd.clear();
  lcd.print("Flow Rate: ");
  lcd.print(gpm);
  lcd.setCursor(0,1); 
  lcd.print("Well Pump: ");
  if (ledState == 1)
  {
  lcd.print("ON");}
  else
  {
  lcd.print("off");}
  delay(2000);
  // Send the command for all devices on the bus to perform
	// TEMPERATURE conversion:
  sensors.requestTemperatures();
  // Fetch the temperature in degrees Celsius for device index:
  float tempC = sensors.getTempCByIndex(0); // the index 0 refers to the first device
  // Fetch the temperature in degrees Fahrenheit for device index:
  float tempF = sensors.getTempFByIndex(0);
  // Print the temperature in Celsius in the Serial Monitor:
  /*
  Serial.print("Temperature: ");
  Serial.print(tempC);
  Serial.print(" \xC2\xB0"); // shows degree symbol
  Serial.print("C  |  ");
*/
  // Print the temperature in Fahrenheit
  lcd.setCursor(0,0);   //Set cursor to character 0 on line 0
  lcd.print("H20 Temp: ");
  lcd.print(tempF);
/*
  Serial.print(tempF);
  Serial.print(" \xC2\xB0"); // shows degree symbol
  Serial.println("F");
*/
  rawvolts = analogRead(2);
  convolts = (rawvolts * 5.0)/ 1024.0;
  /*
  Serial.print("RAW_Volts: ");
  Serial.print(rawvolts);
  Serial.print("  CON_Volts: ");
  Serial.print(convolts);
  */
  if (convolts < 0.5) 
  {
    prshr = 0.00;
  }
  else 
  {
    prshr = (convolts - 0.46)/.04;
  }
  if (prshr > hi_prshr) 
  {
    hi_prshr = prshr;
  }
  if (prshr < lo_prshr)
  {
    lo_prshr = prshr;
  }
  lcd.setCursor(0,1);
  lcd.print("Pressure: ");
  lcd.print(prshr);
  //delay(3000);
  lcd.setCursor(0,0);   //Set cursor to character 0 on line 0
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Gallons: ");
  lcd.print(ttlgallons);
  delay(3000);
/*
  Serial.print("  Pressure: ");
  Serial.print(int(prshr));
  
  Serial.print("  High: ");
  Serial.print(int(hi_prshr));
  Serial.print("  Low: ");
  Serial.println(int(lo_prshr));
  delay(1000);
*/
  }  //end of loop
void blinkPumpLed() {
  ledState = !ledState;
  digitalWrite(PUMP_LED_PIN, ledState);
  /*
  lcd.setCursor(0,1); 
  lcd.print("Well Pump: ");
  if (ledState == 1)
  {
  lcd.print("ON");}
  else
  {
  lcd.print("off");}
  // Serial.print("PUMP STATE CHANGE: ");
  // Serial.println(ledState);
  */
}
void countGallon(){
 //increments the gallon counter for this session
  ttlgallons += 1;
  //blink an LED
  digitalWrite(GALLON_LED_PIN, HIGH);
  delay(1000);
  digitalWrite(GALLON_LED_PIN, LOW);
  Serial.println(ttlgallons);
}
void reportError(const char *errorMsg) {
  Serial.println("Error: ");
  Serial.println(errorMsg);
}