Menu
andrewgrabbs.com
  • Home
  • Cycling
    • Bicycle Builds
    • Events
    • Nutrition
  • DIY
andrewgrabbs.com
October 22, 2019January 9, 2024

Cheap pH Meter for Raspberry Pi with ADS1115 and PH4502C

If you search for “raspberry pi ph meter” you’ll quickly learn that there are very few affordable options when it comes to digitally monitoring the pH of your nutrient solution. For a while Atlas Scientific dominated the search results, but I believe their kit was around $200 at the time. The kit has since come down to $164, but for someone like me that’s still a bit out of my price range.

The problem with the Raspberry Pi is that it has no analog inputs and pH meters are analog for the most part. I like the Raspberry Pi as it’s a one stop shop, sure I could have used a computer that has analogs out of the box, but then how would I upload the information to a remote MySQL server? I’d have to expand that board.

Anyway here is a list of parts I used for this project with the three affiliates I use. Obviously AliExpress is the winner, but if you’re in a time crunch and have the extra money the other two are the exact same things.

** Note: I am using a Raspberry Pi Zero W, this schematic will work with any 40 pin header Raspberry Pi.

Parts used in this Guide (Shipping not included as this varies)
Raspberry Pi Zero W $18.09 $19.98 $21.49
ADS1115 $1.61 $1.79 $6.99
PH4502C + pH Probe $10.47 $14.53 $37.99
pH Reference Solution $0.95 (powder) $17.95 $18.52
Total: $30.17 $54.25 $82.38

Step 1: Wiring

Basic configuration
  • RPi pin 1 (3.3V) to ADS1115 pin VDD
  • RPi pin 2 (5V) to PH4502C pin V+
  • RPi pin 3 (SDA) to ADS1115 pin SDA
  • RPi pin 5 (SCL) to ADS1115 pin SCL
  • RPi pin 8 (GND) to PH4502C pin G (Analog GND closest to V+)
  • RPi pin 9 (GND) to ADS115 pin GND
  • ADS1115 pin A0 to PH4502C pin Po

Optional Setup

There are some optional pins on the PH4502C: To, Do, and G (digital, the G pin furthest from V+). You do not need these pins unless you want a digital signal for the pH limit or the analog temperature sensor as the PH4502C has built in temperature compensation. I do use the temperature sensor built into the pH probe since it’s already there.

  • RPi pin 11 (GPIO 17) to PH4502C pin Do (Optional Digital pH Limit)
  • RPi pin 14 (GND) to PH4502C pin G (Digital GND)
  • ADS1115 pin A1 to PH4502C pin To
Optional Configuration

Step 2: Adjusting the PH4502C Voltage Offset

So the idea behind this step is that that the PH4502C Po voltage oscillates between positive and negative values. We only want positive values for the ADC to convert. To remedy this we force a pH “reading” of 7.0 by shorting the BNC connector. To short the BNC take a metal paper clip and insert it down the center female input on the connector and connect one end of alligator clips to the paper clip and the other end to the outer metal casing of the BNC connector.

Once you have shorted the BNC you can run the following script, which I put way to much thought into. Once you start this script and dial it in to ~2.5 volts, you can leave it running for Step 3.

#!/usr/bin/python
''' Raspberry Pi, ADS1115, PH4502C Calibration '''
import board
import busio
import time
import sys
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
# Setup
i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
def read_voltage(channel):
while True:
buf = list()
for i in range(10): # Take 10 samples
buf.append(channel.voltage)
buf.sort() # Sort samples and discard highest and lowest
buf = buf[2:-2]
avg = (sum(map(float,buf))/6) # Get average value from remaining 6
print(round(avg,2),'V')
time.sleep(2)
if __name__ == '__main__':
print('\n\n\n')
print('---- RPi-ADS115-PH4502 Calibration ----')
input('Press Enter once you have grounded the BNC connector...')
channel = None
while channel not in [0,1,2,3]:
try:
channel = int(input('ADS1115 channel 0-3: ')) # ADS.P0, ADS.P1, ADS.P2, ADS.P3
except:
print('Not a valid option. Try again.')
if channel == 0:
channel = AnalogIn(ads, ADS.P0)
elif channel == 1:
channel = AnalogIn(ads, ADS.P1)
elif channel == 2:
channel = AnalogIn(ads, ADS.P1)
elif channel == 3:
channel = AnalogIn(ads, ADS.P1)
else:
sys.exit('Error selecting an ADS1115 pin.')
print('Adjust potentiometer nearest to BNC socket to ~2.50V')
print('Starting readings. Press CTRL+C to stop...')
try:
read_voltage(channel)
except KeyboardInterrupt:
pass
view raw rpi-ads1115-ph4502c_calibrate.py hosted with ❤ by GitHub

(Link to Github file)

Step 3: Mapping the the voltage to pH readings

In this step we will map two known pH measurements to their respective reported voltages. To do this step you either need some pH calibration solution, or you can use another substance of known pH; however, I prefer pH calibration solution.

I use General Hydroponics Standard Reference Solution pH 4.01 and pH 7.0. You will want some distilled, purified, or some sort of deionized water. Use this water to rinse the probe between pH measurements.

Once you have your solutions ready, the script from Step 2 should still be reporting a ~2.5 voltage connect the pH probe to the BNC to take measurements. Place the probe in both the pH 4.01 solution and the pH 7.0 solution (rinsing in between) and record their output voltages. It can take up to 2 minutes for the sensor to stabilize, so give it time in each solution.

Now that you have voltages for 4.01 and 7.00 reference solutions, use y = mx + b to solve the linear equation and map the range.

In my situation, pH 4.01 reported 3.11 volts (3.11,4.01) and pH 7.0 reported 2.58 volts (2.58, 7.0). If y = pH and x = voltage we can solve for m by y2-y1⁄x2-x1.

7.0-4.01⁄2.58-3.11 = 2.99/-0.53 = –5.641509 = m

Once we have m we simply substitute it back in to one set, we’ll use pH 4.01. 4.01 = -5.641509(3.11) + b. Then solve for b = 21.55509299. The final formula is pH = -5.641509(voltage) + 21.55509299.

External Sources

[1] https://raspberrypi.stackexchange.com/questions/96653/ph-4502c-ph-sensor-calibration-and-adc-using-mcp3008-pcf8591-and-ads1115
[2] https://www.botshop.co.za/how-to-use-a-ph-probe-and-sensor/
[3] https://scidle.com/how-to-use-a-ph-sensor-with-arduino/

32 thoughts on “Cheap pH Meter for Raspberry Pi with ADS1115 and PH4502C”

  1. Tlacaelel says:
    January 15, 2020 at 9:18 pm

    Hi, you have this

    In my situation, pH 4.01 reported 2.52 volts (3.11,4.01) and pH 7.0 reported 3.51 volts (2.58, 7.0).

    Where did the 3.11 value come from if the reported value was 2.52?
    And where did the 2.58 value come from if the reported value was 3.51?

    Reply
    1. andrew says:
      January 31, 2020 at 10:13 pm

      I believe that was a mistake on my part. I need to correct those numbers. Thanks for pointing it out!

      Reply
  2. Ben says:
    June 14, 2020 at 7:52 am

    Thanks for these instructions – I created a modified version of your code that outputs to a file (which is read by another app) and runs as a startup script on a raspberry pi.

    Reply
    1. andrew the builder says:
      June 18, 2020 at 12:51 am

      Awesome, glad I could contribute!

      Reply
  3. Gad says:
    July 28, 2020 at 12:24 am

    I just wanted to say thank you so much to documenting and publishing this. I was attempting the same endeavor and like you was faced with an unreasonably hefty price tag. I had found the pH probe on AliExpress but I had no damn idea how to go about getting the two to communicate. Not to mention no one usually attempts with these Chinese alternatives. Anyway, I ordered it confidently and can’t wait to wire it all up.

    Reply
    1. andrew the builder says:
      July 29, 2020 at 11:53 am

      Awesome! I’m glad I could help.

      Reply
  4. Jerry says:
    November 17, 2020 at 11:15 pm

    ADS1115 datasheet tells that the absolute maximum voltage for analog inputs is VDD+0.3V. The PH sensor is outputting values between 0-5V while ADC VDD is 3.3v. How is this possible?

    Reply
    1. andrew the builder says:
      November 21, 2020 at 6:16 am

      Jerry, In step 2 we normalized the PH probe from -2.5 to 2.5v. This prevents the voltage from going above 3.3V.

      Reply
  5. Namchock says:
    March 3, 2021 at 2:15 pm

    I want to know how to fix this. ads = ADS1115(i2c)
    AttributeError : module ‘ adafruit_ads1115’ has no attribute ‘ADS1115’

    Reply
    1. andrew the builder says:
      March 3, 2021 at 2:33 pm

      Make sure you have the right module from adafruit.

      Reply
      1. Namchock says:
        March 4, 2021 at 4:22 pm

        I checked that there is a module.

        Reply
      2. Namchock says:
        March 4, 2021 at 4:23 pm

        I would like to know how do you install the module.

        Reply
        1. J.Cano says:
          August 7, 2021 at 10:12 am

          You have to install this library: https://github.com/adafruit/Adafruit_CircuitPython_ADS1x15

          Reply
          1. ืnamchock says:
            January 13, 2022 at 10:57 am

            I would like to know if the value obtained is 3.71 v, then what is PH? How do you compare or calculate the value?

  6. JP says:
    January 13, 2022 at 7:26 pm

    I’ve searched everywhere and you’re the only person who documents using the temperature pin. In my case I have tried two of these PH4502C boards, connected to ads1115, and both the temperature pin always reads 4.0v and never changes when moving to different liquids. It reads the same as the DO pin when not triggered.

    Do you have any tips on how you wired the temperature or what I could be doing wrong? It’s driving me nuts!

    Reply
  7. Peter says:
    March 17, 2022 at 11:15 am

    Hallo,
    what is the range of the offset? After shorten the BNC and messure the output voltage I can adjust in a range of 2.56 V up to VCC is this right or is my part broken?
    Thanks a lot
    Peter

    Reply
  8. Nick B says:
    June 13, 2022 at 7:59 am

    Hi,
    I have a project and trying to start out as a complete novice. Is it possible to run this using a Pico? The plan is to use solar power to run a Raspberry with pH sensor, temperature sensor and water pump.

    Reply
    1. andrew the builder says:
      September 21, 2022 at 3:49 am

      Yes, you’d have to re-write everything for pico… pico does have built in ADCs so you can really remove that.

      Reply
  9. Wag says:
    October 1, 2022 at 7:31 pm

    Hey Andrew,

    “Once you have your solutions ready, the script from Step 2 should still be reporting a ~2.5 voltage connect the pH probe to the BNC to take measurements”

    How you connect the pH probe to the BNC with the paper clip on it? should i remove the clip?

    Reply
    1. andrew the builder says:
      October 19, 2022 at 2:52 am

      Wag, once you calibrate the pH Probe you can remove the paper clip.

      Reply
  10. kittycat115 says:
    October 19, 2022 at 5:20 am

    for some reason 7.0PH @ 25c was 3.67v and 3.2PH @ 25c was 4.1v. This doesn’t seem like I’m doing this right.

    Reply
    1. Samuel says:
      February 13, 2023 at 6:57 am

      Hey, you are doing it right in my opinion. My values for ph4,7,9 are: pH4.0 = 3.64, pH7.0 = 3.32 and pH_9 = 3.12. The values in my case are not linear so for the conversion to pH I had to use the polynomial function. I used https://chat.openai.com/chat as a helping hand.

      Reply
  11. Morten says:
    June 1, 2023 at 7:26 pm

    Great script and tutorial!
    When I did the “sudo i2cdetect -y 1” I got the value UU – and the script would not run.
    I moved the i2c pins to other gpio’s (23 and 24).
    Added to the /boot/config.txt
    dtoverlay=i2c-gpio,bus=1,i2c_gpio_delay_us=1,i2c_gpio_sda=23,i2c_gpio_scl=24
    That did the trick for me.

    However:
    Once I have shorted the BNC, I can not get lower than 2.63V. What does that mean for the calculation?

    Reply
    1. Morten says:
      June 3, 2023 at 4:04 pm

      Think I solved that. 2.63 V is 5.2% higher than 2.5 V. So I substracted 5.2% of the V values for my PH4.0 og PH7.0 readings. I get the same readings with my manual measuring sticks 🙂

      Reply
  12. Shuchir Jain says:
    October 11, 2023 at 2:37 am

    Hello,
    Thank you so much for your tutorial. I just had one question- why do you “ground” the BNC connector in step 2? Why should the ADC only get positive values?

    Reply
  13. Gary says:
    January 7, 2024 at 3:51 pm

    Where do the ‘board’ and ‘busio’ modules come from?

    Reply
    1. andrew the builder says:
      January 9, 2024 at 5:19 pm

      Gary,

      This should help you out: https://learn.adafruit.com/arduino-to-circuitpython/the-board-module

      Reply
  14. Joe says:
    February 4, 2024 at 6:16 pm

    This is a really great explanation and also quite an eye-opener. I’d never really thought a out how a PH sensor did its sensing before so to know it’s calculated from the voltage is very interesting.

    What I’m wondering now is whether there’s another formula that can be used on the voltage to calculate TDS and/or EC? I’ve seen 4-in-1 sensors for sale online so could it really be as simple as another formula, or would a different component be required?

    Reply
  15. Mr Michael Matthew says:
    February 6, 2024 at 9:06 am

    I was hoping to find a Fibre Optic Sensor that I could use for my project to detect the following elements:

    Protein (g) Carbohydrate (g) Total Sugar (g) Total Dietary Fibre (g) Total Fat (g) Saturated Fat (g) Cholesterol (mg) Calcium (mg) Iron (mg) Sodium (mg) Potassium (mg) Magnesium (mg) Phosphorus (mg) Thiamin (mg) Riboflavin (mg) Niacin (mg) Niacin equivalent (mg) Folate (g) Vitamin A (RAE) Vitamin B6 (mg) Vitamin B12 (mcg) Vitamin C (mg) Vitamin D (mcg) Vitamin E (mg) Vitamin K1 (g) Beta-carotene (mcg) Lycopene (mcg) Copper (mg) Zinc (mg) Monounsaturated Fat(g) Polyunsaturated Fat(g) DHA (g) EPA (g) Trans Fat (g) Caffeine (mg) Alcohol (g) Retinol (g) Retinol Equivalent (g) Selenium (g) Carotene (g) Iodine (g) Pantothenate (mg) Tryptophan/60 (mg) Biotin (g) Chloride (mg) Manganese (mg)

    The reason that I would like a sensor for these elements, is that I am developing a device on raspberry pi with mongoDB and these are an essential part of the device.

    We want to offer better food choices from the results of the sensor.

    If this is not possible, can you direct me to another company that can produce such a sensor.

    Reply
    1. andrew the builder says:
      February 12, 2024 at 4:54 pm

      I think you’re going to have a hard time finding a sensor that can tell you water composition.

      Reply
  16. Rez says:
    September 18, 2024 at 5:43 pm

    please can someone help me it says 4.1v all the time
    i short the bnc and 4.1v
    i connect probe and 4.1v

    Reply
  17. Rez says:
    September 18, 2024 at 11:21 pm

    ok got it working
    this is better

    def read_voltage(channel):
    while True:
    buf = list()

    for i in range(10): # Take 10 samples
    ph = channel.voltage
    time.sleep(0.1)
    if ph >= 2.0:
    #print(ph)
    buf.append(ph)

    buf.sort() # Sort samples and discard highest and lowest
    print(round(numpy.median(buf), 3))

    # phvalue = 7 + ((2.48 – round(numpy.median(buf), 3)) / 0.1839 )
    # print(phvalue)
    # print(stats.mode(buf))
    # buf = buf[2:-2]
    # avg = (sum(map(float,buf))/16) # Get average value from remaining 6
    # print(round(avg,2), ‘V’)
    time.sleep(0.1)

    Reply

Leave a Reply to andrew the builder Cancel reply

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

Andrew

This is a picture of the guy who writes all of this non-sense.

  • November 15, 2024 by andrew the builder DIY Shimano Di2 Satellite Shifter for Coefficient RR Carbon Handlebars
  • December 24, 2023 by andrew the builder FAN-CTRL Update
  • October 8, 2023 by andrew the builder The Tour das Hugel Build
  • September 22, 2023 by andrew the builder My 2024 Cycling Calendar
  • March 18, 2023 by andrew the builder We Ride South DIY Rocker Plate Plans
@2023 andrewgrabbs.com
Menu
andrewgrabbs.com
  • Home
  • Cycling
    • Bicycle Builds
    • Events
    • Nutrition
  • DIY