Skip to content

Commit

Permalink
Merge pull request #866 from WildernessLabs/DFRobotDO
Browse files Browse the repository at this point in the history
DF Robot Analog DO sensor
  • Loading branch information
jorgedevs authored Dec 20, 2023
2 parents 778b62d + 3133bde commit 49bf560
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ To view all Wilderness Labs open-source projects, including samples, visit [gith
## Usage

```csharp
private IPositionalMotor stepper;
private IStepperMotor stepper;

private bool UseStepDirConfiguration { get; set; } = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public override Task Initialize()
{
Resolver.Log.Info("Initialize...");

a02yyuw = new A02yyuw(Device, Device.PlatformOS.GetSerialPortName("COM1"));
a02yyuw = new A02yyuw(Device, Device.PlatformOS.GetSerialPortName("COM4"));

var consumer = A02yyuw.CreateObserver(
handler: result =>
Expand All @@ -30,7 +30,7 @@ public override Task Initialize()
{
if (result.Old is { } old)
{
return Math.Abs((result.New - old).Centimeters) > 0.5;
return Math.Abs((result.New - old).Centimeters) > 5.0;
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public override Task Initialize()
{
if (result.Old is { } old)
{
return Math.Abs((result.New - old).Centimeters) > 0.5;
return Math.Abs((result.New - old).Centimeters) > 5.0;
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public override Task Initialize()
sensor.Subscribe(consumer);

// optional classical .NET events can also be used:
sensor.SaturationUpdated += (sender, result) =>
sensor.Updated += (sender, result) =>
{
// string oldValue = (result.Old is { } old) ? $"{old * 100:n0}%" : "n/a";
// Resolver.Log.Info($"Updated - New: {result.New * 100:n0}%, Old: {oldValue}");
string oldValue = (result.Old is { } old) ? $"{old * 100:n0}%" : "n/a";
Resolver.Log.Info($"Updated - New: {result.New * 100:n0}%, Old: {oldValue}");
};

return Task.CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using Meadow.Hardware;
using Meadow.Units;
using System;
using System.Threading.Tasks;

namespace Meadow.Foundation.Sensors.Environmental;

/// <summary>
/// DFRobot Analog Gravity Dissolved Oxygen Meter
/// </summary>
public partial class DFRobotGravityDOMeter : SamplingSensorBase<ConcentrationInWater> //, IDissolvedOxygenSensor
{
/// <summary>
/// The current water temperature (default 25C)
/// </summary>
public Units.Temperature WaterTemperature { get; set; } = new Units.Temperature(25, Units.Temperature.UnitType.Celsius);

/// <summary>
/// The calibration value for the sensor at 25C (default 1.6V)
/// </summary>
public Voltage CalibrationAt25C { get; set; } = new Voltage(1.6, Voltage.UnitType.Volts);

/// <summary>
/// Returns the analog input port
/// </summary>
protected IAnalogInputPort AnalogInputPort { get; }

/// <summary>
/// Last concentration value read from the sensor
/// </summary>
public ConcentrationInWater? ConcentrationInWater { get; protected set; }

/// <summary>
/// The disolved oxygen lookup table for temperature values from 0 to 40 degrees C
/// </summary>
readonly int[] DO_Table = new int[41] {
14460, 14220, 13820, 13440, 13090, 12740, 12420, 12110, 11810, 11530,
11260, 11010, 10770, 10530, 10300, 10080, 9860, 9660, 9460, 9270,
9080, 8900, 8730, 8570, 8410, 8250, 8110, 7960, 7820, 7690,
7560, 7430, 7300, 7180, 7070, 6950, 6840, 6730, 6630, 6530, 6410};

/// <summary>
/// Creates a new DFRobotGravityDOMeter object
/// </summary>
/// <param name="analogInputPin">Analog pin the temperature sensor is connected to</param>
/// <param name="sampleCount">How many samples to take during a given reading</param>
/// <param name="sampleInterval">The time, to wait in between samples during a reading</param>
public DFRobotGravityDOMeter(IPin analogInputPin, int sampleCount = 5, TimeSpan? sampleInterval = null)
: this(analogInputPin.CreateAnalogInputPort(sampleCount, sampleInterval ?? TimeSpan.FromMilliseconds(40), new Voltage(3.3)))
{ }

/// <summary>
/// Creates a new DFRobotGravityDOMeter object
/// </summary>
/// <param name="analogInputPort">The port for the analog input pin</param>
public DFRobotGravityDOMeter(IAnalogInputPort analogInputPort)
{
AnalogInputPort = analogInputPort;

AnalogInputPort.Subscribe
(
IAnalogInputPort.CreateObserver(
result =>
{
ChangeResult<ConcentrationInWater> changeResult = new()
{
New = VoltageToConcentration(result.New),
Old = ConcentrationInWater
};
ConcentrationInWater = changeResult.New;
RaiseEventsAndNotify(changeResult);
}
)
);
}

/// <summary>
/// Get the current voltage, useful for calibration
/// </summary>
/// <returns></returns>
public Task<Voltage> GetCurrentVoltage()
{
return AnalogInputPort.Read();
}

/// <summary>
/// Reads data from the sensor
/// </summary>
/// <returns>The latest sensor reading</returns>
protected override async Task<ConcentrationInWater> ReadSensor()
{
var voltage = await AnalogInputPort.Read();
var newConcentration = VoltageToConcentration(voltage);
ConcentrationInWater = newConcentration;
return newConcentration;
}

/// <summary>
/// Starts continuously sampling the sensor
/// </summary>
public override void StartUpdating(TimeSpan? updateInterval)
{
lock (samplingLock)
{
if (IsSampling) { return; }
IsSampling = true;
AnalogInputPort.StartUpdating(updateInterval);
}
}

/// <summary>
/// Stops sampling the sensor
/// </summary>
public override void StopUpdating()
{
lock (samplingLock)
{
if (!IsSampling) { return; }
IsSampling = false;
AnalogInputPort.StopUpdating();
}
}

ConcentrationInWater VoltageToConcentration(Voltage voltage)
{
var calibrationValue = DO_Table[(int)WaterTemperature.Celsius];

var voltageSaturationInMilliVolts = CalibrationAt25C.Millivolts + 35 * (WaterTemperature.Celsius - 25);
var concentrationRaw = voltage.Millivolts * calibrationValue / voltageSaturationInMilliVolts;

return new ConcentrationInWater(concentrationRaw, Units.ConcentrationInWater.UnitType.MicrogramsPerLiter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Meadow.Foundation.Sensors.Environmental.DFRobotGravityDOMeter

**DFRobot analog gravity dissolved oxygen sensor**

The **DFRobotGravityDOMeter** library is designed for the [Wilderness Labs](www.wildernesslabs.co) Meadow .NET IoT platform and is part of [Meadow.Foundation](https://developer.wildernesslabs.co/Meadow/Meadow.Foundation/).

The **Meadow.Foundation** peripherals library is an open-source repository of drivers and libraries that streamline and simplify adding hardware to your C# .NET Meadow IoT application.

For more information on developing for Meadow, visit [developer.wildernesslabs.co](http://developer.wildernesslabs.co/).

To view all Wilderness Labs open-source projects, including samples, visit [github.com/wildernesslabs](https://github.com/wildernesslabs/).

## Usage

```csharp
DFRobotGravityDOMeter sensor;

public override Task Initialize()
{
Resolver.Log.Info("Initialize...");

sensor = new DFRobotGravityDOMeter(Device.Pins.A01);

// Example that uses an IObservable subscription to only be notified when the saturation changes
var consumer = DFRobotGravityDOMeter.CreateObserver(
handler: result =>
{
string oldValue = (result.Old is { } old) ? $"{old.MilligramsPerLiter:n0}" : "n/a";
string newValue = $"{result.New.MilligramsPerLiter:n0}";
Resolver.Log.Info($"New: {newValue}mg/l, Old: {oldValue}mg/l");
},
filter: null
);
sensor.Subscribe(consumer);

// optional classical .NET events can also be used:
sensor.Updated += (sender, result) =>
{
string oldValue = (result.Old is { } old) ? $"{old.MilligramsPerLiter}mg/l" : "n/a";
Resolver.Log.Info($"Updated - New: {result.New.MilligramsPerLiter:n0}mg/l, Old: {oldValue}");
};

return Task.CompletedTask;
}

public override async Task Run()
{
Resolver.Log.Info("Run...");

await ReadSensor();

sensor.StartUpdating(TimeSpan.FromSeconds(2));
}

protected async Task ReadSensor()
{
var concentration = await sensor.Read();
Resolver.Log.Info($"Initial concentration: {concentration.MilligramsPerLiter:N0}mg/l");
}

```
## How to Contribute

- **Found a bug?** [Report an issue](https://github.com/WildernessLabs/Meadow_Issues/issues)
- Have a **feature idea or driver request?** [Open a new feature request](https://github.com/WildernessLabs/Meadow_Issues/issues)
- Want to **contribute code?** Fork the [Meadow.Foundation](https://github.com/WildernessLabs/Meadow.Foundation) repository and submit a pull request against the `develop` branch


## Need Help?

If you have questions or need assistance, please join the Wilderness Labs [community on Slack](http://slackinvite.wildernesslabs.co/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Meadow.Sdk/1.1.0">
<PropertyGroup>
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<Nullable>enable</Nullable>
<LangVersion>10.0</LangVersion>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageIcon>icon.png</PackageIcon>
<Authors>Wilderness Labs, Inc</Authors>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>DFRobotGravityDOMeter</AssemblyName>
<Company>Wilderness Labs, Inc</Company>
<PackageProjectUrl>http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/</PackageProjectUrl>
<PackageId>Meadow.Foundation.Sensors.Environmental.DFRobotGravityDOMeter</PackageId>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.Foundation</RepositoryUrl>
<PackageTags>Meadow,Meadow.Foundation,Environmental,DFRobot,Gravity,DO,Dissolved,Oxygen,Meter</PackageTags>
<Version>0.1.0</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>DFRobot analog gravity dissolved oxygen sensor</Description>
</PropertyGroup>
<ItemGroup>
<None Include=".\Readme.md" Pack="true" PackagePath=""/>
<None Include="..\..\..\icon.png" Pack="true" PackagePath="" />
<ProjectReference Include="..\..\..\Meadow.Foundation.Core\Meadow.Foundation.Core.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Meadow.Sdk/1.1.0">
<PropertyGroup>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.Foundation</RepositoryUrl>
<Company>Wilderness Labs, Inc</Company>
<Authors>Wilderness Labs, Inc</Authors>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>App</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\..\Meadow.Core\Source\implementations\f7\Meadow.F7\Meadow.F7.csproj" />
<ProjectReference Include="..\..\Driver\Sensors.Environmental.DFRobotGravityDOMeter.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="meadow.config.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Meadow;
using Meadow.Devices;
using Meadow.Foundation.Sensors.Environmental;
using System;
using System.Threading.Tasks;

namespace Sensors.Environmental.DFRobotGravityDOMeter_Sample
{
public class MeadowApp : App<F7FeatherV2>
{
//<!=SNIP=>

DFRobotGravityDOMeter sensor;

public override Task Initialize()
{
Resolver.Log.Info("Initialize...");

sensor = new DFRobotGravityDOMeter(Device.Pins.A01);

// Example that uses an IObservable subscription to only be notified when the saturation changes
var consumer = DFRobotGravityDOMeter.CreateObserver(
handler: result =>
{
string oldValue = (result.Old is { } old) ? $"{old.MilligramsPerLiter:n0}" : "n/a";
string newValue = $"{result.New.MilligramsPerLiter:n0}";
Resolver.Log.Info($"New: {newValue}mg/l, Old: {oldValue}mg/l");
},
filter: null
);
sensor.Subscribe(consumer);

// optional classical .NET events can also be used:
sensor.Updated += (sender, result) =>
{
string oldValue = (result.Old is { } old) ? $"{old.MilligramsPerLiter}mg/l" : "n/a";
Resolver.Log.Info($"Updated - New: {result.New.MilligramsPerLiter:n0}mg/l, Old: {oldValue}");
};

return Task.CompletedTask;
}

public override async Task Run()
{
Resolver.Log.Info("Run...");

await ReadSensor();

sensor.StartUpdating(TimeSpan.FromSeconds(2));
}

protected async Task ReadSensor()
{
var concentration = await sensor.Read();
Resolver.Log.Info($"Initial concentration: {concentration.MilligramsPerLiter:N0}mg/l");
}

//<!=SNOP=>
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MonoControl:
Options: --jit
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public override Task Initialize()
);
thermistor.Subscribe(consumer);

thermistor.TemperatureUpdated += (object sender, IChangeResult<Meadow.Units.Temperature> e) =>
thermistor.Updated += (object sender, IChangeResult<Meadow.Units.Temperature> e) =>
{
Resolver.Log.Info($"Temperature Updated: {e.New.Fahrenheit:N1}F/{e.New.Celsius:N1}C");
};
Expand Down
Loading

0 comments on commit 49bf560

Please sign in to comment.