Hi. I have a grove blue ph and orp probes. Apparently you can not have them in the same “container” doing measurements. How far apart do they need to be where they won’t affect each other?
You have sample arduino codes for both. Does all of the code for each probe need to be used in a sketch to read the probes. I have a sketch that is testing my pool water. Then I have small pumps to pump in acid or chlorine. I am having difficulties with the probe reading. They don’t seems to be working in my sketch. I am wondering if the calibration sketches (for both ph and orp) do not work when incorporated into a larger sketch? I am no expert on writing code so I just tried to use the sketches used for calibrations. I am hoping there is a simpler piece of code to do the “reads” from the probes!!! Any input word be appreciated
Thanx
Clyde
Baozhu
November 19, 2020, 12:29am
#2
@salman Do you have any suggest ?
salman
November 19, 2020, 1:36am
#3
Hi @ghostrydr23 , Can you please explain and elaborate on the difficulty you are facing while reading the sensor value? If possible share your programme and error log also!
Hi Salman. Did you get my response to your email a couple of weeks ago? If not I can resend,
Thanx
Clyde
salman
December 2, 2020, 5:09am
#5
@ghostrydr23 Sorry, I didn’t receive any mail from you!
Hi Salman,
The problem I have with the reading is I can not have the orp probe and the ph probe in the same flow cell. So I have taken the orp out for now. Now when the sketch runs the ph value starts at around 17 and after it runs for a while(10 minutes)it ends up around -34 ph. I was hoping you might have some code that is a bit more steamlined for reading PH and ORP. I am very new to arduino so trying to figure out what your orp and ph calibration codes are doing is a little beyond me. Let me know what you think
Thanx
Clyde
Here is the code I came up with
/*
#pool chemical pump
#created 11/16/2020
#Clyde Jones
#updated on
#changes made
#added grove(seeed) code for their ORP and PH probes
# This sample code is used to test the pH meter V1.1.
# Editor : YouYou
# Date : 2014.06.23
# Ver : 1.1
# Product: analog pH meter
# SKU : SEN0161
*/
#include <AFMotor.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//PH section
#define SensorPin A0 //pH meter Analog output to Arduino Analog Input 0
#define Offset 39.64705882302941 //deviation compensate
#define samplingInterval 20
#define printInterval 800
#define ArrayLenth 40 //times of collection
#define uart Serial
//PH start
int pHArray[ArrayLenth]; //Store the average value of the sensor feedback
int pHArrayIndex = 0;
//PH end
// ORP section
#define VOLTAGE 5.00 //system voltage
#define OFFSETorp 7 //zero drift voltage
double orpValue;
#define orpArrayLenth 40 //times of collection
#define orpPin 1 //orp meter output,connect to Arduino controller ADC pin 1
int orpArray[orpArrayLenth];
int orpArrayIndex=0;
double orpavergearray(int* orparr, int orpnumber){
int i;
int max,min;
double orpavg;
long orpamount=0;
if(orpnumber<=0){
printf("Error number for the array to avraging!/n");
return 0;
}
if(orpnumber<5){ //less than 5, calculated directly statistics
for(i=0;i<orpnumber;i++){
orpamount+=orparr[i];
}
orpavg = orpamount/orpnumber;
return orpavg;
}else{
if(orparr[0]<orparr[1]){
min = orparr[0];max=orparr[1];
}
else{
min=orparr[1];max=orparr[0];
}
for(i=2;i<orpnumber;i++){
if(orparr[i]<min){
orpamount+=min; //arr<min
min=orparr[i];
}else {
if(orparr[i]>max){
orpamount+=max; //arr>max
max=orparr[i];
}else{
orpamount+=orparr[i]; //min<=arr<=max
}
}//if
}//for
orpavg = (double)orpamount/(orpnumber-2);
}//if
return orpavg;
}
//ORP section end
// input buttons
int purge_acid = 10; // push button acid
int purge_chlorine = 9; // push button chhlorine
int flowswitch = 2; // water flow indicator
int waterflow = 0;
int pumpacid = 0;
int pumpchlor = 0;
int wakeswitch = 13;
int wakeup = 0;
int rotate = 1; // rotate between to pumps
int startup = 0;
int runtime = 0;
// stepper motor
AF_DCMotor motor_acid(2); //motor on port #2 (M2 ) acid pump
AF_DCMotor motor_chlorine(1); //motor on port #1 (M1) chlorine pump
// LCD SETUP
LiquidCrystal_I2C lcd(0x27, 20, 4); // Set the LCD address to 0x27 for a 20 chars,4 line
unsigned long interval = 200000; // screen saver timeout
unsigned long previoustime = 0;
unsigned long currenttime = 0;
unsigned long pumpinterval = 20000; // pumping interval
unsigned long acidlastpump = 0;
unsigned long chlorlastpump = 0;
unsigned long acidcurrent = 0;
unsigned long chlorcurrent = 0;
void setup(void)
{
uart.begin(9600);
// uart.println("pH meter experiment!"); //Test the uart monitor
// LCD setup
lcd.init();
lcd.backlight(); // Turn on the blacklight
lcd.clear(); //clear screen
lcd.setCursor (0,1); //set cursor
lcd.print("Chlorine PH");
// end lcd
//stepper motor setup
motor_acid.setSpeed(200); //200 rpm
motor_acid.run(RELEASE);
motor_chlorine.setSpeed(200);
motor_chlorine.run(RELEASE);
//stepper motor end
// input buttons
pinMode(purge_acid, INPUT_PULLUP); // push button acid
pinMode(purge_chlorine, INPUT_PULLUP); // push button chhlorine
pinMode(flowswitch, INPUT_PULLUP); // water flow indicator
pinMode(wakeswitch, INPUT_PULLUP); // wake up switch
}
//end buttons
void loop(void){
waterflow = digitalRead (flowswitch);
unsigned long starttime = millis(); // get time
wakeup = digitalRead (wakeswitch);
if ((unsigned long)(starttime - previoustime) >= interval)
{
lcd.noDisplay(); // blank lcd
lcd.noBacklight();
previoustime = millis();
}
if (waterflow == LOW) // pump running?
{
lcd.setCursor (6,0);
lcd.print("pump on ");
if (wakeup == LOW) // turn on lcd
{ lcd.backlight();
lcd.display();
pumpacid = digitalRead (purge_acid); //purge acid line
if (pumpacid == LOW)
{ lcd.setCursor (12,3);
lcd.print ("purging ");
motor_acid.run(FORWARD);
delay(5000);
motor_acid.run(RELEASE);
lcd.setCursor (12,3);
lcd.print ("acid off");
pumpacid = digitalRead (purge_acid);
}
pumpchlor = digitalRead (purge_chlorine);
if (pumpchlor == LOW) // purge chlorine line
{ lcd.setCursor (0,3);
lcd.print ("purging ");
motor_chlorine.run(FORWARD);
delay(5000);
motor_chlorine.run(RELEASE);
lcd.setCursor (0,3);
lcd.print ("Chlor off");
pumpchlor = digitalRead (purge_chlorine);
}
} // end wake loop
// PH loop
static unsigned long samplingTime = millis();
static unsigned long printTime = millis();
static float pHValue, voltage;
if (millis() - samplingTime > samplingInterval)
{
pHArray[pHArrayIndex++] = analogRead(SensorPin);
if (pHArrayIndex == ArrayLenth)pHArrayIndex = 0;
voltage = avergearray(pHArray, ArrayLenth) * 5.0 / 1024;
pHValue = -19.18518519 * voltage + Offset;
samplingTime = millis();
}
if (millis() - printTime > printInterval) //Every 800 milliseconds, print a numerical, convert LED state indicator
{
// uart.print("Voltage:");
// uart.print(voltage, 2);
// uart.print(" pH value: ");
// uart.println(pHValue, 2);
printTime = millis();
}
// End PH loop
//ORP Loop
for (startup = 0; startup < 50; startup ++) //stablize chlor reading
{
static unsigned long orpTimer = millis(); //analog sampling interval
static unsigned long orpprintTime = millis();
if(millis() >= orpTimer)
{
orpTimer=millis()+20;
orpArray[orpArrayIndex++]=analogRead(orpPin); //read an analog value every 20ms
if (orpArrayIndex == ArrayLenth) {
orpArrayIndex=0;
}
orpValue=((30*(double)VOLTAGE*1000)-(75*avergearray(orpArray, ArrayLenth)*VOLTAGE*1000/1024))/75-OFFSETorp; //convert the analog value to orp according the circuit
}
if(millis() >= orpprintTime) //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
{
orpprintTime=millis()+800;
// Serial.print("ORP: ");
// Serial.print((int)orpValue);
// Serial.println("mV");
}
lcd.setCursor (12,2);
lcd.print(pHValue);
lcd.setCursor (0,2); //set cursor
lcd.print(orpValue); //print ph orp values
runtime = runtime + 1;
if (runtime > 50)
{
startup = 100;
}
} // end for loop
// end ph and orp calcs
if ((rotate % 2) == 0) //switch between acid & chlor
{
acidcurrent = millis();
if ((acidcurrent - acidlastpump) >= pumpinterval)
{
if (pHValue > 7.4)
{
lcd.setCursor (12,3);
lcd.print ("Pumping ");
motor_acid.run(FORWARD);
delay(5000);
motor_acid.run(RELEASE);
lcd.setCursor (12,3);
lcd.print ("acid off");
acidlastpump = millis();
}
} //end interval loop
} // end rotate loop
if ((rotate & 1) == 1) ////switch between acid & chlor
{
chlorcurrent = millis();
if ((chlorcurrent - chlorlastpump) >= pumpinterval)
{
if (orpValue < -700)
{
lcd.setCursor (0,3);
lcd.print ("Pumping ");
motor_chlorine.run(FORWARD);
delay(5000);
motor_chlorine.run(RELEASE);
lcd.setCursor (0,3);
lcd.print ("Chlor off");
chlorlastpump = millis();
}
} // end interval loop
} // end rotate loop
rotate = (rotate + 1);
} // waterflow loop
if (waterflow == HIGH) // pump running?
{
lcd.setCursor (0,0);
lcd.print(" pump off ");
}
delay (2000); // 2 second loop delay
} // end void void void void void void
// Grove probe software
double avergearray(int* arr, int number) {
int i;
int max, min;
double avg;
long amount = 0;
if (number <= 0) {
uart.println("Error number for the array to avraging!/n");
return 0;
}
if (number < 5) { //less than 5, calculated directly statistics
for (i = 0; i < number; i++) {
amount += arr[i];
}
avg = amount / number;
return avg;
} else {
if (arr[0] < arr[1]) {
min = arr[0]; max = arr[1];
}
else {
min = arr[1]; max = arr[0];
}
for (i = 2; i < number; i++) {
if (arr[i] < min) {
amount += min; //arr<min
min = arr[i];
} else {
if (arr[i] > max) {
amount += max; //arr>max
max = arr[i];
} else {
amount += arr[i]; //min<=arr<=max
}
}//if
}//for
avg = (double)amount / (number - 2);
}//if
return avg;
}