Skip to content

Commit

Permalink
Merge pull request #851 from WildernessLabs/AtlasDO
Browse files Browse the repository at this point in the history
Atlas Gravity Dissolved Oxygen sensor
  • Loading branch information
jorgedevs authored Dec 4, 2023
2 parents 4eb2860 + d7d8b89 commit c5eadea
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Meadow.Foundation.Displays
{
/// <summary>
/// Base class for TFT SPI displays
/// These displays typically support 16 & 18 bit, some also include 8, 9, 12 and/or 24 bit color
/// These displays typically support 16 and 18 bit, some also include 8, 9, 12 and/or 24 bit color
/// </summary>
public abstract partial class TftSpiBase : IGraphicsDisplay, ISpiPeripheral, IDisposable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public enum Gain
/// Initializes a new instance of the Mcp492x class.
/// </summary>
/// <param name="spiBus">The SPI bus.</param>
/// <param name="chipSelect">The chip select port (can be null).</param>
/// <param name="chipSelectPort">The chip select port (can be null).</param>
public Mcp492x(ISpiBus spiBus, IDigitalOutputPort? chipSelectPort)
{
this.spiBus = spiBus;
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using Meadow.Hardware;
using Meadow.Peripherals.Sensors.Environmental;
using Meadow.Units;
using System;
using System.Threading.Tasks;

namespace Meadow.Foundation.Sensors.Environmental;

/// <summary>
/// Atlas Scientific Analog Gravity Dissolved Oxygen Meter
/// </summary>
public partial class AtlasScientificGravityDOMeter : SamplingSensorBase<double>, IDissolvedOxygenSensor
{
/// <summary>
/// Raised when a new sensor percentage saturation reading is ready
/// </summary>
public event EventHandler<IChangeResult<double>> SaturationUpdated = delegate { };

/// <summary>
/// The calibration value for the sensor in air
/// </summary>
public Voltage CalibrationInAir { get; set; } = new Voltage(0.05, Voltage.UnitType.Volts);

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

/// <summary>
/// Last saturation value read from the sensor (0.0-1.0)
/// </summary>
public double? Saturation { get; protected set; }

/// <summary>
/// Creates a new AtlasScientificGravityDOMeter 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 AtlasScientificGravityDOMeter(IPin analogInputPin, int sampleCount = 5, TimeSpan? sampleInterval = null)
: this(analogInputPin.CreateAnalogInputPort(sampleCount, sampleInterval ?? TimeSpan.FromMilliseconds(40), new Voltage(3.3)))
{ }

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

AnalogInputPort.Subscribe
(
IAnalogInputPort.CreateObserver(
result =>
{
ChangeResult<double> changeResult = new()
{
New = VoltageToSaturation(result.New),
Old = Saturation
};
Saturation = 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<double> ReadSensor()
{
var voltage = await AnalogInputPort.Read();
var newSaturation = VoltageToSaturation(voltage);
Saturation = newSaturation;
return newSaturation;
}

/// <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();
}
}

/// <summary>
/// Raise change events for subscribers
/// </summary>
/// <param name="changeResult">The change result with the current sensor data</param>
protected override void RaiseEventsAndNotify(IChangeResult<double> changeResult)
{
SaturationUpdated?.Invoke(this, changeResult);
base.RaiseEventsAndNotify(changeResult);
}

double VoltageToSaturation(Voltage voltage)
{
return voltage.Millivolts / CalibrationInAir.Millivolts;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Meadow.Foundation.Sensors.Environmental.AltasScientificGravityDOMeter
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>AtlasScientificGravityDOMeter</AssemblyName>
<Company>Wilderness Labs, Inc</Company>
<PackageProjectUrl>http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/</PackageProjectUrl>
<PackageId>Meadow.Foundation.Sensors.Environmental.AtlasScientificGravityDOMeter</PackageId>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.Foundation</RepositoryUrl>
<PackageTags>Meadow,Meadow.Foundation,Environmental,Atlas,Scientific,Gravity,DO,Dissolved,Oxygen,Meter</PackageTags>
<Version>0.1.0</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Atlas Scientific 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.AtlasScientificGravityDOMeter.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,68 @@
using Meadow;
using Meadow.Devices;
using Meadow.Foundation.Sensors.Environmental;
using Meadow.Units;
using System;
using System.Threading.Tasks;

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

AtlasScientificGravityDOMeter sensor;

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

sensor = new AtlasScientificGravityDOMeter(Device.Pins.A01);
sensor.CalibrationInAir = new Voltage(0.04, Voltage.UnitType.Volts);

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

// optional classical .NET events can also be used:
sensor.SaturationUpdated += (sender, result) =>
{
// 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;
}

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

await ReadSensor();

//example calibration setting, ensure the sensor is set up for calibration
var calibrationVoltage = await sensor.GetCurrentVoltage();
sensor.CalibrationInAir = calibrationVoltage;

Resolver.Log.Info($"Calibration voltage: {calibrationVoltage.Volts}V");

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

protected async Task ReadSensor()
{
var saturation = await sensor.Read();
Resolver.Log.Info($"Initial saturation: {saturation * 100:N1}%");
}

//<!=SNOP=>
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MonoControl:
Options: --jit
27 changes: 25 additions & 2 deletions Source/Meadow.Foundation.sln
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32901.215
MinimumVisualStudioVersion = 10.0.40219.1
Expand Down Expand Up @@ -1375,6 +1374,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Lsm6dsox", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lsm6dsox_Sample", "Meadow.Foundation.Peripherals\Sensors.Motion.Lsm6dsox\Samples\Lsm6dsox_Sample\Lsm6dsox_Sample.csproj", "{CDBE4FD5-4432-4E8E-8E5F-A628D3D976FA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AltasScientificGravityDOMeter", "AltasScientificGravityDOMeter", "{E8D56013-9C99-4214-AAD2-F02919BC1191}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Environmental.AtlasScientificGravityDOMeter", "Meadow.Foundation.Peripherals\Sensors.Environmental.AtlasScientificGravityDOMeter\Driver\Sensors.Environmental.AtlasScientificGravityDOMeter.csproj", "{9B466C8D-880D-4BEF-83B6-5B8CF7741635}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{994D89F7-E9BC-4BD0-8C44-D05297FC7E08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtlasScientificGravityDOMeter_Sample", "Meadow.Foundation.Peripherals\Sensors.Environmental.AtlasScientificGravityDOMeter\Samples\AtlasScientificGravityDOMeter_Sample\AtlasScientificGravityDOMeter_Sample.csproj", "{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DigiPot", "DigiPot", "{77204A90-B195-4EA4-A17B-CB74E8910FC1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mcp4xxx", "Mcp4xxx", "{CD113034-407F-4FA7-9706-8004406551D2}"
Expand Down Expand Up @@ -3343,6 +3350,18 @@ Global
{CDBE4FD5-4432-4E8E-8E5F-A628D3D976FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDBE4FD5-4432-4E8E-8E5F-A628D3D976FA}.Release|Any CPU.Build.0 = Release|Any CPU
{CDBE4FD5-4432-4E8E-8E5F-A628D3D976FA}.Release|Any CPU.Deploy.0 = Release|Any CPU
{9B466C8D-880D-4BEF-83B6-5B8CF7741635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B466C8D-880D-4BEF-83B6-5B8CF7741635}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B466C8D-880D-4BEF-83B6-5B8CF7741635}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{9B466C8D-880D-4BEF-83B6-5B8CF7741635}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B466C8D-880D-4BEF-83B6-5B8CF7741635}.Release|Any CPU.Build.0 = Release|Any CPU
{9B466C8D-880D-4BEF-83B6-5B8CF7741635}.Release|Any CPU.Deploy.0 = Release|Any CPU
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}.Release|Any CPU.Build.0 = Release|Any CPU
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7}.Release|Any CPU.Deploy.0 = Release|Any CPU
{C9ABEEBE-341B-47C3-941F-57EE696FC9D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9ABEEBE-341B-47C3-941F-57EE696FC9D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9ABEEBE-341B-47C3-941F-57EE696FC9D5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
Expand Down Expand Up @@ -4083,6 +4102,10 @@ Global
{1CBD6FF1-B3AE-4DE0-91FF-A09E481629D6} = {03C07B80-FB22-4E12-84B8-6D71AC089443}
{A5F7052F-B028-488C-A94D-600B784109C7} = {FDAFC20B-C53A-46C6-B453-0B39D51248A9}
{CDBE4FD5-4432-4E8E-8E5F-A628D3D976FA} = {F1808C13-C604-46FA-828A-D1749762A38A}
{E8D56013-9C99-4214-AAD2-F02919BC1191} = {78E463DA-0FA1-4AAE-A281-D3297C9388C9}
{9B466C8D-880D-4BEF-83B6-5B8CF7741635} = {E8D56013-9C99-4214-AAD2-F02919BC1191}
{994D89F7-E9BC-4BD0-8C44-D05297FC7E08} = {E8D56013-9C99-4214-AAD2-F02919BC1191}
{8CE16106-AE01-41AC-BC68-12AA8CBC5EF7} = {994D89F7-E9BC-4BD0-8C44-D05297FC7E08}
{77204A90-B195-4EA4-A17B-CB74E8910FC1} = {A1917BD0-881F-4775-88D9-38D42D448CF5}
{CD113034-407F-4FA7-9706-8004406551D2} = {77204A90-B195-4EA4-A17B-CB74E8910FC1}
{C9ABEEBE-341B-47C3-941F-57EE696FC9D5} = {853477A1-9B58-4893-AFDD-577471C62DB1}
Expand Down

0 comments on commit c5eadea

Please sign in to comment.