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)avgValue5.0/1024/6; //convert the analog into millivolt phValue=3.5phValue; //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 Answers1

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.

the busybee
  • 2,408
  • 9
  • 18