, , , , ,

(but before I begin…I’ve had a hard time getting a post out recently.  I am in the middle of the most amazing course offered by Contextual Electronics on learning how to build a PCB.  Each day brings on a lot more to learn.  So far taking this course has been a wonderful experience.  There is a fee and I have no reason to sing its praises – although so far it is exceeding my expectations. Once I learn and go through the process of building a PCB, my goal is to build PCBs and cases of the nodes and Base Station.)

In a previous post I discussed the Air Sensor Node.  In this post I’ll be building a Water Sensor Node.


The Water Sensor Node will measure properties of the water that are important to a plant’s growing cycle – water temperature, EC, and pH.  It will respond to a request to get and send readings to the Base Station.

The Goals

In this post I will:

  • identify and discuss the choice of components for my Water Hydroponics Sensor Node.
  • run the water sensor node through a sample sketch to show its features.

The Parts List

Part  Cost  Info
pH Kit


Previous Post
Conductivity Kit $108.87  Atlas Scientific Web Page
Water Temperature sensor  $6.40  Previous post
10 screw terminals


Wires + breadboard    –  from parts
Moteino w/ RFM69HW @ 433  $24.14   Previous post
wall wart      –    from parts 

Total: $250.41  (shipping included)


I decided against an LCD and buttons to locally control the node.  Instead I will control nodes through an app I’ll write for my iPhone.  More on that in a later post.  By using an iPhone app, I’ll be minimizing the additional hardware cost and complexity added in by an LCD and buttons.  

pH and Conductivity Sensors

The pH and Conductivity kits  are both from Atlas Scientific.   



I bought the kit.  The kit includes a “circuit” PCB (which is the small rectangular PCB near the BNC connector and below the probes on the above images of the kits) which is breadboard friendly. This is ideal for Arduino prototyping.  They also supply sample Arduino sketches which were very helpful in getting used to how the probes work.  And very important – their support is excellent.  I like what Atlas Scientific has done with their products.  Their “secret sauce” (IP) – measuring pH and conductivity in this case – is locked into the software of the sensor’s circuit board.  I am relying on their expertise and quality of equipment.

I have come across these challenges:


  • The more prototypes I do the more I lose time on faulty wiring!  Even more than usual with my Arduino prototypes, it is easy for something to affect the wiring to the point the circuit doesn’t work.  The common occurrence for me was the PCB holding the BNC would not reliably secure itself into my breadboard.
I found this gem, but have not ordered any:
This is  the Single Circuit Carrier Board.  It gets rid of the wiring between the BNC and the circuit.
  • The circuits use the SoftwareSerial library. The SoftwareSerial library is limited to listening to one port at a time.  In order to support two sensors, I needed to switch which port I was listening on and also keep track of the two instances representing the SoftwareSerial ports when the sketch is running.  Perhaps a better communications method between the Arduino and the circuit is I2C.
  • It wasn’t uncommon for roughly 30-50% of the Conductivity readings to contain non-printable ASCII (junk) characters.  My thoughts are many of these errors are caused by the two challenges noted above as well as noise within the circuit.
  • I wish there I didn’t have to choose which Conductivity probe.  This will be discussed more later.  The challenge is the K0.1 probe can detect the conductivity for a lot – but not all – of the plants.  Some plant’s conductivity readings fall within the K1.0 probe.
  • I’m lazy.  Thus, the required calibration is “one more thing.”  i note more about calibration later on.  I wish there was an easier way to calibrate, or it self calibrated, although I have no idea how it could self calibrate.  I guess I am truly lazy.


It is always a good practice to not single source.   I have not investigated alternatives.  I will “lock and load” on the Atlas Scientific products for now so that I can focus on the tons of other aspects of this project that I need to complete.  When I have time I will evaluate options like the pH sensor from Sparky’s Widgets.  I like the fact that it uses I2C to communicate between the Arduino and the sensor.  

Design Constraints

My design constraints include:

  • integrates with Arduino
  • does not require me to have to create algorithms to measure pH and conductivity based on the characteristics of the liquid the probe is in.  I want to leave this to experts.  I am assuming the folks at Atlas Scientific have experts on staff that have a deep knowledge on how to get and calculate these measurements as well as provide a robust solution.  I use “assuming” because their web site does not provide any company/people info.  I might be incorrect – I could be buying nice packaging and assuming expertise because of the professionalism of the presentation and support.  I read this negative comment on the Sparkfun product post but have not talked with AtlasScientific or the person that wrote it:
 oneRSP2k | about 3 months ago *  2

I have had nothing but problems with this probe. It provides Inaccurate readings. The pH probe cannot be submersed, only the tip can, otherwise you will ruin the probe. We purchased this in order to speedup development time, not donate beta testing time to Atlas Scientific. It nearly cost me a client. If you read through their documentation you will find glaring errors that indicate issues with their document review process.  We also had several of their temperature probes (ENV-TMP-D) shipped to us that read almost 3deg C high at room temperatures (factory calibration). When I called them on this, they confirmed they “had a bad batch” but didn’t offer to replace my bad sensors. Save your money and time and look into another solution

While comments like these add to my concern that the product is not as robust and full of expertise as I assumed, I also put them in perspective after creating and shipping software!

  • accurate measurements of plants in a hydroponics growing environment
  • easy to use.  For example – both circuits use the same commands – which require sending commands such as “r\r” to get a sensor reading back as a string.
For the most part, the products from Atlas Scientific meet these requirements.  I say for the most part because the circuits use the Software Serial library to communicate with the Arduino.  There are two challenges I had with this: 1) Results are returned as a string.  About 1 in 5 readings were corrupted with non printable ASCII characters. 2) only one Software Serial port can be listening at a time.  Perhaps an I2C interface with the Arduino would have been a better choice than Software Serial.

 In-Home Wireless

I’m pretty sure the RFM69W will work well for the water node.  For now I’m sticking with the RFM69HW since I will most likely be running a water node from a wall wart.  The power will need to be there since I will need it to run pumps, lights, and other equipment.  

Power Source

The Conductivity circuit needs 5V.  Everything else can run at 3.3V.  Since the Moteino provides a voltage regulated 3.3V, I used a leftover 5V cell phone charger wall wart when placing the water node where it will be used.  I took the covering off the wire and used screw terminals I found on Sparkfun. 



I bought ten since a big expense was in shipping ($3.69).  The screw terminals are ok, not great.  I ended up doing what this guy recommended:

SD | about 3 years ago 1
reply | report
I tried plugging one of these in my breadboard (probably not meant to be used with a breadboard) and it wasn’t going in very well with the pins the way they are built. All I had to do to make it work was twist the pins 90° with some needle nose pliers and now this little baby plugs right into the breadboard nice and snug.

Even after doing this the screw terminals would occasionally pop out.  Bummer.

For debugging, I use the Moteino’s 3.3V.  Although the Conductivity circuit requires 5V, it will return results at 3.3V – although many are not usable.  This means switching wiring on the Moteino such that when the water node is powered by the Wall Wart – Moteino’s Vin is hooked up. .


 When the water node is getting power through USB, Moteino’s 3.3V is hooked up to provide power to the sensors

pH Measurements 

As shown in the image below, keeping the pH at the right level for a plant is an important aspect of healthy growth.  Since how much of a nutrient a plant will absorb depends on the pH,  as the plant is growing it is important to first check and adjust the pH level before checking and adjusting the nutrients based on conductivity readings.



I discuss my first use of Atlas Scientific’s pH sensor in a previous post.  

Conductivity Measurements

(here is a FAQ on why it is important to measure Electrical Connectivity when practicing hydroponics)..

 (please see this post if you need a backgrounding in TDS vs. EC)

The first thing I needed to do was choose a conductivity probe.  Atlas Scientific offers three types of conductivity probes (discussed in this document).: 

K0.1…………. 5.94 to 1,620
K1.0…………. 702 to 21,600
K10.…………. 19,440 to 49,680

 The values are in TDS.  So which one?  I will be using the recommended values from this chart.    Armed with this info, and also with feedback from the great people on the hydro subreddit, the “best” probe for hydroponics is the K0.1.  Not unusual – I let the excitement of buying a probe come before looking at the chart and verifying with other folks….I got the K1.0.  I’ll be using the K1.0 until I can replace it with the K0.1.  The other mistake was buying the kit on eBay versus directly from Atlas Scientific.  When a smaller company is involved, I have always found  the best support comes directly from the folks who make the product.  Given my own experience as a small business shipping software, I know how hard support can be for folks like me who tried to save a few bucks.  In the future, I wish to support Atlas Scientific’s efforts and will buy directly from them.

The probe returns three readings.  Each reading is separated by a comma:

<EC>,<TDS>,<salinity value>

The example given in the EC circuit data sheet:

Example: 50000,32800,32<CR>

Salinity Value

According to this book,  the salinity should go no higher than 50.

it [Sodiium] should not be in excess of 50 ppm.


Before using the sensors and once a year after that, they need to be calibrated.  I am not going to cover the commands and actions for calibration in this post.  You will need to do this before taking readings.

As noted the Conductivity Circuit’s data sheet:

In order to provide the engineer with the greatest possible accuracy E.C. Circuits now ship uncalibrated. This is because micro voltage changes in your circuit design cannot be compensated for at the factory. 

Calibration requires calibration solutions.  Both of the kits I bought included the calibration solutions shown below.  

I’ll discuss how I calibrated the probes when I go into the Arduino Sketch I wrote for the Water node.


I was thrilled to move from a 5V Arduino environment to a 3.3V Moteino setup.  That is until I looked more closely at the conductivity circuit.  While the pH circuit can run at 3.3V or 5V, the conductivity circuit must run at 5V.  While a bit of a pain, the mixture of 5V and 3.3V parts is getting pretty common in my circuits.  I did try running the conductivity circuit at 3.3V.  The readings showed more errors than I got when running the circuit at 5V.  I ended up powering the Moteino, pH circuit, and conductivity circuit with a 5V Wall Wart that I had lying around which originally charged a cell phone I owned in the past.  I hooked it up to the breadboard as shown in an earlier image.  

Both the pH and conductivity sensor components are easy to include in a circuit using a bread board.  

My familiarity with the pH probe was a time savings in getting started with the conductivity sensor.  I used the easy to follow wiring diagram to set up the probe connector and conductivity stamp on a breadboard and then hooked it up to the Arduino.




I bet a major support issue is how the BNC connector should be wired to the pH circuit.  In the first video I watched on wiring the circuit and BNC connector, the wiring used a wire between the stamp and connector.  Now – as shown in the picture – the recommendation is to align the connector and stamp to share the same row of pins.  

Here’s what I ended up with:



The Sketch

For the past few weeks I was implementing a water sensor node experience in which the node constantly sent readings to the base station.  I then decided that my priority was not gathering readings for post analysis, but rather getting readings when I request them from my iPhone.  Thus, my sensor reading collection model went from constantly getting readings and sending them to the Base Station to the Base Station requesting a reading.  This drastically simplified the base station’s job since it no longer had to send data to an Internet service such as Google Docs or Xively.  

Now the job requirements of the Water Node include:

  • Commands can come from the Base Station as well as locally through the serial port (for easier debugging).
  • measuring and sending (temperature corrected!) the readings for the water temperature, EC, and pH within the nutrient tub when requested by the Base Station.
  • automatically adjust pH based on what is growing (future)
  • automatically adjust EC based on what is growing (future)
I will use Mains electricity as the power source since I will need this power source for the other parts of the system such as LEDs and pumps. 

Taking Readings

The good news is the sensors use the same commands to take sensor readings.  I evolved the sketch provided within the documentation available for the EC sensor.  Please open up this sketch if you wish to follow along.   The readings that will be taken include water temperature, pH, E.C., and salinity. Things to note:
  • Results are returned as character strings.
  • As noted earlier, the SoftwareSerial library is used as the communication method between the Arduino and the circuit.
  • The same commands are used for both sensors.  Thus, the learning curve when introducing a new sensor is much lower than if I mixed circuits from other vendors.
  • While not obvious in the sketch – in fact, the simple sketch provided by the conductivity sensor does not do this probably because the sketch is generic to other sensors (like the pH sensor) – how to take measurements are different depending on the sensor.  With the pH sensor, I can take one reading (or more accurately enough readings until I get one that does not contain non-printable ASCII characters).  With the conductivity sensor, the recommendation in the circuit data sheet is to take 25 readings and then use the next (accurate) reading.
  • The sketch allows any of the commands to be passed in.  This means I can calibrate (once a year) and get readings (often).

The Sketch I Wrote

You can download the sketch – waterNode_03.ino from here.  I will go over the general points here but you’ll need to look at the sketch to get a better feel for all that is going on.  

The water temperature sensor was discussed in this previous post.  I copy/pasted the getTemp() function from Sparkfun’s H20_pHrobe.ino sketch.  The function is quick and gets valid results.


 Alas, the Arduino IDE does not have much in the way of debugging support.  Instead I liberally sprinkle the sketch with DEBUG_PRINTXXX macros found in debugHelpers.h.  

#ifdef DEBUG

#define DEBUG_PRINT(x)  Serial.print (x)

#define DEBUG_PRINTHEX(x) Serial.print(x,HEX)

#define DEBUG_PRINTF(x) Serial.print(F(x))

#define DEBUG_PRINTLN(x) Serial.println(x)

#define DEBUG_PRINTLNF(x) Serial.println(F(x))


#define DEBUG_PRINT(x)

#define DEBUG_PRINTF(x)

#define DEBUG_PRINTLN(x)




These can be turned on or off using the #define DEBUG.

Sending a Command

There are two ways a command can come to the water node: locally via a serial monitor which is very useful when debugging and from the Base Station using the RFM69HW to communicate between the two devices.  The code that will get executed when a character comes in from the serial port is found in the serialEvent() function.  How serialEvent() works is covered in the docs on Arduino functions.  The code that gets executed when a command comes from the base station occurs in the loop() function within the code if(radio.receiveDone()){}.  

Serial Monitor 
Entering a ? will display the available commands. Any of the commands listed in the circuits document – either the pH or the Conductivity circuits – can be sent to through the serial monitor.  Entering a 0 changes which port is listening for sensor readings.  If I enter a 0, the readings will come through the pins designated for the pH circuit.  If I enter a 1, the readings will come in through the pins designated for the conductivity circuit.

Base Station
A command from the Base Station is really a command sent from my iPhone.  I’ll detail this in another post…the way I communicate from Base Station to iPhone is through an HTTP request.  Thus, when a reading comes in, I send a string containing all sensor readings as soon as I can.  I’ll send cached results if I cannot get a return in a quick enough time.  The Base Station sends the ‘a’ command to the water node to request (and hopefully receive!) all readings within a string.

Taking a Reading

pH and Conductivity

After trying different options to read the pH and conductivity sensors, and honoring the constraint that 25 readings are needed before a valid conductivity reading should be taken, I decided to use the “C\r” (continuous) command to retrieve readings.  The way the sketch reads the sensors:

  • listen on the pH port.   Send a temperature reading to the pH circuit so that measurements will use the current water temperature.
  • Keep sending the “C\r” command to get the pH circuit to send continuous readings.  Even though the pH circuit does not need the sketch to get pre-readings before taking the real reading, there have been many times when a command needed to be repeated before the circuit would respond. The number of times varied.  For that reason the sketch keeps sending “C\r” commands to the pH circuit. 
  • Every second send the “C\r” command through the pH port.  I opted to continuously send the command because sometimes it took several tries at a command before the circuit would act on the command.
  • When a reading comes in through the pH port, check to see if it is a valid reading.  If the reading is valid, put the pH reading into a substring (sensorReadingpH).  Stop sending the “C\r” command.  Let the sketch know a reading is available (phStringReceived).
  • listen on the conductivity port.  Send a temperature reading to the EC circuit for the same reason one was sent after switching ports to the pH circuit.
  • Keep sending the “C\r” command until the port lets the sketch know it has received an EC reading (isECReadingInContinuousMode).
  • Keep getting Conductivity readings until a reading after the 25th reading is a valid reading.  Put the reading into a substring (sensorReadingEC)
  • After the first reading, turn off the “C\r” command
  • After 26 readings,  do the same as with the pH reading only use variables and such related to the conductivity readings.  Let the sketch know a reading is available (ECStringReceived).
  • Switch to taking a pH reading….switch to taking an EC reading…with to taking a pH reading…..switch…switch….


Reading the water temperature is done right before the string is created that holds all the sensor readings.  The “meat and potatoes” of getting a water temperature reading is found in the getTemp() function which I talked about earlier.

Sending a Reading to the Base Station

If readings are available, the water node will send a string of readings when the ‘a’ command comes in from the Base Station.  If all the readings are not available, the water node sends a string noting a reading is not ready yet.  The Base Station needs to determine if it got a valid string and if it did not to keep requesting for a valid string of readings until one is received.  The way the sketch sends a reading:

  • An ‘a’ command is detected from bytes received from the Base Station (within the code if(radio.receiveDone()){})
  • If readings are available for both circuits, create a string that contains the readings and send it back to the Base Station.   If readings are not available, send a string containing: “ERROR|No readings available, try again”.  I use the | key to delineate between sentences. The flag variable, pHAndConductivityReadingsAvailable, tells the sketch whether there are recent readings.  If this variable = 1, only the pH reading is available.  If 2, only the conductivity, if 3, both readings are available.  By using this flag, I can separate taking readings – which happen constantly – to sending a reading – which happens with the Base Station sends the ‘a’ command.  

Sending a Reading to the Serial Monitor

All commands found in the data sheets for the pH and conductivity circuits can be sent to the water node when the node is hooked up to a serial monitor.  Besides being a tremendous debugging aid, this is the only way right now I can calibrate the sensors.  The sketch knows whether commands are being sent by the Base Station or the Serial Monitor by checking the bool isRemoteInput.

That’s All For Now

It took me longer than I had planned to get the water node going and to write this post!  Come to think about it, I can’t think of a project that hasn’t taken longer than I have planned.  Some of the time spent was exploring the best way to put together the pH, conductivity, and water temperature sensors.  As well as understanding the how the Atlas Scientific sensors work.  I hope the information is useful to you.  

My next step with the water node is to put in automatic adjustment of pH and nutrients.  Before that, I will finish up my work on my iPhone app talking to the Base Station and displaying results on the iPhone.  While doing all this, I will be having an amazing learning experience with my fellow learners at Contextual Electronics.