Hacking a Capacitive Soil Moisture Sensor for Frequency Output

A $1.50 soil moisture sensor:  frequency – hacked & ready to deploy. My first experiments didn’t quite work due to probe polarization at low frequencies…but I’m still noodling with it.

There’s something of a cultural divide between the OpAmp/555 crowd and Arduino users. I think that goes some way to explaining the number of crummy sensor modules in the hobbyist market: engineers probably assume that anyone playing in the Arduino sandbox can’t handle anything more advanced than analogRead().  So it’s not unusual to find cheap IC sensor modules with features grounded out, because how many ‘duino users could config those registers anyway – right?

Legit suppliers like Adafruit do a much better job in that regard, but our project rarely uses their sensors because they are often festooned with regulators, level shifters, and other ‘user-friendly’ elements that push the sleep current out of our power budget. Sparkfun boards usually have leaner trim, but with all the cheap PCB services available now I’m tempted to just roll my own. But I keep running into the problem that in ‘prototype quantities’ the individual parts can cost more than modules with the reflow already done – and that’s before everything gets sand-bagged with shipping charges larger than the rest of the project combined.

So we still use a lot of lame eBay modules – after removing the usual load of redundant pullups and those ubiquitous 662k regulators.  Once you go down that rabbit hole you discover a surprising number of those cheap boards can be improved with ‘other’ alterations. The reward can be substantial, with our low power RTC mod bringing $1 DS3231 modules from ~0.1 mA down to less than 5µA sleep current. Another easily modified sensor is the SOIL moisture probe I flagged in the electrical conductivity post:

Schematic before conversion:  (regulator not shown). The output frequency is controlled by the time constant when  charging/discharging C3 through R2/R3. Gadget Reboot gives a good overview of how the basic configuration works, feeding the RC filtered 555 output into a simple peak detector. The V1.2 probes with the TLC555 run at a higher 1.5Mhz frequency with a 34% duty cycle.

These sensors use coplanar traces to filter high frequency output from a 555 oscillator, but you’re lucky to see more than 400 raw counts reading that smoothed output with Arduino’s 10-bit ADC.  On 3.3v systems, you can remove the regulator, jumper the in->out pads, and then combine the sensor with an ADS1115 for 15-bit resolution. But I found you can’t push that combination to high gain settings because the 1115’s low input impedance starts draining the C4 output capacitor too quickly.

These sensors are cheap enough that I’ve started noodling around with them for other tasks like measuring water level.  But with a water/air dielectric difference of about 80:1, even the unmodified soil probes do that job well.  After testing some ‘naked’ boards ( where I had removed all the components)  I realized that the bare traces fell within a workable capacitance range for the same astable configuration the timer was already configured for.  And since the TL555 doesn’t draw much more than 5mA, you can supply the sensor from a digital I/O pin to save power between readings:

The Hack:                                                               (click images to enlarge)

Get the regulated boards with the CMOS TLC555 chip rather than the NE555. 3.3v operation is out-of-spec for the NE and 1/2 the NE’s I’ve tried don’t even work in their default analog config at 5v.

Remove the regulator & bridge the Vin to Vout pads. If you are going to pin-power the sensor you also need to remove the INPUT caps C5&C6 as their inrush current will damage your MCU pins.

Note that some variants of these sensors come with the regulator already removed DO NOT BUY THESE BOARDS  – they use older NE555 chips which won’t operate at 3.3v.

Remove the T4 diode, C3 & C4 caps and R2& R3 resistors as shown.

Move the10k R1 to the R3 pads, and the 1Meg ohm R4 to the R2 pads. When the new R2 exceeds is more than 10x the new R3 resistor you approach a 50% duty cycle on the FM output.

Bridge the R1/T4 pads closest to the 555. This patches the frequency output to AOUT. Linking the other T4 pad to C3 replaces put’s the probes capacitance in its place.

There isn’t much left after the mod. It’s important to leave the C1 bypass in place but I haven’t had problems pin-powering other sensor boards with similar caps. It’s the bare minimum you can get away with on a 555 so if you get too many bad reads or weird spikes try adding another stabilization cap to the empty C5/C6 pads.

With the probe capacitance varying from <30 pF to ~500 pF (air/water), using 1M/10K resistors on the R2&R3 pads will give you about 50 kHz output in air, and ~1.5 kHz in water. Or you could drop in your own resistor combination to tune the output.  Our ProMini based loggers have a relatively slow 8MHz clock so the upper limit for measuring period intervals is about 120kHz before things get flakey. On a 16MHz board you can reach 200 kHz easily and with a faster MCU you could tweak that to even higher speeds. But at first bounce, with parts I already had, the 1M&10K combination seemed  workable.


the TLC555 draws far less current and works at 3.3v.  It can also be pushed to 2 MHz in astable mode, though you’d need a ripple counter to keep up. LMC555 & TLC551 work at even lower voltages than TLC555

You have variety of options to read pulsed signals with an Arduino. We reviewed those in the ‘Adding Sensors to an Arduino Datalogger‘ but the short version of that is:  Tillart’s TSL235R example works, or you could try PJRC’s FreqCount Library. Gate interval methods count many output cycles. This reduces error and lets you approach frequencies to about 1/2 your uC clock speed (depending on the interrupt handling). However at lower frequencies the precision suffers, so measuring the elapsed time during a single cycle is better.  Since I’ve already switched over to using the Input Capture Unit to read thermistors, I started with  Reply #12, on Nick’s Timers & Counters page.  This works with these hacked soil sensors, though it will occasionally throw a spurious High/Low outlier. Putting a few repeats through Paul Badgers digital smooth filter crops away those glitch reads and median filters are also good for single spike suppression.  Denes Sene’s Simple Kalman filter is also fun to play with, though in this case that’s  killing flies with a sledge hammer.

There are a few more steps to make the sensor ready for the real world. A quick search reveals plenty of approaches to protecting these sensors, but I’ve had success hardening many different types of sensor modules with an epoxy + heat-shrink method that lets you inspect the condition of the circuits later:

Cable & Epoxy Mounting:                               (click images to enlarge)

An old USB cable works for light – duty sensor applications. Here I’ve combined two of the four wires to carry the pulsed output.

Clear 2:1 heat-shrink forms a container, with adhesive lined 3:1 sealing the cable & providing a plug to hold in the epoxy.

Only fill to about 10% of the volume with epoxy. Here I’m using Loctite E30-CL

GENTLE heating compresses the tubing from the bottom up. This forces the epoxy over the components

Before finishing, use a cotton swab to seal the edges of the probe with the epoxy. Cut PCBs can absorb several % water if edges are left exposed.

Complete the heating over a rubbish bin to catch the overflow drips & wipe the front surface of the probe so that you don’t have any epoxy buildup on the sensing surfaces.

Soil moisture sensors measure the volumetric water content of a soil indirectly by using some other property such as electrical resistance or dielectric permittivity. The relation between the measurement and soil moisture varies depending on environmental factors such as soil type, temperature, or the amount of salt dissolved in the pore water.  This is kind of obvious if you think about how differently sand behaves with respect to water infiltration & retention compared to a soil high in clay content – but the low level details get quite complex.

I generally use a Classroom logger for backyard experiments because they’re cheap & only take an hour to build. You want at least 2-3 monitoring locations due to the spatial variability of infiltration pathways, and then 2-3 sampling depths at each spot for the complete profile.

Vernier outlines a basic volumetric calibration procedure for soil sensors which starts by measuring soil from your target area that’s been dried in an oven for 24 hours. To get another calibration point you add an amount of water equivalent to some percentage (say 45%) of that soils dry volume and take another sensor reading after that’s had a chance to equilibrate.  To get a more complete response curve you would use 5-10 jars of dry soil, adding different relative %-volumes of water to each one.

If the distance between interdigital coplanar electrodes is comparable to the smallest dimension of each electrode, then fringe fields’ are significant.  As a rule of thumb, the field usually has a penetration distance of between 0.5-1x the distance between the centers of the electrodes.  I found several papers modeling that as one third of the width of the electrode plus the gap between electrodes: EPD ≈ (W + G)/3 . In this case I estimate the useful sensing distance is a bit less, say 3-6 millimeters from the probes surface, so you have to take care there are no air gaps near the sensor surface during the calibration, and when you deploy. Agricultural sensors are often placed in an augured hole filled with a screen filtered soil slurry to avoid air bubbles.

The story gets more complicated with respect to growing things because water in the pores of sandy soil is more available to the plants than water in clay soils (see: matric potential) plus you have the root depth of your crop to consider. (typically 6-24 inches)  With all the confounding factors, soil sensors are often used in the context of ‘relative’ boundaries by setting an arbitrary upper threshold for the instrument’s raw output at field capacity (e.g., two days after a rain event) and the lower threshold at the value when plant wilting is observed. Soil moisture sensors also need to be placed in a location that receives a similar amount of sunlight to account for evapotranspiration.

But as usual, I pretty much ignored all that and simply stuck the thing in the ground for a couple of weeks to see what I’d get. Which was fortunate because it developed a problem which I might have missed during short calibration runs:

Probe Frequency [Hz] (left axis) at 5cm soil depth. Rain event on 9/5 reset the probe to normal for a few days.

The  daily thermal wobble was expected, but the probe repeatedly displayed an upward bend which did not match the daily ‘stair-step’ drying cycles seen with other nearby soil sensors. Were we slowly pulling the ions out of the soil matrix? Rain events would reset back to normal  behavior, but eventually the rising curve would happen again.  Perhaps that was because the water was leaving, but the ions were being held on the probe surface?  When I looked into the frequency of commercial sensors, they were running at least 100 kHz, and most were in the 10’s of MHz range. Some of them automatically increased frequency with increasing conductance specifically to avoid this type of problem.

I also tried to measure the electrical conductivity of solutions with this hacked probe. But without polarity reversals, polarization again became a limiting problem – and this only gets worse if you increase resistor values to resolve more detail with slower 555 pulses.  So at low freshwater conductivities, where polarisation is negligible, the probe works ‘ok’ as a low-resolution EC sensor if you take your readings quickly & then de-power the probe for a longish rest period. (I used no stirring) However the readings ‘plateau’ as you approach 10 mS/cm – so it’s not much use in the kind of brackish coastal environments we play in.

At it’s heart, this is just a variation of standard RC rise-time methods with the 555 converting that into pulses.  While these attempts with the 1M&10K pair didn’t deliver much, the parrot ain’t dead yet.  Changing that R2/R3 resistor combination to boost frequencies to 100kHz when the probe is in dry soil might go a long way to solving the polarization trouble.  Or, with a fixed capacitor (instead of the probe) I could try replacing a resistor with some plaster of Paris & carbon rods for matric potential sensor with pulsed output.

And then there’s all the other capacitive sensors that I could jumper onto the C3 pads.  At that point I might as well get out the hack-saw, because I’m really just using the top section of the probe as a TLC555 breakout that I can mount under epoxy. When you consider how many of us are working with 3.3v MCUs, a low voltage 555 module should have been on the market already.  And while I’m thinking about that – where are all the 3v op-amp boards, with each stage jumperable into several ‘standard recipes’, and linkable to the next by solder pads or holes along the outer edge?  I’m envisioning an SMD quad in the middle, and a few layers of elegantly designed traces & well labeled through-holes for population with resistors & caps.  Even at eBay prices, you’d think the mark-up would have made those common as dirt a long time ago . . .


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s