How to Connect a pH Sensor to a Raspberry Pi
Whether you want to monitor a pool, aquarium or some other body of water, connecting a pH sensor to a Raspberry Pi can be achieved relatively easily. In this tutorial I’ll be using the Atlas Scientific pH sensor, it’s an industrial grade sensor that works well with the Raspberry Pi, it’s fully submersible up to the BNC connector in both fresh and saltwater. The sensor works using either serial communication or via the I2C protocol, for this example, I will be configuring the sensor to use the I2C interface on the Raspberry Pi.
To configure the Pi I am assuming that you are running the latest version of Raspian, have the ability to connect to your Pi either through SSH with putty and FTP with Filezilla, or directly with a keyboard and monitor. If you haven’t set-up your Pi yet then check out the getting started section.
Materials
In this tutorial I will be using the following materials:
- Raspberry Pi (2, 3 or 4)
- Micro SD Card
- Power Supply
- Atlas Scientific pH sensor kit
- Breadboard
- Jumper Wires
- Adafruit T-Cobbler Plus (Optional)
- Raspberry Pi Case (Optional)
The first thing we need to do is enable the I2C modules on the Pi. This is done by entering the following at the command prompt to start the configuration tool.
sudo raspi-config
select option 5 – Interfacing Options
select option P5 – I2C
select “Yes” for all the questions and reboot the Pi
sudo reboot
Note: The GPIO pins 2&3 on the RPi have now been configured as the Serial Data Line (SDA) and Serial Clock Line (SCL) for use by the I2C protocol. The TX connection of the sensor circuit will connect to SDA (pin 2) on the Pi and the RX connection will go to the SCL (pin 3).
After the reboot open the terminal and ensure that all the Raspbian packages are up to date, enter the following
sudo apt update
sudo apt dist-upgrade
sudo apt autoremove
sudo apt clean
Next, check or add the Raspbian i2c tools package
sudo apt install i2c-tools
i2cdetect -y 1
This should produce the following without the sensor attached.
Now that we have our I2C module working correctly we can go ahead and connect our pH sensor.
When describing the physical pin connections I will be following the GPIO pin numbering convention shown below.
Firstly we need to get the pH circuit into the correct mode, when delivered the pH circuit will be in UART (serial) mode, the pH circuit has to be manually switched from UART mode to I2C mode. When this is done the pH circuit will have its I2C address set to 99 (0x63).
Using your breadboard perform the following actions
- Cut the power to the device
- Disconnect any jumper wires going from TX and RX to the Pi
- Short the PGND pin to the TX pin
- Power the device
- Wait for LED to change from Green to Blue
- Remove the short from the probe pin to the TX pin
- Power cycle the device
The device is now I2C mode.
The Pi and pH circuit are now configured so we can go ahead and connect it all together
Assuming that all of the parts are now mounted on your breadboard
- Connect the GND pin of the pH circuit to the ground pin of your RPi.
- Connect the TX(SDA) pin to GPIO pin 2.
- Connect the RX(SCL) pin to GPIO pin 3.
Note: Do Not Use jumper wires for these connections or your readings will not be accurate.
- The PRB and PGND pins should be connected via your breadboard to the center and shield pins of your BNC connector.
- Finally, power your pH circuit by connecting the Vcc pin to the +3.3V pin.
You can now run a quick test to prove that we are set up correctly, from the command prompt enter the following:
i2cdetect -y 1
you should see the following response, if not then check your connections, ensure the light on the pH circuit is blue and reboot your RPi.
In the image above I have 3 sensors connected to my RPi, the pH sensor connection is indicated by Hex value 63. The factory pre-set address for the pH sensor is 99 or 63 in hexadecimal as mentioned above, if you have more than 1 pH circuit connected then you will need to specify a different value. To do this we need to add some python code to our RPi.
Atlas Scientific provides the python code that I will be using here for interfacing with the pH Circuit.
We start by importing the required python modules
#!/usr/bin/env python
import io # used to create file streams
import fcntl # used to access I2C parameters like addresses
import time # used for sleep delay and timestamps
import string # helps parse strings
Next, we add the class code to interface with the pH circuit (or any other Atlas Scientific circuit for that matter)
class atlas_i2c:
long_timeout = 1.5 # the timeout needed to query readings and
#calibrations
short_timeout = .5 # timeout for regular commands
default_bus = 1 # the default bus for I2C on the newer Raspberry Pis,
# certain older boards use bus 0
default_address = 99 # the default address for the pH sensor
def __init__(self, address=default_address, bus=default_bus):
# open two file streams, one for reading and one for writing
# the specific I2C channel is selected with bus
# it is usually 1, except for older revisions where its 0
# wb and rb indicate binary read and write
self.file_read = io.open("/dev/i2c-" + str(bus), "rb", buffering=0)
self.file_write = io.open("/dev/i2c-" + str(bus), "wb", buffering=0)
# initializes I2C to either a user specified or default address
self.set_i2c_address(address)
def set_i2c_address(self, addr):
# set the I2C communications to the slave specified by the address
# The commands for I2C dev using the ioctl functions are specified in
# the i2c-dev.h file from i2c-tools
I2C_SLAVE = 0x703
fcntl.ioctl(self.file_read, I2C_SLAVE, addr)
fcntl.ioctl(self.file_write, I2C_SLAVE, addr)
def write(self, string):
# appends the null character and sends the string over I2C
string += "