Grove ph probe with grove orp probe

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

@salman Do you have any suggest ?

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

@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;


}