DIY Arduino pH Meter: Full Schematic, Code, and OLED Display Tutorial

In this blog post, I want to show how one can build a sophisticated pH meter using an Arduino Uno. This electronics project goes beyond simple plug‑and‑play modules by employing a specialized quad op‑amp configuration to handle the extremely sensitive signals produced by a pH probe. This embedded project will thus explore how to bridge the gap between chemistry and electronics to build diy Arduino pH meter that achieves professional‑grade results.

Hardware & Schematic

The circuit diagram of Arduino based pH meter is shown below.

Arduino pH meter circuit diagram

The Role of Each Op‑Amp (TL074 Quad Package)

At the heart of this design is the TL074 op-amp IC, which contains four independent operational amplifiers. Each one plays a precise role in conditioning and stabilizing the probe’s signal.

  • Op‑Amp 1 (U1:A) – The High‑Impedance Guard

    • Role: Unity Gain Buffer (Voltage Follower)

    • Function: pH probes have extremely high internal resistance. Drawing even a tiny current can distort the reading. This op‑amp, with its JFET inputs, “looks” at the probe’s voltage without loading it. It replicates the voltage at its output with enough drive capability for the rest of the circuit.

  • Op‑Amp 2 (U1:D) – The Reference Generator

    • Role: Voltage Reference Buffer

    • Function: To make the signal compatible with the Arduino, we need a stable offset. This op‑amp takes the voltage from the R4/R5 divider and stabilizes it, creating a “virtual ground.” This shifts the probe’s signal upward so that even negative voltages (common in alkaline solutions) are translated into positive values the Arduino can measure.

  • Op‑Amp 3 (U1:B) – The Precision Scaler

    • Role: Differential Amplifier

    • Function: This stage performs the “math” in hardware. It compares the buffered probe signal from U1:A against the reference voltage from U1:D. It then amplifies the tiny difference between them, scaling small pH changes into a measurable swing from 0 V to 3.3 V for the Arduino’s ADC.

  • Op‑Amp 4 (U1:C) – The Ground Stabilizer

    • Role: Active Ground / Isolation

    • Function: This op‑amp ties into the ground loop, ensuring that the return path for analog signals remains clean and isolated from digital noise generated by the Arduino and OLED display.

Supporting Components

  • ICL7660 (U3): A charge pump that generates a −5 V rail. This is essential because pH probes naturally produce negative voltages in alkaline solutions, and the op‑amps need this rail to process them correctly.

  • Potentiometer (RV1): Acts as the calibration tool. By adjusting it, you can align the offset so that when the probe is placed in a pH 7.0 buffer solution, the display reads exactly 7.00.

  • Arduino & OLED: The Arduino samples the refined analog voltage at pin A2. Using the I²C protocol, it sends the data to the SSD1306 OLED screen, which provides a crisp digital readout of the pH value.

Program Code

The following is the program code for the Arduino pH meter:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Final Calibrated Constants based on your successful test:
const float probeSlope = -3.91; 
const float probeInt = 13.51;   

void setup() {
  Serial.begin(9600);
  analogReference(EXTERNAL); // 3.3V connected to AREF

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { for(;;); }
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  // Smoothing: Read 10 times and average
  float reading = 0;
  for(int i = 0; i < 10; i++) {
    reading += analogRead(A2);
    delay(5);
  }
  float avgADC = reading / 10.0;
  float voltage = (avgADC * 3.3) / 1023.0;

  // Linear Formula
  float phValue = probeInt + (probeSlope * voltage);

  // Constraints
  if (phValue < 0) phValue = 0.0;
  if (phValue > 14) phValue = 14.0;

  // OLED Output
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0, 10);
  display.print("pH: ");
  display.print(phValue, 2);
  
  display.setTextSize(1);
  display.setCursor(0, 45);
  display.print("V(A2): "); display.print(voltage, 3);
  display.print(" (");
  display.print((int)((avgADC/1023.0)*100)); // Show % of ADC range
  display.print("%)");
  
  display.display();
  delay(20);
}

How the Code Works

1. External Reference (AREF) Setup

The line analogReference(EXTERNAL) is vital. By default, an Arduino uses its 5V supply as a reference, but that supply can fluctuate. By connecting a steady 3.3V source to the AREF pin and calling this function, the code ensures the Analog-to-Digital Converter (ADC) has a rock-solid "ruler" to measure against, significantly increasing precision.

2. Signal Smoothing (Anti-Jitter)

Instead of taking a single, potentially noisy reading, the code uses a for loop to read pin A2 ten times. It adds these up and divides by ten to get an average. This mathematical "filtering" removes the rapid flickering of numbers often seen in high-impedance sensor circuits.

3. The Linear Conversion Formula

The code converts the ADC steps into a voltage and then uses a linear equation ($y = mx + b$) to find the pH:

  • probeSlope (-3.91): This represents the sensitivity of your specific hardware.

  • probeInt (13.51): This is the "intercept" or offset, accounting for where pH 7 sits in your voltage range.

4. Safety Constraints

pH cannot physically go below 0 or above 14. The code includes constraints to "clamp" the values, ensuring that if electrical noise or a disconnected probe causes a weird reading, the screen doesn't show an impossible value like "pH: -1.5".

How to Calibrate This Meter

To calibrate this sophisticated meter, we use a Digital Two-Point Calibration method. Instead of fiddling with hardware trimmers, we fine-tune the mathematical constants within the code to match the specific characteristics of your pH probe.

1. Find the Neutral Point (pH 7.0)

  • Action: Dip your probe into a pH 7.0 buffer solution.

  • Adjustment: Look at the pH value on the OLED. If it is not exactly 7.00, go to the code and adjust the probeInt (Intercept) constant.

    • Example: If the screen shows 7.20, decrease the probeInt value by 0.20 in your code and re-upload.

  • Goal: This "centers" your meter so that the neutral point is perfectly aligned.

2. Find the Slope (pH 4.0 or 10.0)

  • Action: Clean the probe with distilled water and dip it into a pH 4.0 (acidic) or pH 10.0 (alkaline) solution.

  • Adjustment: If the reading is off, you need to adjust the probeSlope constant in the code. This changes the "sensitivity" of the calculation.

    • If the reading is too high: Increase the negative value of the slope (e.g., change -3.91 to -4.05).

    • If the reading is too low: Decrease the negative value of the slope (e.g., change -3.91 to -3.80).

  • Why? This step ensures the meter stays accurate as you move further away from the neutral pH 7 point.

3. Verify and Lock In

  • Action: Rinse the probe and check both buffer solutions one last time.

  • Result: Once both points read correctly, your calibration constants are "locked" in the code. Unlike a physical potentiometer that can drift if bumped, these digital values will remain perfectly stable.

Unique Features vs. Standard pH Meters

What makes this project "sophisticated" compared to the cheap $10 modules found online?

  • Raw Data Transparency: Most meters only show the pH. This code displays the raw voltage (V) and the ADC percentage (%). This is a pro-level feature that helps you troubleshoot if a probe is dying or if the circuit is saturated.

  • Dual-Rail Handling: Because your hardware uses a negative voltage generator (ICL7660), this code can accurately read across the full 0–14 range without the "clipping" issues that affect single-supply budget meters.

  • Custom Sensitivity: Standard modules have fixed gain. Because you can change the probeSlope directly in this code, you can use high-end laboratory probes or cheaper hobbyist probes and achieve the same high accuracy by simply updating one number.

  • Enhanced Resolution: By utilizing the 3.3V AREF instead of the 5V default, you are effectively "zooming in" on the signal, giving you better resolution per bit than most standard Arduino pH projects.

Video demonstration

The following video demonstrates how this Arduino pH meter works:


Conclusion By using this quad op‑amp approach, we ensure that our pH meter is not only accurate but also resilient against electrical noise and signal degradation. The result is a reliable instrument that combines chemistry and electronics into a practical, DIY solution.

If you have any comments or question leave them in the comment section below.

Post a Comment

Previous Post Next Post