#include <LiquidCrystal.h>
#include <EEPROM.h>
//*************** User defined variables **************************//
//pH meter Analog output to Arduino Analog Input 0
int PHPin = A5;
//The calibration constant for the PH probe
float K_PH=3.64;
//used for min/max logs
float MinPH=10;
float MaxPH=0;
//************** Some values for working out the ph*****************//
float Kn=0;
float phValue=0;
int i=0;
long reading=0;
unsigned long sum=0;
float average=0;
// 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 btnRST 6
int Screen =1;
//Max number of screens on lcd
const int Last_Screen_no =4;
//used to debounce input button
int buttonLast=0;
//******************** Main Loops runs Forver ************************************//
void loop()
{
//All these functions are put below the main loop, keeps the loop logic easy to see
read_LCD_buttons();
ReadPH();
CalibratePH();
PrintReadings();
delay(100);
};
//*************************Startup display **************************//
void startupinfo(){
Serial.println("pH Probe Script for Chemistry 114");
Serial.println("Dr. Windman's Class");
Serial.println("Devon von Lichtenstein");
Serial.println("How to Use:");
Serial.println("1:Place Probe into pH7 calibration fluid, open serial");
Serial.println("2:Take Recomened cell constant and change it in the top of code");
Serial.println("3:Rinse Probe and place in pH4 calibration fluid");
Serial.println("4:Adjust potentiometer on pH meter shield until ph reading in serial is 4");
Serial.println(" ");
Serial.println("That's it you're calibrated and your readings are accurate!");
}
//*************************Take Ten Readings And Average ****************************//
void ReadPH(){
i=1;
sum=0;
while(i<=100){
reading=analogRead(PHPin);
sum=sum+reading;
delay(20);
i++;
}
average=sum/i;
//converting the average to PH 3.5 part convers mv to ph
phValue=average*K_PH*5/1024;
}
//****************************** 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>=Last_Screen_no) Screen=Last_Screen_no;
if(Screen<=1) Screen=1;
buttonLast=button;
};
//************************** 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;
//***************** Specifying where to sotre the calibration value [non volatile memory **//
int value; //we use this to check if memory has been writen or not
int addresCalibrationPH=50;
//************************** Printing somthing useful to LCD on start up **************************//
void Splash_Screen(){
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
delay(1000);
lcd.print("PH meter ");
lcd.setCursor(0,1);
delay(1000);
lcd.print("Devon von Lichtenstein");
lcd.setCursor(0,0);
lcd.print("To Navigate ");
lcd.setCursor(0,1);
lcd.print("Use Up-Down ");
delay(3000);
lcd.setCursor(0,0);
lcd.print("To Calibrate ");
lcd.setCursor(0,1);
lcd.print("Hold Select ");
delay(3000);
};
void Read_Eprom(){
//************** Restart Protection Stuff ********************//
//the 254 bit checks that the adress has something stored to read [we dont want noise do we?]
value = EEPROM.read(addresCalibrationPH);
if (value <=254) K_PH=value*0.02;
};
//******************************* Checks if Select button is held down and enters Calibration routine if it is ************************************//
void CalibratePH(){
//we check if we are on ph screen and the select button is held
if(Screen!=4) return;
if(button!=5) return;
else delay(1000);
read_LCD_buttons();
if(button!=5) return;
//we need to stop in this loop while the user calibrates
while(1){
read_LCD_buttons();
lcd.setCursor(0,0);
lcd.print("Ph Probe in pH7 ");
lcd.setCursor(0,1);
lcd.print("Press Right ");
//user pressed right?
if(button==1) break;
delay(100);
};
lcd.setCursor(0,0);
lcd.print("Calibrating ");
lcd.setCursor(0,1);
lcd.print("pH Probe ");
//let probe settle
delay(2000);
//read the ph probe
ReadPH();
Kn=((7*1024)/(average*5));
while (1) { // wee need to keep this function running until user opts out with return function
read_LCD_buttons();
if(button==4) return; //exits the loop without saving becauser user asked so
if (button==5){
K_PH=Kn; //saving the new cell constant
//*******Saving the new value to EEprom**********//
value=Kn/0.02;
EEPROM.write(addresCalibrationPH, value);
lcd.setCursor(0,0);
lcd.print("Saved Calibration ");
lcd.setCursor(0,1);
lcd.print("K: ");
lcd.setCursor(3,1);
lcd.print(Kn);
delay(2000);
lcd.setCursor(0,0);
lcd.print("Now pH4 and ");
lcd.setCursor(0,1);
lcd.print("Adjust Pot ");
delay(4000);
//Put back to main screen and exit calibration
Screen=1;
return;
}
if(millis()%4000>=2000){
ReadPH();
lcd.setCursor(0,0);
lcd.print("Calibrated ");
lcd.setCursor(0,1);
lcd.print("PH: ");
lcd.setCursor(3,1);
lcd.print(phValue);
}
else{
lcd.setCursor(0,0);
lcd.print("Select To Save ");
lcd.setCursor(0,1);
lcd.print("Down to Exit ");
};
}
};
//******************************* LOGS Min/MAX Values*******************************//
void Log_Min_MaxPH(){
if(phValue>=MaxPH) MaxPH=phValue;
if(phValue<=MinPH) MinPH=phValue;
};
void PrintReadings(){
Serial.print("pH: ");
Serial.print(phValue);
//** First Screen Shows pH **//
if(Screen==1){
lcd.setCursor(0,0);
lcd.print("Arduino pH ");
lcd.setCursor(0,1);
lcd.print("pH: ");
lcd.setCursor(3,1);
lcd.print(phValue);
}
//**Second Screen Shows Min and Max **//
else if(Screen==2){
lcd.setCursor(0,0);
lcd.print("Min: ");
lcd.setCursor(4,0);
lcd.print(MinPH);
lcd.setCursor(0,1);
lcd.print("Max: ");
lcd.setCursor(4,1);
lcd.print(MaxPH);
lcd.setCursor(9,1);
}
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);
}
else if(Screen==4){
lcd.setCursor(0,0);
lcd.print("Calibrate pH ");
lcd.setCursor(0,1);
lcd.print("Hold Select ");
}
};