ORP / PH / Temperature Data Logger




About: Patrick is a water quality and environmental regulatory compliance manager with an interest in all things technological and gadgety. And everything else besides.

As a Water Quality professional working in the drinking water field, I know how important it is to accurately monitor the disinfectant levels in the drinking water that gets served to the public.  Usually, that means taking weekly grab samples in the distribution system and measuring free chlorine or total chlorine residual via a DPD colorimetric test.  Sometimes, however, it would be nice to know what’s going on with the disinfectant residual when you’re not out there to take a sample.  It would be nice to log the residual over time.  That’s why I wanted to put together an inexpensive data logger that would measure and log pH, oxidation-reduction potential (ORP), and temperature.  From those three parameters, the disinfectant residual can be approximated, not to mention that they are interesting parameters to measure and log in their own right.  In my research for this project, I also came across some other uses in which this device might come in handy.  It seems that aquarists regularly measure these parameters to keep their aquariums healthy, and it can also be used to keep track of oxidant levels in apool or spa. These are three very commonly measured parameters in water system security devices that are being used more and more to make sure that a water system is not being tampered with. And, it can be used in the lab for testing oxidant dosing, or measuring reaction kinetics.

My criteria for the project were that it had to be fairly easy to make; relatively inexpensive; and pretty accurate.  I think what I’ve created meets those criteria, and I hope you do, too! 

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Parts and Supplies

Here are the materials I used in my project, and where I purchased them:

1. Arduino Uno:   http://stores.ebay.com/lemonbleue/
2. Prototyping Shield:  http://stores.ebay.com/chippartnerstore/
3. pH probe:  http://stores.ebay.com/lotsgoods88/
4. ORP probe:   http://stores.ebay.com/eseasongear/
5. pH & ORP circuits:  https://www.atlas-scientific.com/embedded.html
6. BNC connectors:  https://www.atlas-scientific.com/embedded.html
7. Temperature sensor: http://www.ebay.com/usr/saymlove
8. LCD keypad shield: http://stores.ebay.com/womarts/
9. SD card shield: http://stores.ebay.com/csmqshop/
10. 170 tie point breadboards: http://stores.ebay.com/chippartnerstore/
11. Nylon mounting hardware: http://stores.ebay.com/audiowind2010/
12. Project box: http://www.discountofficeitems.com/school-supplies/student-teacher-supplies/basic-school-supplies/pencil-boxes-pouches/advantus-super-stacker-stackable-pencil/p296171.html?q=pencil%20boxes

Various and sundry other parts were used, such as all the jumper wires, were purchased from e-bay vendors and other electronic supply companys.

Step 2: Construction - Electronics

I have attached a diagram of the Fritzing wiring diagram for this project as a pdf.  It isn’t laid out exactly like it is in my project box – the diagram utilizes a large breadboard instead of a prototyping shield and a smaller breadboard; and the LCD shown isn’t the exact one I had, nor is the temperature sensor.  Also, I couldn't find Fritzing library files for the Atlas Scientific pH and ORP circuits, so I had to make my own for illustrative purposes, as well as modify the BNC connectors I could find.  But the diagram does show what wires I have hooked up to which pins on the Arduino, which is the important part to get it to all working right with the programming.  I used an LCD with a keypad because that’s what I had lying around; the keypad isn't used, however, so you can just use any 16x2 LCD without the keypad. 

I got everything to work together outside of the project box first, then disassembled it and put it back together inside the box.  For the LCD, I took a 170 tie point breadboard, cut it in half along the middle spacer, and then used half for each side of the LCD.  I mounted the pH and ORP circuits on another small breadboard and cut holes in the side of the plastic project box for the BNC connectors to stick through, connecting the BNC connectors to the breadboard with the pH and ORP circuits with jumper wires.  I did the same for the USB and power connectors for the UNO, and for the temperature probe.  I also drilled some small holes on the back of the box to put small nylon screws through to secure the UNO and the temperature circuit.

Step 3: Construction - Sample Cell

The probes, of course, have to be in contact with the solution being sampled.  If the unit is being used in the laboratory, you can just immerse them in the container, such as a beaker or an Erlenmeyer flask, or use a probe holder.  If your doing work in the field, you may need a sample cell to put the probes in, and then run the water through that.  The sample cell I built for this purpose is very simple.  I used a 2" diameter piece of PVC pipe with caps on the end.  In one end, which will be the bottom, I drilled a hole and inserted a barbed fitting for 1/4" ID hose.  This will be the water inlet.  On the other end, I drilled a small hole for the temperature probe, and two 1/2" diameter holes for the pH and ORP probes.  On the side near the top, I drilled a hole for a barbed fitting for a 1/2" ID hose.  This will be the outlet for the water being sampled.  The small diameter hose is attached to the water source, which is turned on at a very low rate of flow.  The water flows into the flow cell through the bottom and overflows through the larger fitting on the side near the top.  The water level is sufficient to keep the probes continuously covered.  I added a couple of eye screws and a length of chain at the top to help secure the sample cell in the field.

Step 4: Arduino Code and Data Manipulation

I am definitely not a very experienced coder.  The attached pdf of the code, also pasted below, was developed using Atlas Scientific code for both their pH and ORP circuits; one-wire temperature sensor code from Hacktronics (http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html); and other bits and pieces gleaned from a myriad of chat boards and other internet posts.  Thank goodness for the open source community!  Please feel free to comment on how best to clean it up and make it more functional.  It will be important to go to the Hacktronics tutorial on finding the address for your particular temperature sensor, and then go in to the code and replace the address I have there with the one for your sensor to get it to work correctly.  That tutorial can be found here - http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html .

As written, the instrument will take a ph, ORP, and temperature reading every 12 seconds; that time interval is easily adjusted by changing the delay in the program on line 95.  It will display the readings on the LCD screen, and it will log the data to the SD card in a text file named datalog.  When I am finished logging data, I open the file in Word, and it looks like the picture.  I then do a search and replace for “^p,” (that’s a paragraph mark and a comma) and replace with a “^t” (that’s a tab character) to get tab delimited data.  I then save the file and open it with Excel as a tab delimited text file.  This gives me a spreadsheet with the elapsed time since the program began, in milliseconds, in the first column; the pH in the second column; the ORP in the third column; and the temperature in degrees Celsius in the fourth column.  If you keep track of the time the program began, you can then calculate using Excel the time each reading was taken.  Instructions to manipulate the data file are given in more detail in the attached file.

#include <LiquidCrystal.h>        //LCD library
#include <SoftwareSerial.h>       //SoftwareSerial library  
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>                  //SPI library for SD card
#include <SD.h>                   //SD card library

//Serial ports
#define orprx 2                         //define what pin orp rx is going to be
#define orptx 3                         //define what pin orp Tx is going to be
SoftwareSerial orpserial(orprx, orptx); //define the ORP soft serial port
#define phrx 14                         //define what pin pH rx is going to be
#define phtx 15                         //define what pin pH Tx is going to be
SoftwareSerial phserial(phrx, phtx);    //define the pH soft serial port

//Temperature probe setup
#define ONE_WIRE_BUS 19                  // Data wire is plugged into pin 19 on the Arduino
OneWire oneWire(ONE_WIRE_BUS);           // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire);     // Pass our oneWire reference to Dallas Temperature.
DeviceAddress insideThermometer = { 0x28, 0xB4, 0x6B, 0xC8, 0x04, 0x00, 0x00, 0x1F };     // Assign the addresses of your 1-Wire temp sensors.

//define ORP variables
char orp_data[20];                    //20 byte character array to hold ORP data
char orp_computerdata[20];            //20 byte character array to hold incoming data from a pc
byte orp_received_from_computer=0;    //we need to know how many character have been received.                                
byte orp_received_from_sensor=0;      //we need to know how many character have been received.
byte orp_startup=0;                   //used to make sure the arduino takes over control of the ORP Circuit properly.
float ORP=0;                          //used to hold a floating point number that is the ORP
byte orp_string_received=0;           //used to identify when we have received a string from the ORP circuit

//define pH variables
char ph_data[20];                    //20 byte character array to hold incoming pH
char ph_computerdata[20];            //20 byte character array to hold incoming data from a pc
//byte pc_debug=0;                   //if you would like to debug the pH Circuit through the serial monitor(pc/mac/other). if not set this to 0.
byte ph_received_from_computer=0;    //we need to know how many characters have been received from computer                               
byte ph_received_from_sensor=0;      //we need to know how many characters have been received from pH sensor 
byte ph_startup=0;                   //used to make sure the arduino takes over control of the pH Circuit properly.
float ph=0;                          //used to hold a floating point number that is the pH.
byte ph_string_received=0;           //used to identify when we have received a string from the pH circuit.

//LCD set up
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // select the pins used on the LCD panel

void setup(){
     Serial.begin(38400);        //enable the hardware serial port
     orpserial.begin(38400);     //enable the software serial port
     phserial.begin(38400);      //enable the software serial port
     sensors.begin();            //start up temp probe library
     sensors.setResolution(insideThermometer, 10);       // set the temp probe resolution to 10 bit
     lcd.begin(16, 2);           // start the lcd library
     pinMode(10, OUTPUT);

void loop() {
sensors.requestTemperatures();         //read Temp probe          
  if(orpserial.available() > 0){           //if we see that the ORP Circuit has sent a character.
     orp_received_from_sensor=orpserial.readBytesUntil(13,orp_data,20); //we read the data sent from ORP Circuit untill we see a <CR>. We also count how many character have been recived. 
     orp_data[orp_received_from_sensor]=0; //we add a 0 to the spot in the array just after the last character we recived. This will stop us from transmiting incorrect data that may have been left in the buffer.
     orp_string_received=1;                //a flag used when the arduino is controlling the ORP Circuit to let us know that a complete string has been received.
  if(phserial.available() > 0){          //if we see that the pH Circuit has sent a character.
     ph_received_from_sensor=phserial.readBytesUntil(13,ph_data,20); //we read the data sent from ph Circuit untill we see a <CR>. We also count how many character have been recived. 
     ph_data[ph_received_from_sensor]=0; //we add a 0 to the spot in the array just after the last character we recived. This will stop us from transmiting incorrect data that may have been left in the buffer.
     ph_string_received=1;               //a flag used when the arduino is controlling the pH Circuit to let us know that a complete string has been received.    
void printTemperature(DeviceAddress deviceAddress)
    int decPlaces = 0;     // set temp decimal places to 0
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    lcd.print("Error getting temperature");
  } else {
     lcd.setCursor(0,0);   //set position on lcd for pH
     lcd.print(ph, 1);     //send pH to lcd
     lcd.setCursor(7,0);   //set position on lcd for ORP
     lcd.print(ORP, 0);    //send ORP to lcd
     lcd.setCursor(0,1);   //set position on lcd for Temp
     lcd.print("C ");
     lcd.print(tempC,decPlaces);     //display Temp in celsius
     lcd.print(" F ");
     lcd.print(DallasTemperature::toFahrenheit(tempC),decPlaces);  //convert celsius to farenheit
     delay(10000);          //we will take a reading ever 10000ms

orpserial.print("R\r");                     //send it the command to take a single reading.
   if(orp_string_received==1){              //did we get data back from the ORP Circuit?
     ORP=atof(orp_data);                    //convert orp_data string to ORP float
     if(ORP>800){Serial.println("high\r");} //This is the proof that it has been converted into a string.
     if(ORP<800){Serial.println("low\r");}  //This is the proof that it has been converted into a string.
     orp_string_received=0;}                //reset the string received flag.
phserial.print("R\r");                      //send it the command to take a single reading.
   if(ph_string_received==1){               //did we get data back from the ph Circuit?
     ph=atof(ph_data);                      //convert ph_data string to ph float
     if(ph>=7.5){Serial.println("high\r");} //This is the proof that it has been converted into a string.
     if(ph<7.5){Serial.println("low\r");}   //This is the proof that it has been converted into a string.
     ph_string_received=0;}                 //reset the string received flag.    

long currentTime = millis();                                // Get the current time in ms (time since program start)
File dataFile = SD.open("datalog.txt", FILE_WRITE);         //open the file
  if (dataFile) {                                            // if the file is available, write to it:
      dataFile.println(currentTime);                         // logs the time in milliseconds since the program started
      dataFile.print(",");                                   //inserts a comma
      dataFile.println(ph);                                  //logs the pH
      dataFile.print(",");                                   //inserts a comma
      dataFile.println(ORP);                                 //logs the ORP
      dataFile.print(",");                                   //inserts a comma
      dataFile.println(tempC);                               //logs the temperature in degrees C
      dataFile.print("\r");                                  //inserts a return character

Step 5:

And that's it!  Now it's all ready to go into the field and start collecting data, or get used in the lab for something like reaction kinetics monitoring.  I hope I've presented my idea in a fairly organized fashion that didn't leave you with too many questions, but if you have any, please be sure to ask.  And I would love any comments on how to improve things as well. Thanks, and please vote for my project if you find it interesting.

Build My Lab Contest

Fourth Prize in the
Build My Lab Contest

Microcontroller Contest

Participated in the
Microcontroller Contest

Be the First to Share


    • Made with Math Contest

      Made with Math Contest
    • Multi-Discipline Contest

      Multi-Discipline Contest
    • Robotics Contest

      Robotics Contest

    71 Discussions


    9 months ago on Step 5

    What sensors are used to measure chlorine ?


    1 year ago

    This is a great build, and I have some ideas to share with you regarding housings. Take a look at the waterproof PVC housings we used at http://www.mdpi.com/1424-8220/18/2/530 (open access - pdf is free to download) The 4" rubber bottomed housing shown there can easily be made at 6 & 8" diameters. We have had that style out on deployments in caves at 100% humidity for years with no water leaks, You can pot things like the display on the upper surface in clear loctite e30-cl epoxy.

    Kim Erso

    3 years ago

    this is awesome! can you teach me how to command my SD and RTC to log data after every two hours? thanks for your reply :)


    4 years ago

    What type of output is given by the pH probe ??
    Can i directly connect the output of the probe to arduino board ?

    6 replies

    Reply 4 years ago

    I'm not totally sure, but I believe it outputs a voltage difference between the measuring electrode and the reference electrode. It's so weak though that you need an amplifier, so I don't think you could plug it directly into the Arduino.


    Reply 4 years ago

    I will use an amplifier for that
    I heard that it is very difficult to calculate the pH from pH probe as the output of probe is a sine wave and we have to pick a particular value for calculations. Is it so ??


    Reply 3 years ago

    there is a sensor called sen0161 ph metter, in www.dfrobot.com, this one includes a module whit the comparator that you are looking for, ready to get conected with arduino, there also is the code and everything you will need.



    Reply 4 years ago

    I'm afraid that I don't know the answer to that one. Sorry, but let me know what you find out!


    Reply 4 years ago

    Sir, good eve. I want to ask if you know the temperature sensor used and and the probes used for the pH and ORP circuits? I am having a hard time finding the exact manufacturing/part number of the components. If you can help me sir, can you provide me a full list of the componets with its part numbers?? thanks in advance sir.


    Reply 4 years ago

    http://www.atlas-scientific.com/ You can find pH sensor and ORP sensor and board from here or you could buy pH probe from ebay if they do not deliver in your country.
    As in for temperature there are various sensors like LM35 which u can use in your project.


    3 years ago

    hello my friend!

    im making a very similiar project, but i have a question, how do you calibrate de orp probe? in the manual says to DO NOT PRESS the calibrate button when the prove is connected, but when you want to change the offset, in the progaming code, to get zero drift voltage, the manual says that you have to PRESS the calibration button and see in the serial monitor a reading in milivolts that concerns the offset value we are looking for, i hope you can help me, or any body could, a hug! and thanks!


    3 years ago

    can i delete the line

    Serial.begin(38400); and use the pin 0,1 as normal input/output?

    1 reply

    Reply 3 years ago

    Not sure. My suggestion is to try it and see what happens. Experiment!


    3 years ago

    Thus a 5% error would be plus or minus 0.268 pH for 5.35.


    3 years ago

    Um a plus or minus 5% error is above the range of error. You may have to clean your probe with hot 50 degrees C potassium chloride. The error rate for a good functioning ph meter is +- 0.1 ph or 0.01 ph.

    Ph error for 5.35

    Min: 5.08 ph.

    Max: 5.61 ph.

    meaning the range for 5.35 could be 5.08 or 5.61 pH.



    3 years ago

    Another problem may be that you cannot leave a ph meter for long periods of time running in water due to the fact that debris and other things would eventually clog the sensitive and thin layer inside the ph meter and could especially over a period of time. When placed in a ph solution you need buffers like Potassium chloride to re establish the ions between the ph meter. Just if you stored a ph meter in water this would also destroy the ph meter. This could work but you need to check and calibrate the ph meter every day or so or even half a day to protect the ph meter. It is not RECOMMENDED to place a ph meter in water more than 4 -5 hours. (This is what the manual says too.) Also replacing frequently the ph meter would make this very expensive!! (These are a few problems with it) liked that you tried and the theory is smart.

    1 reply

    Reply 3 years ago

    Right again - pH probes can be sensitive and subject to degradation if stored in water. However, that said, I've been doing tests with a very inexpensive pH probe and letting it run for long periods of time in an aquarium I've set up as sort of an environmental waters test tank: it's a "dirted" tank with many live plants, a good flow of water, several fish, snails, etc. My pH probe has been going for a couple of months now with only the occasional wipe with a clean cloth. I check it in calibration solutions of pH 4, 7, and 10 about every two weeks, and it's been consistently whithin plus or minus 5%, which is really good for a cheap probe.


    3 years ago

    This sound very interesting and I liked the steps that you provided. However is this a bit complex? I could get a good 130 dollar ph meter from a certain online store and it has build in ph, temperature, and records data with memory. What was the total cost of doing this? Are there any advantages or disadvantages of using this? I log all of my ph data by paper and sent it to the computer.

    1 reply

    Reply 3 years ago

    You're absolutely right - there are many ways to solve any given problem, and yours certainly work. I was coming at this from the point of view of having not just pH, but temp and ORP as well. And I did not build this particularly for an aquarium, but for remote locations like water storage tanks or field monitoring of environmental waters. In that case, being able to log the data for long periods is quite helpful. Just depends on your application.