1

I have to measure the pH value for some experiment. I have checked various codes and all include the average of pH values.

#define SensorPin 0          // the pH meter Analog output is connected with the Arduino’s Analog
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10],temp;
 
void setup()
{ 
  Serial.begin(9600);  
  Serial.println("Ready");    //Test the serial monitor
}
void loop()
{
  for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
  { 
    buf[i]=analogRead(SensorPin);
    delay(10);
  }
  for(int i=0;i<9;i++)        //sort the analog from small to large
  {
    for(int j=i+1;j<10;j++)
    {
      if(buf[i]>buf[j])
      {
        temp=buf[i];
        buf[i]=buf[j];
        buf[j]=temp;
      }
    }
  }
  avgValue=0;
  for(int i=2;i<8;i++)                      //take the average value of 6 center sample
  avgValue+=buf[i];
  float phValue=(float)avgValue*5.0/1024/6; //convert the analog into millivolt
  phValue=3.5*phValue;                      //convert the millivolt into pH value
  Serial.print("pH:");  
  Serial.println(phValue,2);
  delay(5000); 
} 

Kindly explain the meaning of these two lines. Why take constant values as in bold (5/1024/6) and (3.5*pH)? Can I use some other value instead of these?

float phValue=(float)avgValue*5.0/1024/6; //convert the analog into millivolt
  phValue=3.5*phValue;                      //convert the millivolt into pH value

1 Answer 1

1

This is a fine example why magic numbers are bad. Always use symbolic constants.

Concerning the first line:

  1. The "5.0" is the reference voltage of the ADC, apparently 5.0 volts.

  2. The "1024" is the width of the range of values returned by the ADC.

  3. The "6" is the number of samples summed up in the two lines before.

The ADC returns values in the range from 0 to 1023, giving you 1024 different values. If it measures 0% of its references voltage, it returns 0. If it measures 100% of its references voltage, it returns 1023. Actually the value "1024" should be "1023", but considering the accuracy it does not really matter.

By dividing the measured value by 1024, a single ADC value ranges from 0.0 (0%) to 0.999 (nearly 100%).

Multiplication by "5.0" gives the voltage, if we suppose that the reference voltage is 5.0 volts.

As 6 samples are summed up, another division by 6 is necessary to obtain the average.

In contrary to the comment the result of the first line is the measured and averaged voltage in volts, not in millivolts.

If the author had used smybolic constants, no comment would have been necessary and thus could not become erroneous.

Concerning the second line:

Apparently this is the factor of the sensor between voltage and pH value. A voltage of 0 volts means a pH value of 0, and a voltage of 4 volts means a pH value of 14. Note: pH can only range from 0 to 14.

Since you did not post a link to the data sheet of the used sensor, we cannot check this. But you can.

A first approach with symbolic constants:

static const int FIRST_INDEX_FOR_AVERAGE = 2;
static const int NUMBER_OF_VALUES_TO_AVERAGE = 6;

static const float FULL_SCALE_IN_VOLTS = 5.0;
static const int ADC_MAXIMUM = 1023; // was 1024

static const float PH_PER_VOLT = 3.5; // or even better 14.0 / 4.0

// ...

avgValue = 0;
for (int i = FIRST_INDEX_FOR_AVERAGE;
     i < FIRST_INDEX_FOR_AVERAGE + NUMBER_OF_VALUES_TO_AVERAGE;
     i++)
{
    avgValue += buf[i];
}

float phValue = avgValue * FULL_SCALE_IN_VOLTS / ADC_MAXIMUM / NUMBER_OF_VALUES_TO_AVERAGE;

phValue = phValue * PH_PER_VOLT;

There is no need to cast avgValue to float since FULL_SCALE_IN_VOLTS is float and so the calculations are done in floating point.

5
  • 1
    PH values follows a linear equation, y = mx + b, the 3.5 is the slope of the linear line. Typically a PH probe need to be calibrated with two buffer solutions, for example, at PH4 and another at PH9 or PH7, the line can then be draw and the slope can be determined. Commented Aug 5, 2022 at 6:31
  • A voltage of 0 volts means a pH value of 0, and a voltage of 4 volts means a pH value of 14. Not exactly, the measurement of PH value usually required to be amplified via an OP AMP, and since PH value can't be a negative value, the OP AMP is usually "raise" the reference voltage, say, to 2.5V, and then calibrate the probe for the OP Amp to output 0 voltage when PH is at 7.0 (Center of the PH range), so the PH value swing between +/-2.5V. Commented Aug 5, 2022 at 6:35
  • As I wrote, we have no information what sensor and external circuitry the OP uses. Therefore, I simply explained the factor. Anyway, your comments are welcome, as an potential edition of my answer. Just keep the meaning, please. Commented Aug 5, 2022 at 6:39
  • 2
    Re “the value ‘1024’ should be ‘1023’”: In theory, it should be 1024. This is clearly stated in the datasheet of the microcontroller: the value 1023 “represents the selected reference voltage minus one LSB”. In practice, you have to calibrate the ADC if you need this level of accuracy. I have measured a slope of ≈1026 on three Arduinos. Commented Aug 5, 2022 at 7:40
  • @EdgarBonet Thanks for this valuable insight! Commented Aug 5, 2022 at 7:51

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.