Soil moisture sensor, very noisy readings

Hello!

Built automatic irregation system for outdoor plastic pots. first tried soil sensor with capacitance - was extremely unrelyable, sensed moisture outside pot, and other unknown factors changed readings about 3 times more than the actual soil moisture I was trying to measure. (Used absolute results)

http://pcb.daince.net/doku.php?id=ebay_soil_hum_temp_aio_v100 (it actually worked very well in short tests)

Now stripped insulation and tried with simple analog readings with resistor. with the same plate. This works much better but still horrible. there are 4 zones in different depths , moisture is sum of them, in the time there have been readins there has been no rain, so it should have been very stable slightly going down. "target" is a potentiometer wich hasn't been touched, and it's also not stable in readings.

using 12v power for arduino because I use the same power supply for electric valves, but in measurement times they havn't been used. (this is with using stabilization, by taking average of last 100 readings) Light is also being measured with analog port, but appears to be working fine.

Any ideas why the soil moisture data is so bad?

try averaging 16 reads,

you must only apply power to the sensor if you want to make readings, otherwise there is a chance of electrolysis.

There is a new capacitive soil humidity sensor: http://wemakethings.net/chirp/ https://www.tindie.com/products/miceuz/i2c-soil-moisture-sensor/

No idea why, but averaging 16 reads helped a lot. Thanks!

Averaging assumes the noise consists of values that are too high and values that are too low in approx. equal amount. by adding the measurements the noise ++ and -- cancels each other out.

The averaging is bit faster if you take a power of 2 as #measurements as the computer can do the divide very fast.

(a small backgrounder on averaging measurements)

Often a noisy signal is sampled multiple times and averaged with equal weights.

int sum = 0;
for (int m=0; m < 16; m++) 
{
    sum += analogRead(A0);
}
val = sum/16;

Possible drawback is that as the measurements have a different time stamps, the equal weight per measurement can introduce a systematic error.

To solve this “systematic error” one can add weights to different measurements e.g this average of 5 measurements with an increasing weight, so the last measurement gets most weight. Note the sum of the weights adds up to 100%.

sum = analogRead(A0) /16;
sum += analogRead(A0) /16;
sum += analogRead(A0) /8;
sum += analogRead(A0) /4;
sum += analogRead(A0) /2;

Another averaging scheme gives the largest weight to the middle measurement.

sum = analogRead(A0) /16;
sum += analogRead(A0) /16;
sum += analogRead(A0) /8;
sum += analogRead(A0) /2;
sum += analogRead(A0) /8;
sum += analogRead(A0) /16;
sum += analogRead(A0) /16;

Other schemes can be used of course, a generic way to use weights is to place the weights in an array

int weight[] = { 6, 3, 3, 6 }; // outer ones are equal the middle two
int sum = 0;
for (int m =0; m < 4; m++)
{
    sum += analogRead(A0) /weight[m];  // sum of the weights add up to 100%
}

Possible drawback of the multiple divisions is the value is truncated with every division. Rounding solves this for most part.

sum = 0;
for (int m =0; m < 10; m++) 
{
    sum += (analogRead(A0) + weight[m]/2) /weight[m];  // sum of the weights add up to 100%
}