Measure pH with a low-cost Arduino pH sensor board

pH Sensor Board

I recently bought an Arduino pH sensor kit for measuring pH value of my hydroponic setup, it cheap but has very little information/document on how to use it, so I decided to figure it out myself on how it works and how to use it.

Popular pH measurement kits for Arduino

If you search for pH sensor with Arduino on Internet, you are likely see 3 major commercially available or mass-produced solutions:

Atlas Scientific offers high quality and well-designed sensor kit for pH measurement. It Gravity analog pH Kit consists of a consumer-grade pH sensor and interface board, plus 3 package of calibration buffer solutions will cost $65.00. Atlas Scientific hardware is high quality but doesn’t seems to be open-sourced.

DFRobot also has a solution with the same name Gravity (why?) as Atlas Scientific. its version 1 Gravity: Analog pH Sensor Kit consists of pH probe plus the sensor board and is priced at $29.50. There is a version 2 of Gravity: Analog pH Sensor Kit which comes with the board with enhanced design at $39.50 by including buffer solutions and mounting screws for the board. DFRobot published its schematic, PCB layout and Arduino code for version 1 on its website and github under GPL2 license. But it only publish the PCB layout for version 2 without schematic, so I don’t know what exactly was enhanced in the design for the version 2.

The third commonly available pH sensor kit for Arduino that you see almost in every e-commerce marketplaces such as Taobao, AliExpress and Amazon is this “mystery” pH sensor kit that I bought. You can find it at as low as $17.00 for a pH probe with the sensor board. It is “mystery” because it seems that there are multiple Chinese manufacturers producing the same board but I can’t really find out which company actually own the design. I bought it anyway with the thinking that if I could understand how the pH probe works and with a little bit of “reverse-engineering” of the circuit design to help me to have better understanding of the circuitry, then I should be able to figure out on how to make it work. This fits my tinker spirit well…

Other than those three commonly available pH sensor kits, there are others available in the market, but they are relatively niche with limited distribution.

How pH probe work electronically?

A pH probe consists of two main parts: a glass electrode and a reference electrode as shown in the picture below. I’m not very good at chemistry, so I won’t try to explain it that way, this pH theory guide provides very comprehensive explanation about the theory behind. In the nutshell, pH is determined essentially by measuring the voltage difference between these two electrodes.

Typical pH probe and characteristics

The pH probe is a passive sensor, which means no excitation voltage or current is required. It produces a voltage output that is linearly dependent upon the pH of the solution being measured. An ideal pH probe produces 0v output when pH value is at 7, and it produces a positive voltage (a few hundred mili-volts) when pH value go down, and a negative voltage level when pH value go up, causing by the hydrogen irons forming at the outside (and inside) of the membrane glass tip of the pH probe when the membrane comes into contact with solution. The source impedance of a pH probe is very high because the thin glass bulb has a large resistance that is typically in the range of 10 MΩ to 1000 MΩ. Whatever measurement circuit connect to the probe requires to be high-impedance in order to minimise the loading effect of the circuit.

Hardware – The pH sensor board explained

The pH sensor board that I bought came without any user guide, schematic or example code. I asked the small Chinese vendor for information but in vain. I decided to “reverse-engineering” the schematic diagram but eventually I find the schematic diagram at the attachment of this Arduino forum discussion. The pH sensor board can be divided into 3 different sections based on its functionality. I colour the three key sections with different color for discussion here.

ph sensor board functional highlights
pH sensor board functional highlights

pH Measurement Circuit

The light green section with the TLC4502 high-impedance operation amplifier basically consists of a voltage divider and a unity-gain amplifier. The pH output(Po) provided an analog output for pH measurement. As pH probe swing between positive and negative voltage, and since TLC4502 is operate with single power source, half of the TLC4502 is used as a voltage divider to provide a reference voltage of 2.5v to “float” the pH probe input so that the output of Po will be +/-2.5v based on pH value. A potentiometer RV1 is used for calibration purpose that I will further discuss later. This part of the circuit is well-designed and it is all it needed for measuring the pH value. The other parts of the board in my opinion are not well designed and sort of in the category of “nice-to-have” and not essential.

pH Threshold Detection Circuit

The yellow section provides a pH threshold detection/notification circuit. For example, you could adjust the potentiometer RV2 so that when pH level reach a threshold level (e.g. say 7.5), the RED LED D1 will be turned on (Digital output Do changed from high to low). Alternatively, you could use it to detect the lower pH level threshold, say, when pH value is below 5.5, the RED LED will be turned off and Do changes from low to high. But you can’t set both lower and upper thresholds with this circuit. In my opinion, it will be easier to just use software solution than this hardware solution for threshold detection.

Temperature Reading Circuit

The light blue/cyan section of the board consists of 1 and a half LM358 OpAmp, and provides an analog reading at To. U2B of LM358 acts as a not so accurate voltage divider and provides a voltage reference of 2.5v to a Wheatstone bridge that consists of R13 – R15 and a thermistor TH1. The U3A behave as an differential OpAmp, the output is then pass through a low-pass filter and further amplified by a non-inverting OpAmp U3B. This entire circuit has nothing to do with pH measurement, at least not directly. I will talk about this toward the end of this article.

The sole reason for measuring temperature in the context of measuring pH value is because that pH curve slope changes when temperature change between 0 to 100 degree Celsius. It is therefore important to measure the temperature of the solution, and add temperature compensation factor into the pH calculation.

One thing interesting is that all the manufacturers for this board design that I saw in the market had the thermistor solder on the board instead of having a water-proof thermistor probe like the one that I described in my my previous post. By soldering thermistor on-board, that means the thermistor is measuring ambience temperature near the board instead of the temperature of the solution where pH was measured, this simply doesn’t make sense. This makes me think that all those Chinese manufacturers are simply copying the design from a circuit diagram or reverse-engineering without understanding the purpose of having the thermistor for temperature measurement in the context of pH measurement application.

Now I studied and understand the circuit diagram, it is time to calibrate the pH sensor and write some code for measuring the pH value!

How to calibrate the pH sensor?

As discussed previously that by design the pH probe oscillates between negative and positive values. When the pH reading is at 7.0, the pH output is offset by 2.5v so that both negative and positive values generated by the pH probe can be represented as positive values in full range, this means that when pH is at 0, the Po would be at 0v, and when pH is at 14, the Po would be at 5v.

In order to make sure that when pH is at 7.0, we can calibrate the reading to make sure that Po will be at 2.5v by disconnecting the probe from the circuit and short-circuiting the inner pin of the BNC connector with the outer BNC ring. With a multimeter measure the value of Po pin and adjust the potentiometer to be 2.5V. Don’t worry if you don’t have a multimeter, you can write an Arduino sketch to read the analog input by connecting the Po to analog input A0 of the Arduino.

ph_calibrate.ino

#include <Arduino.h>
const int adcPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int adcValue = analogRead(adcPin);
  float phVoltage = (float)adcValue*5.0/1024;
  Serial.print("ADC = ");
  Serial.print(adcValue);
  Serial.print(";  Po  = ");
  Serial.println(phVoltage, 3);
  delay(1000);
}

Connect Po to Aanalog input A0 on Arduino, and G to Arduino GND. Run the Arduino sketch, and open the Serial Monitor of Arduino IDE to observe the reading, slowly adjust the potentiometer RV1 (the one near the BNC connector on the board) until the Po reading equal to 2.50v.

This is assuming that all the pH probe are equal and will produce exactly 0v at pH reading of 7.0, but in reality all probes are slightly different from each other, especially for consumer-grade pH probe. Temperature also affect the reading of pH sensor slightly, so the better way is to use a pH buffer solution of pH=7.0 to calibrate the probe. All the buffer solution will have the temperature compensation information on its package that you could factor-in for your calibration.

ph buffer solution for calibration
pH buffer solution for calibration

pH buffer packages for calibration purpose available in liquid form or in powders form, liquid pack is easy to use but powders pack is good for storage. These solutions are sold in different values but the most common are pH 4.01, pH 6.86 and pH 9.18.

pH values are relatively linear over a certain range (between ph 2 to ph 10), we need two calibration points to determine the linear line, and then derives the slope of the line so that we could calculate any pH value with a given voltage output (see Figure 2 chart above). What value of pH buffer to use for this second calibration depends on your application, if your application is for measuring acidic solution, use buffer solution for ph=4.01 for the second calibration; buf if your application is mostly for measuing basic/alkanine solution, use buffer solution of ph=9.18 for the second calibration. In my case, as hydroponic for vegetable grow tends to be slightly acidic with ph ranging between 5.5 – 6.5, I use ph=4.01 buffer solution for my calibration.

To avoid cross contamination, dip the probe in distill water for a couple of minites before dipping it in different buffer solutions. For increase the accuracy, let the probe stay in the buffer solution for a couple of minutes before taking the reading as the result.

Use the same Arduino sketch to get the voltage reading for pH=4.01, and write down the voltage value, in my case, the voltage is 3.06 @ pH=4.01. The voltage readings at ph of 4.01 Vph4 and at pH of 7.0 Vph7 allows us to draw a straight line, and we can get the Voltage change per pH value m as:

m = (Vph7 - Vph4) / (ph7 - ph4)
m = (2.5 - 3.06) / (7 - 4.01)
m = -0.18729

So the pH value at any voltage reading at Po can be derived with this formula:

pH = pH7 - (Vph7 - Po)/m

i.e.

pH = 7 - (2.5 - Po)/m

Measure pH value

With the formula, we can create the Arduino sketch to measure the pH value based on the voltage reading at the Po.

#include <Arduino.h>
const int adcPin = A0;
  
// calculate your own m using ph_calibrate.ino
// When using the buffer solution of pH4 for calibration, m can be derived as:
// m = (Vph7 - Vph4)/(pH7 - pH4)
const float m = -0.18729; 

void setup() {
  Serial.begin(9600);
}

void loop() {
  float Po = analogRead(adcPin) * 5.0 / 1024;
  float phValue = 7 - (2.5 - Po)/m;
  Serial.print("ph value = ");
  Serial.println(phValue);
  delay(5000);
}

How about Temperature Measurement?

As I mentioned before it doesn’t make sense to measure the ambience temperature near the PCB, so the first thing I did is de-solder the on-board thermistor and replace it with one of those water-prove thermistors.

A Wheatstone Bridge circuit is nothing more than two simple series-parallel arrangements of resistances connected between a reference voltage supply and ground producing zero voltage difference between the two parallel branches when balanced. When one of the arm of the resistance arrangements consists of a thermistor, its resistance changes as temperature changed, causing the imbalance of two resistance arms and a voltage difference developed between the two parallel branches in according to the change of the thermistor resistance which is directly related to the change of the temperature.

Specifically to this circuit, the voltage reference is provided by U2B which formed a voltage divider and produce a reference voltage (let’s called it Vref) of 2.5V at pin 7 of U2B. According to the characteristics of thermistor, the thermistor will have a resistance of 10k-ohms at temperature of 25 degree Celsius. The Wheatstone Bridge will be balanced and the output voltage Vd of the Wheatstone Bridge at the terminals of resistors R16 and R18 will be zero and will swing above and below 0 volt when temperature changes. The Vd is then amplified by U3A which seems to be a differential amplifier, the U3B is a typical non-inverting amplifier. As I’m not quite sure about the gain of U3A so I decided to ask at Electrical Engineering StackExchange, and I got my questions answered within an hour. The circuit has a total gain of 14.33 when the thermistor is at 10k (i.e. when temperature is at 25 degree Celsius). However, the gain of U3A will change when the thermistor resistance change, obviously this is not a very good design.

I also got confirmed my suspicion that there is a missing 20k resistor between between pin 3 of U3A and ground on the circuit diagram, interestingly the circuit board is designed to have this resistor, but where the resistor is supposed to be is left empty (why?). Further inspect the circuit I noticed that the R12 on the board is actually having a value of 51.1k instead of 100k as shown in the circuit diagram. So the over gain will be 1.33+5.11+1=7.44.

We can derive the Vd based on the measured voltage of To, and further derive the value of resistance of TH1 at the temperature where To is measured:

    Vd = To / 7.44

    Vd = Vref * (R14 / (R14 + R15)) - Vref * (R13 / (R13 + TH1))

Absolute temperature T based on Steinhart–Hart equation for thermistor calculation can then be derived from:

    T = 1 / (1/To + 1/B * ln(TH1/Ro))

Where:
T is the absolute temperature to be measured in Kelvin;
To is the reference temperature in Kelvin at 25 degree Celsius;
Ro is the thermistor resistance at To;
B is Beta or B parameter = 3950, provided by manufacturer in their specification.

In theory, the primary benefit of Wheatstone Bridge circuit is its ability to provide extremely accurate measurements in contrast with a simple voltage divider, as a voltage divider is often affected by the loading impedance of the measuring circuit. In actual application, the accuracy of the Wheatstone Bridge is highly depend on the precision of the resistors used to form the Wheatstone Bridge, the precision of voltage reference as well as the circuit that connected to the Wheatstone Bridge. Although I figured out the formula on how to measure the temperature, I did not write the code to calculate the temperature, as the gain of U3A will vary as the value of the thermistor varies in according to the temperature. This make the reading result almost unpredictable and I will probably not use this circuit for measuring the water temperature without further modify the design.

In Summary

Overall, this pH sensor board has a good pH measurement circuit design, the rest parts of the circuit are quite useless and a little bit over-engineered. By eliminating the bad part of the circuit design and kept the good part, it could be simpler and maybe slightly cheaper than current design for a pH sensor board.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.