Aquaponics pH to 1-Wire Converter – Part 2

This is the first draft of the pH to 1-Wire converter schematic, and some of the component values are still missing. The original circuit runs on 12 VDC, but since the A/D converter IC must be supplied with 5 VDC only I want to scale down the circuit, so that 5 V is the maximum voltage present. I assume I would have to tweak some resistor values in order to make the circuit run at this lower supply voltage, but I haven’t looked into the details yet. I’ll post an updated schematic and the calculations later.

ph_1wire_1.png

(Click on the picture above for a larger version.)

These are the source files:

gEDA schematic, .sch and .pdf:
ph_1wire_1.sch ph_1wire_1.pdf

gEDA symbols, DS2762 and BAT54S:
DS2762-1.sym BAT54S-1.sym

The original idea was to use a 1-Wire A/D converter with built-in 1-Wire digital interface, but the one I found was not recommended for new designs. This is what Maxim writes about the DS2450 A/D converter:

This product is Not Recommended for New Designs. Some versions may be No Longer Available or being discontinued and subject to Last Time Buy, after which new orders can not be placed.

Also known as ‘NRND’. Most of the other A/D converters I found at Maxim had another interface, but the main IC on the soil moisture sensor board from Hobby Boards also converts analog signals to digital and that’s a DS2760. The updated version is called DS2762, which is the one that I have used in the new circuit.

The DS2760 on the soil moisture sensor board measures current, but the IC also has a voltage input pin. The IC is actually a ‘High-Precision Li+ Battery Monitor With Alerts’ as Maxim calls it. The idea is to only use the voltage input pin and 1-Wire interface to get a popular, and cheap, A/D converter, with high input resistance.

Since the DS2762 operates on 5 VDC, the ground reference for the amplifier section should be changed to 2.5 V instead of 7 V in order to use the entire input voltage span of the A/D converter. The 7 V in the original circuit was meant to be measured with a voltage meter and you would have the pH value directly as a reading (pH 7 = 7.00 V, pH 8 = 8.00 V etc.). There’s no meter or display on this new circuit, only data delivered to a computer via the 1-Wire interface, so voltages in the circuit can be converted to something meaningful using software on the computer. Historical data can be displayed with e.g. RRDtool.

When the supply voltage is changed, the gain of the voltage amplifier has to change too, along with a change in offset voltage, i.e. ground reference. IC300 is a dual op-amp IC, where R351, R352 and R355 determines the gain. R300 sets the ground reference voltage level. Apparently it is necessary to put in trimmer resistors, since practical op-amps are not perfect like theoretical ones. Also, the pH probe is worn down as time goes by, and the circuit will have to be calibrated regularly.

Several capacitors have been added to short circuit any fast changing signals as these are irrelevant to aquaponics pH measurements and any alternating currents are considered noise in this respect. It means that the pH values from the 1-Wire interface will need seconds to stabilize. D101 is included to protect the 1-Wire interface.

Since the schematic does not represent the PCB layout, a note has been written about the seemingly long wires going from the BNC connector to the op-amp. On the actual PCB the traces must be as short as possible, because the internal resistance of a pH probe is very high and any electromagnetic radiation will induce relatively high unwanted voltages in the circuit. It shouldn’t be a problem though to place IC300 close to J300.

DS2762 has a general purpose I/O pin (PIO) which can be used for debugging. D100 could be connected to this pin to be able to signal something, but it would probably need an extra transistor. As I want things to be as simple as possible I haven’t included this, but at least there’s a resistor footprint to work with now.

I want to experiment with the values of R351, R353, R354 and R355 in Qucs, as I don’t fully understand the impact of changing the supply voltage, hence the missing resistor values. But I don’t mind – Qucs turns out to be an awesome piece of software for the electronics hacker ;-)

How to Calculate the Calibration of Watermark Moisture Sensors for Soil

My 1-Wire Watermark soil moisture sensor board from Hobby-Boards generates a negative number ranging from -1.338 when fully wet to -0.1394 when totally dry. These are the limits and normal everyday readings fall in between these limits.

I already had a basic script installed on my NSLU2 in order to find the limits to be used for calibration, so I just need to update the calculation section with the limits and the necessary math to get a readout in percent instead [%]:

# Calculate soil moisture
drylimit=0.1394
wetlimit=1.338
range=`echo "$wetlimit-$drylimit" | bc`
a=`echo "(-1)*$soilmoist1" | bc`
b=`echo "$a-$drylimit" | bc`
c=`echo "scale=3; $b/$range" | bc`
d=`echo "100*$c" | bc`
soilmoist=`echo $d | cut -c -5`

The original script called update_database.sh is shown in this post: Watermark Soil Moisture Sensor Probe Calibration

With this new modification the soil moisture graph will now show the data in percent:

It shows a remarkably steady low moisture content, but again, it hasn’t rained for days, perhaps even weeks, so for now I trust that this graphs is telling the truth. Time will tell if the system is stuck at this level, or if the rain will be able to change the curve.

Watermark Soil Moisture Sensor Probe Calibration

OWFS and the 1-Wire bus are able to handle several 1-Wire units at a time and I want to display air and soil temperature together in the same graph, and also add a Watermark soil moisture sensor to the system. The soil moisture sensor is controlled by a PCB from Hobby-Boards.com, but the temperature sensors are connected directly to the 1-Wire bus in a daisy chain.

When the units are connected they show up in the owfs directory. 10.x... are temperature sensors, 30.6... is the ground moisture sensor circuit board, and 81.5... is the USB-to-1-Wire adapter:

$ ssh 192.168.1.xx
$ cd owfs
$ ls -la

total 4
drwxr-xr-x 1 root   root      8 Oct 19 13:58 .
drwxr-xr-x 7 thomas thomas 4096 Sep 28 13:36 ..
drwxrwxrwx 1 root   root      8 Oct 19 15:39 10.06A394010800
drwxrwxrwx 1 root   root      8 Oct 19 15:39 10.4F7494010800
drwxrwxrwx 1 root   root      8 Oct 19 15:39 30.6A1E62120000
drwxrwxrwx 1 root   root      8 Oct 19 15:39 81.592527000000
drwxr-xr-x 1 root   root      8 Oct 19 13:58 alarm
drwxr-xr-x 1 root   root      8 Oct 19 13:58 bus.0
drwxr-xr-x 1 root   root      8 Oct 19 13:58 settings
drwxrwxrwx 1 root   root      8 Oct 19 15:39 simultaneous
drwxr-xr-x 1 root   root      8 Oct 19 13:58 statistics
drwxr-xr-x 1 root   root     32 Oct 19 13:58 structure
drwxr-xr-x 1 root   root      8 Oct 19 13:58 system
drwxr-xr-x 1 root   root      8 Oct 19 13:58 uncached

My previous system only had a single temperature sensor connected to it, so I delete the old RRDtool database:

$ cd /home/thomas/rrdtool/
$ rm database.rrd
$ nano create_database.sh

and add the new temperature sensor and the soil moisture sensor (soiltemp and soilmoist) to a new database using the create_database.sh script:

#!/bin/bash
rrdtool create database.rrd --start N --step 300 \
DS:airtemp:GAUGE:600:U:U \
DS:soiltemp:GAUGE:600:U:U \
DS:soilmoist:GAUGE:600:U:U \
RRA:AVERAGE:0.5:1:12 \
RRA:AVERAGE:0.5:1:288 \
RRA:AVERAGE:0.5:12:168 \
RRA:AVERAGE:0.5:12:720 \
RRA:AVERAGE:0.5:288:365

(Check out my other post about RRDtool for more details on how to get the logging system up and running: How to Use RRDtool on Debian NSLU2 to Capture Temperature Data).

The update_database.sh script also needs an update to include the soil temperature data and the soil moisture data:

#!/bin/bash
cd /home/thomas/rrdtool

# Read data from sensors
airtempread=`cat /home/thomas/owfs/10.4F7494010800/temperature`
soiltempread=`cat /home/thomas/owfs/10.06A394010800/temperature`
soilmoistread=`cat /home/thomas/owfs/30.6A1E62120000/current`

# Format reading
airtemp=`echo $airtempread | cut -c -4`
soiltemp=`echo $soiltempread | cut -c -4`
soilmoist1=`echo $soilmoistread | cut -c -7`

# Calculate soil moisture
a=`echo "(-1)*$soilmoist1" | bc`
soilmoist=`echo $a | cut -c -5`

# Update database
rrdtool update database.rrd N:$airtemp:$soiltemp:$soilmoist

# Create graphs
#0000FF = blue trace color
#CC6600 = brown trace color

rrdtool graph temp_h.png -y 2:1 --vertical-label "[deg C]" \
--start -1h DEF:airtemp=database.rrd:airtemp:AVERAGE \
DEF:soiltemp=database.rrd:soiltemp:AVERAGE \
LINE1:airtemp#0000FF:"Air temperature [deg C]" \
LINE1:soiltemp#CC6600:"Soil temperature [deg C]"

rrdtool graph temp_d.png -y 2:1 --vertical-label "[deg C]" \
--start -1d DEF:airtemp=database.rrd:airtemp:AVERAGE \
DEF:soiltemp=database.rrd:soiltemp:AVERAGE \
LINE1:airtemp#0000FF:"Air temperature [deg C]" \
LINE1:soiltemp#CC6600:"Soil temperature [deg C]"

rrdtool graph temp_w.png -y 2:1 --vertical-label "[dec C]" \
--start -1w DEF:airtemp=database.rrd:airtemp:AVERAGE \
DEF:soiltemp=database.rrd:soiltemp:AVERAGE \
LINE1:airtemp#0000FF:"Air temperature [deg C]" \
LINE1:soiltemp#CC6600:"Soil temperature [deg C]"

rrdtool graph temp_m.png -y 2:1 --vertical-label "[dec C]" \
--start -1m DEF:airtemp=database.rrd:airtemp:AVERAGE \
DEF:soiltemp=database.rrd:soiltemp:AVERAGE \
LINE1:airtemp#0000FF:"Air temperature [deg C]" \
LINE1:soiltemp#CC6600:"Soil temperature [deg C]"

rrdtool graph temp_y.png -y 2:1 --vertical-label "[dec C]" \
--start -1y DEF:airtemp=database.rrd:airtemp:AVERAGE \
DEF:soiltemp=database.rrd:soiltemp:AVERAGE \
LINE1:airtemp#0000FF:"Air temperature [deg C]" \
LINE1:soiltemp#CC6600:"Soil temperature [deg C]"

rrdtool graph soil_moisture_h.png --vertical-label "[]" \
--start -1h DEF:soilmoist=database.rrd:soilmoist:AVERAGE \
LINE1:soilmoist#CC6600:"Soil moisture"

rrdtool graph soil_moisture_d.png --vertical-label "[]" \
--start -1d DEF:soilmoist=database.rrd:soilmoist:AVERAGE \
LINE1:soilmoist#CC6600:"Soil moisture"

rrdtool graph soil_moisture_w.png --vertical-label "[]" \
--start -1w DEF:soilmoist=database.rrd:soilmoist:AVERAGE \
LINE1:soilmoist#CC6600:"Soil moisture"

rrdtool graph soil_moisture_m.png --vertical-label "[]" \
--start -1m DEF:soilmoist=database.rrd:soilmoist:AVERAGE \
LINE1:soilmoist#CC6600:"Soil moisture"

rrdtool graph soil_moisture_y.png --vertical-label "[]" \
--start -1y DEF:soilmoist=database.rrd:soilmoist:AVERAGE \
LINE1:soilmoist#CC6600:"Soil moisture"

Watermark soil moisture sensor circuits need to be calibrated before the system will produce any meaningful results. Therefore the calculation in the above script is limited to converting from a negative to a positive readout, by multiplying with -1. In order to make the calibration you need the minimum and maximum value and afterwards convert to a percentage, i.e. minimum corresponds to a totally dry sensor, and maximum corresponds to a totally wet sensor.

With the raw soil moisture data now available the upload_graphs.sh script needs to be updated to upload the new graphs too:

#!/bin/bash
sleep 30
lftp -u USER,PASSWORD SERVER <<EOF
cd /temp/
lcd /home/thomas/rrdtool/
put temp_h.png
put temp_d.png
put temp_w.png
put temp_m.png
put temp_y.png
put soil_moisture_h.png
put soil_moisture_d.png
put soil_moisture_w.png
put soil_moisture_m.png
put soil_moisture_y.png
quit 0
EOF

Using the above scripts will produce graphs that contain both the air temperature and the soil temperature in the same graph.

Data from the soil moisture circuit are displayed in another graph:

Note that there’s no unit on the Y-axis because it’s still the raw data coming from the soil moisture sensor circuit. The reason for the fast drop shown in the graph is that during calibration I’m controlling the actual moisture. This is not your usual kitchen table project – it turned into a kitchen floor project ;-) :

When I had the Watermark soil moisture probe installed in my previous garden I noticed a strong dependence on soil temperature, which I wanted to compensate for in this new installation. This is a graph produced by my old set up:

You do get a general idea about the soil moisture content, but the temperature influence is clear, as each number on the X-axis represents day of month and the temperature drops each night.

I used an oven and a freezer during calibration to find the real minimum and maximum values, that the system is able to produce.

I had hoped that I could do some math in my scripts and remove this temperature dependence but after seeing the graph for the raw minimum and maximum data produced during calibration I realized that it’s not possible to that after all.

To the left on the X-axis I have a completely dry sensor (using the hot air fan in my oven), and to the right the sensor is completely soaked in a bowl of water:

The graph do show the temperature dependence, but the problem is that the error due to temperature is dependent on the actual soil moisture content, which is also the parameter I want to measure. So to make the correct adjustment, in order to calculate the actual moisture, I would need to know the actual moisture, which is impossible, since the actual moisture is what I wanted to measure in the first place. I guess I had hoped that the two lines would have been parallel, so that the temperature error would have been the same no matter what the actual moisture was. We’re moving into the field of physics, but the question still is: What is the maximum value to be used for calibration?

If the average value of 1.0 is used you’ll get measurements showing more than 100 % when the temperature exceeds 20 deg. C and the sensor is soaked. Choosing 0.7 will only make it worse. If 1.3 is chosen as maximum value the measurements will always be too low, but I’ll use this value in a new script to get the readout converted to a percentage. I’ll show the math and new graphs in my next blog post.

(Update 2011-11-08: Check out my new script: Watermark soil moisture sensors calibration calculator)