Remarks

Fc28
Status Status badge: working
Source code GitHub
Datasheet(s) GitHub
NuGet package NuGet Gallery for Meadow.Foundation.Sensors.Moisture.Fc28

FC-28 Soil Moisture Sensor is a simple breakout for measuring the moisture in soil and similar materials. The sensor has two probes and measures the resistance between them, which means this sensor is of type Resistive. Since water is conductive, as moisture in the soil increases, the resistance decreases allowing the sensor to determine soil humidity.

The biggest issue of this sensor is the corrosion of the probes, not just because it is in contact with the soil but also because there is a DC current flowing which causes electrolysis of the sensors. A work-around to prolong the life of the probes is to not constantly have the sensor powered on, but activate it every time the sensor will perform a read using a digital output port connected to the VCC pin. The code and circuit example shows you how to use it.

The following example shows how read the soil moisture every second:

public class MeadowApp : App<F7Micro, MeadowApp>
{
    Fc28 fc28;

    public MeadowApp()
    {
        Console.WriteLine("Initializing...");

        fc28 = new Fc28(
            Device.CreateAnalogInputPort(Device.Pins.A01),
            Device.CreateDigitalOutputPort(Device.Pins.D15),
            minimumVoltageCalibration: 3.24f,
            maximumVoltageCalibration: 2.25f
        );

        TestFC28Updating();
    }

    void TestFC28Updating() 
    {
        Console.WriteLine("TestFC28Updating...");

        fc28.Subscribe(new FilterableObserver<FloatChangeResult, float>(
            h => { Console.WriteLine($"Moisture values: {Math.Truncate(h.New)}, old: {Math.Truncate(h.Old)}, delta: {h.DeltaPercent}"); },
            e => { return true; }
        ));

        fc28.Updated += (object sender, FloatChangeResult e) =>
        {
            Console.WriteLine($"Moisture Updated: {e.New}");
        };

        fc28.StartUpdating();
    }
}

Sample projects available on GitHub

Code Example

Fc28 fc28;

public override Task Initialize()
{
    Console.WriteLine("Initialize...");

    fc28 = new Fc28(
        Device.CreateAnalogInputPort(Device.Pins.A01, 5, TimeSpan.FromMilliseconds(40), new Voltage(3.3, Voltage.UnitType.Volts)),
        Device.CreateDigitalOutputPort(Device.Pins.D15),
        minimumVoltageCalibration: new Voltage(3.24f, VU.Volts),
        maximumVoltageCalibration: new Voltage(2.25f, VU.Volts)
    );

    var consumer = Fc28.CreateObserver(
        handler: result => {
            // the first time through, old will be null.
            string oldValue = (result.Old is { } old) ? $"{old:n2}" : "n/a"; // C# 8 pattern matching
            Console.WriteLine($"Subscribed - " +
                $"new: {result.New}, " +
                $"old: {oldValue}");
        },
        filter: null
    );
    fc28.Subscribe(consumer);

    fc28.HumidityUpdated += (object sender, IChangeResult<double> e) =>
    {
        Console.WriteLine($"Moisture Updated: {e.New}");
    };

    return Task.CompletedTask;
}

public async override Task Run()
{
    var moisture = await fc28.Read();
    Console.WriteLine($"Moisture Value { moisture}");

    fc28.StartUpdating();
}

Sample project(s) available on GitHub

Wiring Example

Characteristic Locus
Inheritance System.Object ObservableBase<System.Double> SensorBase<System.Double> > Fc28
Implements IMoistureSensor
Inherited Members SensorBase<Double>.Updated SensorBase<Double>.samplingLock SensorBase<Double>.SamplingTokenSource SensorBase<Double>.Conditions SensorBase<Double>.IsSampling SensorBase<Double>.UpdateInterval SensorBase<Double>.RaiseEventsAndNotify(IChangeResult<>) SensorBase<Double>.Read() ObservableBase<Double>.observers ObservableBase<Double>.NotifyObservers(IChangeResult<>) Meadow.Foundation.ObservableBase<System.Double>.Subscribe(IObserver<>) Meadow.Foundation.ObservableBase<System.Double>.CreateObserver(Action<>, System.Nullable<Predicate<IChangeResult<UNIT>>>)
Namespace Meadow.Foundation.Sensors.Moisture
Assembly Fc28.dll

Syntax

public class Fc28 : SensorBase<double>, IMoistureSensor

Constructors

Fc28(IAnalogInputPort, IDigitalOutputPort, Nullable<Voltage>, Nullable<Voltage>)

Creates a FC28 soil moisture sensor object with the especified analog pin and digital pin.

Declaration
public Fc28(IAnalogInputPort analogPort, IDigitalOutputPort digitalPort, Voltage? minimumVoltageCalibration, Voltage? maximumVoltageCalibration)

Parameters

Type Name Description
IAnalogInputPort analogPort
IDigitalOutputPort digitalPort
System.Nullable<Voltage> minimumVoltageCalibration
System.Nullable<Voltage> maximumVoltageCalibration

Fc28(IMeadowDevice, IPin, IPin, Nullable<Voltage>, Nullable<Voltage>, Nullable<TimeSpan>, Int32, Nullable<TimeSpan>)

Creates a FC28 soil moisture sensor object with the especified analog pin, digital pin and IO device.

Declaration
public Fc28(IMeadowDevice device, IPin analogPin, IPin digitalPin, Voltage? minimumVoltageCalibration, Voltage? maximumVoltageCalibration, TimeSpan? updateInterval = null, int sampleCount = 5, TimeSpan? sampleInterval = null)

Parameters

Type Name Description
IMeadowDevice device
IPin analogPin
IPin digitalPin
System.Nullable<Voltage> minimumVoltageCalibration
System.Nullable<Voltage> maximumVoltageCalibration
System.Nullable<TimeSpan> updateInterval
System.Int32 sampleCount
System.Nullable<TimeSpan> sampleInterval

Properties

AnalogInputPort

Returns the analog input port

Declaration
protected IAnalogInputPort AnalogInputPort { get; }

Property Value

Type Description
IAnalogInputPort

DigitalPort

Returns the digital output port

Declaration
protected IDigitalOutputPort DigitalPort { get; }

Property Value

Type Description
IDigitalOutputPort

MaximumVoltageCalibration

Voltage value of most moist soil. Default of 3.3V.

Declaration
public Voltage MaximumVoltageCalibration { get; set; }

Property Value

Type Description
Voltage

MinimumVoltageCalibration

Voltage value of most dry soil. Default of 0V.

Declaration
public Voltage MinimumVoltageCalibration { get; set; }

Property Value

Type Description
Voltage

Moisture

Last value read from the moisture sensor.

Declaration
public double? Moisture { get; }

Property Value

Type Description
System.Nullable<System.Double>

Methods

RaiseChangedAndNotify(IChangeResult<Double>)

Declaration
protected void RaiseChangedAndNotify(IChangeResult<double> changeResult)

Parameters

Type Name Description
IChangeResult<System.Double> changeResult

ReadSensor()

Declaration
protected override Task<double> ReadSensor()

Returns

Type Description
Task<System.Double>

Overrides

Meadow.Foundation.SensorBase<System.Double>.ReadSensor()

StartUpdating()

Starts continuously sampling the sensor.

This method also starts raising Updated events and IObservable subscribers getting notified. Use the standbyDuration parameter to specify how often events and notifications are raised/sent.

Declaration
public void StartUpdating()

StopUpdating()

Stops sampling the sensor.

Declaration
public void StopUpdating()

VoltageToMoisture(Voltage)

Declaration
protected double VoltageToMoisture(Voltage voltage)

Parameters

Type Name Description
Voltage voltage

Returns

Type Description
System.Double

Events

HumidityUpdated

Raised when a new sensor reading has been made. To enable, call StartUpdating().

Declaration
public event EventHandler<IChangeResult<double>> HumidityUpdated

Event Type

Type Description
EventHandler<IChangeResult<System.Double>>