diff --git a/Source/Meadow.Foundation.Core/Sensors/Potentiometer/Potentiometer.cs b/Source/Meadow.Foundation.Core/Sensors/Potentiometer/Potentiometer.cs
index 351dcd2f9..3a42b78f9 100644
--- a/Source/Meadow.Foundation.Core/Sensors/Potentiometer/Potentiometer.cs
+++ b/Source/Meadow.Foundation.Core/Sensors/Potentiometer/Potentiometer.cs
@@ -10,9 +10,13 @@ namespace Meadow.Foundation.Sensors;
///
public class Potentiometer : IPotentiometer, IDisposable
{
+ ///
+ public event EventHandler>? Changed;
+
private IAnalogInputPort inputPort;
private Voltage referenceVoltage;
private bool portCreated = false;
+ private Resistance? oldValue;
///
/// Gets whether this instance has been disposed.
@@ -22,7 +26,7 @@ public class Potentiometer : IPotentiometer, IDisposable
///
/// Gets the maximum resistance value of the potentiometer.
///
- public Resistance MaxResistance { get; }
+ public Resistance MaxResistance { get; private set; }
///
/// Initializes a new instance of the Potentiometer class with default reference voltage.
@@ -31,9 +35,8 @@ public class Potentiometer : IPotentiometer, IDisposable
/// The maximum resistance value of the potentiometer.
public Potentiometer(IAnalogInputPort inputPort, Resistance maxResistance)
{
- this.inputPort = inputPort;
- MaxResistance = maxResistance;
- referenceVoltage = inputPort.ReferenceVoltage;
+ Initialize(inputPort, maxResistance, inputPort.ReferenceVoltage);
+ portCreated = false;
}
///
@@ -63,6 +66,22 @@ public Potentiometer(IPin inputPin, Resistance maxResistance, Voltage referenceV
portCreated = true;
}
+ private void Initialize(IAnalogInputPort inputPort, Resistance maxResistance, Voltage refereceVoltage)
+ {
+ this.inputPort = inputPort;
+ MaxResistance = maxResistance;
+ referenceVoltage = inputPort.ReferenceVoltage;
+
+ inputPort.Updated += OnInputPortUpdated;
+ }
+
+ private void OnInputPortUpdated(object sender, IChangeResult e)
+ {
+ var newValue = new Resistance(MaxResistance.Ohms * e.New.Volts / referenceVoltage.Volts);
+ Changed?.Invoke(this, new ChangeResult(newValue, oldValue));
+ oldValue = newValue;
+ }
+
///
/// Gets the current resistance value of the potentiometer by reading the analog input.
/// Setting the resistance throws NotSupportedException as potentiometer value can only be changed mechanically.
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedAnalogInputPort.cs b/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedAnalogInputPort.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedAnalogInputPort.cs
rename to Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedAnalogInputPort.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs b/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs
new file mode 100644
index 000000000..ac4d23a8e
--- /dev/null
+++ b/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs
@@ -0,0 +1,34 @@
+using Meadow.Hardware;
+
+namespace Meadow.Foundation.Sensors;
+
+public class SimulatedDigitalOutputPort : IDigitalOutputPort
+{
+ private bool state;
+
+ public bool InitialState { get; }
+ public string Name { get; }
+
+ public SimulatedDigitalOutputPort(string name, bool initialState)
+ {
+ Name = name;
+ InitialState = state = initialState;
+ }
+
+ public virtual bool State
+ {
+ get => state;
+ set
+ {
+ state = value;
+ Resolver.Log.Info($"Output {Name} = {State}");
+ }
+ }
+
+ public IDigitalChannelInfo? Channel => null;
+ public IPin? Pin => null;
+
+ public void Dispose()
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalSignalAnalyzer.cs b/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalSignalAnalyzer.cs
new file mode 100644
index 000000000..725898d88
--- /dev/null
+++ b/Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalSignalAnalyzer.cs
@@ -0,0 +1,51 @@
+using Meadow.Hardware;
+using Meadow.Units;
+
+namespace Meadow.Foundation.Sensors;
+
+public class SimulatedDigitalSignalAnalyzer : IDigitalSignalAnalyzer
+{
+ private Frequency frequency;
+ private double dutyCycle = 0.5;
+ private ulong count;
+
+ public SimulatedDigitalSignalAnalyzer(Frequency frequency)
+ {
+ this.frequency = frequency;
+ }
+
+ public void SetDutyCycle(double dutyCycle)
+ {
+ this.dutyCycle = dutyCycle;
+ }
+
+ public double GetDutyCycle()
+ {
+ return dutyCycle;
+ }
+
+ public void SetFrequency(Frequency frequency)
+ {
+ this.frequency = frequency;
+ }
+
+ public Frequency GetFrequency()
+ {
+ return frequency;
+ }
+
+ public Frequency GetMeanFrequency()
+ {
+ return frequency;
+ }
+
+ public void SetCount(ulong count)
+ {
+ this.count = count;
+ }
+
+ public ulong GetCount()
+ {
+ return count;
+ }
+}
diff --git a/Source/Meadow.Foundation.Core/Simulation/BaseSimulatedSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/BaseSimulatedSensor.cs
similarity index 89%
rename from Source/Meadow.Foundation.Core/Simulation/BaseSimulatedSensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/BaseSimulatedSensor.cs
index 2821f1e98..7a2e64c85 100644
--- a/Source/Meadow.Foundation.Core/Simulation/BaseSimulatedSensor.cs
+++ b/Source/Meadow.Foundation.Core/Simulation/Sensors/BaseSimulatedSensor.cs
@@ -6,36 +6,6 @@
namespace Meadow.Foundation.Sensors;
-/*
-///
-/// Represents a simulated tone generator that implements both IToneGenerator and ISimulatedSensor interfaces.
-///
-public class SimulatedToneGenerator : IToneGenerator, ISimulatedSensor
-{
-}
-
-///
-/// Represents a simulated RgbPwmLed that implements both IRgbPwmLed and ISimulatedSensor interfaces.
-///
-public class SimulatedRgbPwmLed : IRgbPwmLed, ISimulatedSensor
-{
-}
-
-///
-/// Represents a simulated barometric pressure sensor that implements both IBarometricPressureSensor and ISimulatedSensor interfaces.
-///
-public class SimulatedBarometricPressureSensor : IBarometricPressureSensor, ISimulatedSensor
-{
-}
-
-///
-/// Represents a simulated gas resistance sensor that implements both IGasResistanceSensor and ISimulatedSensor interfaces.
-///
-public class SimulatedGasResistanceSensor : IGasResistanceSensor, ISimulatedSensor
-{
-}
-*/
-
///
/// A base class for simple simulated single-unit sensors
///
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulateBarometricPressureSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulateBarometricPressureSensor.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulateBarometricPressureSensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulateBarometricPressureSensor.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedAccelerometer.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedAccelerometer.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedAccelerometer.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedAccelerometer.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedCurrentSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedCurrentSensor.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedCurrentSensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedCurrentSensor.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedHallEffectFlowSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedHallEffectFlowSensor.cs
new file mode 100644
index 000000000..5494ece88
--- /dev/null
+++ b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedHallEffectFlowSensor.cs
@@ -0,0 +1,31 @@
+using Meadow.Peripherals.Sensors;
+using Meadow.Units;
+using System.Threading.Tasks;
+
+namespace Meadow.Foundation.Sensors;
+
+public class SimulatedHallEffectFlowSensor : IVolumetricFlowSensor
+{
+ private SimulatedDigitalSignalAnalyzer _analyzer;
+ private double _flowCoefficient;
+
+ public SimulatedHallEffectFlowSensor(Frequency simulatedPulseFrequency, double flowCoefficient = 80d)
+ {
+ _flowCoefficient = flowCoefficient;
+ _analyzer = new SimulatedDigitalSignalAnalyzer(simulatedPulseFrequency);
+ }
+
+ public void SetSignalFrequency(Frequency frequency)
+ {
+ _analyzer.SetFrequency(frequency);
+ }
+
+ public VolumetricFlow Flow => new VolumetricFlow(
+ _analyzer.GetFrequency().Hertz / _flowCoefficient,
+ VolumetricFlow.UnitType.LitersPerMinute);
+
+ public Task Read()
+ {
+ return Task.FromResult(Flow);
+ }
+}
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedHumiditySensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedHumiditySensor.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedHumiditySensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedHumiditySensor.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedLightSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedLightSensor.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedLightSensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedLightSensor.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedMoistureSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedMoistureSensor.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedMoistureSensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedMoistureSensor.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedRangeFinder.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedRangeFinder.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedRangeFinder.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedRangeFinder.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedRelay.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedRelay.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedRelay.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedRelay.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedSamplingSensorBase.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedSamplingSensorBase.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedSamplingSensorBase.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedSamplingSensorBase.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedSensorBase.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedSensorBase.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedSensorBase.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedSensorBase.cs
diff --git a/Source/Meadow.Foundation.Core/Simulation/SimulatedTemperatureSensor.cs b/Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedTemperatureSensor.cs
similarity index 100%
rename from Source/Meadow.Foundation.Core/Simulation/SimulatedTemperatureSensor.cs
rename to Source/Meadow.Foundation.Core/Simulation/Sensors/SimulatedTemperatureSensor.cs
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/ListBox.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/ListBox.cs
index 853e6bff5..cca0ef8f5 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/ListBox.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/ListBox.cs
@@ -27,6 +27,12 @@ public class ListBox : MicroLayout
/// Spacing, in pixels, between items
///
public int ItemSpacing { get; } = 1;
+
+ ///
+ /// Spacing, in pixels, between the control left and the left of each item
+ ///
+ public int ItemLeftMargin { get; set; } = 2;
+
///
/// Items to display in the ListBox
///
@@ -53,11 +59,11 @@ public ListBox(int left, int top, int width, int height, IFont font)
private void CreateRowLabels(int rowCount)
{
- var y = 0;
+ var y = 2;
for (var i = 0; i < rowCount; i++)
{
Controls.Add(
- new Label(Left, Top + y, this.Width, _rowHeight)
+ new Label(ItemLeftMargin, y, this.Width, _rowHeight)
{
Font = _font,
TextColor = TextColor,
@@ -182,6 +188,7 @@ private void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEven
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
+ case NotifyCollectionChangedAction.Replace:
// is the added item visible?
if (e.NewStartingIndex < TopIndex + Controls.Count)
{
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.DigiPots.Mcp4xxx/Driver/Mcp4xxx.ResistorArray.cs b/Source/Meadow.Foundation.Peripherals/ICs.DigiPots.Mcp4xxx/Driver/Mcp4xxx.ResistorArray.cs
index 98d0e8f87..a93008ca0 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.DigiPots.Mcp4xxx/Driver/Mcp4xxx.ResistorArray.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.DigiPots.Mcp4xxx/Driver/Mcp4xxx.ResistorArray.cs
@@ -1,6 +1,8 @@
using Meadow.Hardware;
using Meadow.Units;
using System;
+using System.Threading;
+using System.Threading.Tasks;
namespace Meadow.Foundation.ICs.DigiPots;
@@ -20,6 +22,9 @@ public class ResistorArray : IPotentiometer, IRheostat
private Mcp4xxx _parent;
private int _index;
private ISpiCommunications _spiComms;
+ private EventHandler>? _changedEvent;
+ private Timer? _pollTimer;
+ private Resistance? _lastValue;
///
public Resistance MaxResistance => _parent.MaxResistance;
@@ -39,6 +44,35 @@ public Resistance Resistance
}
}
+ ///
+ public event EventHandler>? Changed
+ {
+ remove
+ {
+ _changedEvent -= value;
+
+ if (_changedEvent?.GetInvocationList().Length == 0)
+ {
+ _pollTimer?.Dispose();
+ _pollTimer = null;
+ }
+ }
+ add
+ {
+ _changedEvent += value;
+ if (_pollTimer == null)
+ {
+ _pollTimer = new Timer(async (_) =>
+ {
+ var r = Resistance;
+ _changedEvent?.Invoke(this, new ChangeResult(r, _lastValue));
+ _lastValue = r;
+ await Task.Delay(500);
+ });
+ }
+ }
+ }
+
internal ResistorArray(Mcp4xxx parent, int index, ISpiCommunications spiComms)
{
if (index is < 0 or > 1) throw new ArgumentException();
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs
index 4a5f74eca..9386959c6 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs
@@ -643,5 +643,11 @@ private PortBank GetPortBankForPin(IPin pin)
}
return PortBank.A;
}
+
+ ///
+ public IDigitalSignalAnalyzer CreateDigitalSignalAnalyzer(IPin pin, bool captureDutyCycle)
+ {
+ return new SoftDigitalSignalAnalyzer(pin, captureDutyCycle: captureDutyCycle);
+ }
}
}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.cs
index 75a4603d2..7099bb077 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.cs
@@ -286,7 +286,7 @@ public void AllOn()
/// True to set the pin state high, False to set it low
protected abstract void SetPinState(IPin pin, bool state);
- void WriteUint16(ushort value)
+ private void WriteUint16(ushort value)
{
Span buffer = stackalloc byte[2];
buffer[0] = (byte)value;
@@ -313,6 +313,12 @@ private void InterruptPortChanged(object sender, DigitalPortResult e)
}
}
+ ///
+ public IDigitalSignalAnalyzer CreateDigitalSignalAnalyzer(IPin pin, bool captureDutyCycle)
+ {
+ return new SoftDigitalSignalAnalyzer(pin, captureDutyCycle: captureDutyCycle);
+ }
+
///
/// Dispose of the object
///
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr105.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr105.cs
new file mode 100644
index 000000000..9833143ab
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr105.cs
@@ -0,0 +1,22 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the GR-105 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 5.5 Hz per L/min
+///
+public class Gr105 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the GR-105 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public Gr105(IPin pin)
+ : base(pin, 5.5d)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr201.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr201.cs
new file mode 100644
index 000000000..01e0af51b
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr201.cs
@@ -0,0 +1,22 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the GR-201 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 7.5 Hz per L/min
+///
+public class Gr201 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the GR-201 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public Gr201(IPin pin)
+ : base(pin, 7.5d)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr216.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr216.cs
new file mode 100644
index 000000000..10413a93a
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/Gr216.cs
@@ -0,0 +1,22 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the GR-216 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 0.2 Hz per L/min
+///
+public class Gr216 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the GR-216 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public Gr216(IPin pin)
+ : base(pin, 0.2d)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB1.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB1.cs
new file mode 100644
index 000000000..2b3892e8c
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB1.cs
@@ -0,0 +1,23 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the YF-B1 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 11.0 Hz per L/min
+/// - Offset: 0 Hz
+///
+public class YfB1 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the YF-B9 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public YfB1(IPin pin)
+ : base(pin, 11.0)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB10.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB10.cs
new file mode 100644
index 000000000..fc97fee67
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB10.cs
@@ -0,0 +1,23 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the YF-B10 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 7.5 Hz per L/min
+/// - Offset: 4 Hz
+///
+public class YfB10 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the YF-B10 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public YfB10(IPin pin)
+ : base(pin, 7.5, 4)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB2.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB2.cs
new file mode 100644
index 000000000..7c8e8c46a
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB2.cs
@@ -0,0 +1,23 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the YF-B1 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 11.0 Hz per L/min
+/// - Offset: 0 Hz
+///
+public class YfB2 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the YF-B9 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public YfB2(IPin pin)
+ : base(pin, 11.0)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB3.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB3.cs
new file mode 100644
index 000000000..e3b2c84c4
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB3.cs
@@ -0,0 +1,23 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the YF-B3 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 11.0 Hz per L/min
+/// - Offset: 0 Hz
+///
+public class YfB3 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the YF-B9 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public YfB3(IPin pin)
+ : base(pin, 11.0)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB6.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB6.cs
new file mode 100644
index 000000000..f44d9d22b
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB6.cs
@@ -0,0 +1,23 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the YF-B10 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 6.6 Hz per L/min
+/// - Offset: 0 Hz
+///
+public class YfB6 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the YF-B6 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public YfB6(IPin pin)
+ : base(pin, 6.6d)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB9.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB9.cs
new file mode 100644
index 000000000..c5437bee3
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Drivers/YfB9.cs
@@ -0,0 +1,23 @@
+using Meadow.Hardware;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Driver for the YF-B9 Hall effect water flow sensor.
+///
+///
+/// Configures the sensor with its factory calibration values:
+/// - Scale factor: 7.5 Hz per L/min
+/// - Offset: 4 Hz
+///
+public class YfB9 : HallEffectBase
+{
+ ///
+ /// Initializes a new instance of the YF-B9 flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ public YfB9(IPin pin)
+ : base(pin, 7.5, 4)
+ {
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/HallEffectBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/HallEffectBase.cs
new file mode 100644
index 000000000..4d615bb98
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/HallEffectBase.cs
@@ -0,0 +1,69 @@
+using Meadow.Foundation;
+using Meadow.Hardware;
+using Meadow.Units;
+
+using System.Threading.Tasks;
+
+namespace Meadow.Peripherals.Sensors.Flow;
+
+///
+/// Base class for Hall effect flow sensors that measure volumetric flow based on pulse frequency.
+///
+///
+/// Hall effect flow sensors typically output a frequency proportional to the flow rate.
+/// Each sensor model has a specific calibration coefficient (Hz per L/min) used to convert
+/// the measured frequency to a flow rate.
+/// Sensors will have a flow formula in the form:
+/// F = (S * Q - O)
+/// e.g. F = (7.5 * Q - 4)
+/// where:
+/// F = Frequency
+/// Q = Flow
+/// S = Scale
+/// O = Offset
+///
+public abstract class HallEffectBase : PollingSensorBase, IVolumetricFlowSensor
+{
+ private readonly IDigitalSignalAnalyzer analyzer;
+ private readonly double scale;
+ private readonly double offset;
+
+ ///
+ /// Initializes a new instance of a Hall effect flow sensor.
+ ///
+ /// The digital input pin connected to the sensor's signal line.
+ /// The sensor scale factor (S) in Hz per L/min
+ /// The sensor offset (O) in Hz
+ protected HallEffectBase(IPin pin, double scale, double offset = 0)
+ {
+ this.scale = scale;
+ this.offset = offset;
+ analyzer = pin.CreateDigitalSignalAnalyzer(false);
+ }
+
+ ///
+ public VolumetricFlow Flow => CalculateFlow(analyzer.GetFrequency(), scale, offset);
+
+ ///
+ protected override Task ReadSensor()
+ {
+ return Task.FromResult(CalculateFlow(analyzer.GetFrequency(), scale, offset));
+ }
+
+ ///
+ /// Calculates volumetric flow rate from frequency using the formula F = (S * Q - O), solving for Q.
+ ///
+ /// The measured frequency in Hz
+ /// The scale factor (S) in Hz per L/min
+ /// The offset (O) in Hz
+ /// The flow rate in cubic meters per second
+ private VolumetricFlow CalculateFlow(Frequency frequency, double scale, double offset)
+ {
+ // First solve for Q (L/min): F = (S * Q - O)
+ // F + O = S * Q
+ // Q = (F + O) / S
+ double litersPerMinute = (frequency.Hertz + offset) / scale;
+
+ return new VolumetricFlow(litersPerMinute, VolumetricFlow.UnitType.LitersPerMinute);
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Readme.md b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Readme.md
new file mode 100644
index 000000000..86e449b92
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Readme.md
@@ -0,0 +1,92 @@
+# Meadow.Foundation.Sensors.Light.Bh1750
+
+**Bh1750 I2C luminance and color light sensor**
+
+The **Bh1750** library is included in the **Meadow.Foundation.Sensors.Light.Bh1750** nuget package and is designed for the [Wilderness Labs](www.wildernesslabs.co) Meadow .NET IoT platform.
+
+This driver is part of the [Meadow.Foundation](https://developer.wildernesslabs.co/Meadow/Meadow.Foundation/) peripherals library, an open-source repository of drivers and libraries that streamline and simplify adding hardware to your C# .NET Meadow IoT applications.
+
+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/).
+
+## Installation
+
+You can install the library from within Visual studio using the the NuGet Package Manager or from the command line using the .NET CLI:
+
+`dotnet add package Meadow.Foundation.Sensors.Light.Bh1750`
+## Usage
+
+```csharp
+Bh1750 sensor;
+
+public override Task Initialize()
+{
+ Resolver.Log.Info("Initialize...");
+
+ var i2c = Device.CreateI2cBus();
+ sensor = new Bh1750(
+ i2c,
+ measuringMode: Mode.ContinuouslyHighResolutionMode, // the various modes take differing amounts of time.
+ lightTransmittance: 1 // lower this to increase sensitivity, for instance, if it's behind a semi opaque window
+ );
+
+ // Example that uses an IObservable subscription to only be notified when the filter is satisfied
+ var consumer = Bh1750.CreateObserver(
+ handler: result => Resolver.Log.Info($"Observer: filter satisfied: {result.New.Lux:N2}Lux, old: {result.Old?.Lux:N2}Lux"),
+
+ // only notify if the visible light changes by 100 lux (put your hand over the sensor to trigger)
+ filter: result =>
+ {
+ if (result.Old is { } old)
+ {
+ // returns true if > 100lux change
+ return ((result.New - old).Abs().Lux > 100);
+ }
+ return false;
+ });
+ sensor.Subscribe(consumer);
+
+ // classical .NET events can also be used:
+ sensor.Updated += (sender, result) => Resolver.Log.Info($"Light: {result.New.Lux:N2}Lux");
+
+ return Task.CompletedTask;
+}
+
+public override async Task Run()
+{
+ var result = await sensor.Read();
+ Resolver.Log.Info("Initial Readings:");
+ Resolver.Log.Info($" Light: {result.Lux:N2}Lux");
+
+ sensor.StartUpdating(TimeSpan.FromSeconds(1));
+}
+
+```
+## 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/).
+## About Meadow
+
+Meadow is a complete, IoT platform with defense-grade security that runs full .NET applications on embeddable microcontrollers and Linux single-board computers including Raspberry Pi and NVIDIA Jetson.
+
+### Build
+
+Use the full .NET platform and tooling such as Visual Studio and plug-and-play hardware drivers to painlessly build IoT solutions.
+
+### Connect
+
+Utilize native support for WiFi, Ethernet, and Cellular connectivity to send sensor data to the Cloud and remotely control your peripherals.
+
+### Deploy
+
+Instantly deploy and manage your fleet in the cloud for OtA, health-monitoring, logs, command + control, and enterprise backend integrations.
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Sensors.Flow.HallEffect.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Sensors.Flow.HallEffect.csproj
new file mode 100644
index 000000000..48747d866
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Flow.HallEffect/Driver/Sensors.Flow.HallEffect.csproj
@@ -0,0 +1,28 @@
+
+
+ 1.11.0
+ Readme.md
+ enable
+ 10.0
+ Apache-2.0
+ true
+ icon.png
+ Wilderness Labs, Inc
+ netstandard2.1
+ Library
+ HallEffectFlowSensors
+ Wilderness Labs, Inc
+ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/
+ Meadow.Foundation.Sensors.Flow.HallEffect
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Meadow.Foundation,flow,YF-B10,GR-105,GR-201,GR-216
+ true
+ Drivers for various hall effect flow sensor
+ Meadow.Foundation.Sensors.Flow
+
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Keyboard.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Keyboard.cs
index 60ee38043..d63f26bcb 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Keyboard.cs
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Keyboard.cs
@@ -166,4 +166,10 @@ public IDigitalOutputPort CreateDigitalOutputPort(IPin pin, bool initialState =
return new KeyboardIndicator(pin, ci, initialState ? true : null);
}
+
+ ///
+ public IDigitalSignalAnalyzer CreateDigitalSignalAnalyzer(IPin pin, bool captureDutyCycle)
+ {
+ return new SoftDigitalSignalAnalyzer(pin, captureDutyCycle: captureDutyCycle);
+ }
}
diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln
index 20a6a49de..5a12d6827 100644
--- a/Source/Meadow.Foundation.sln
+++ b/Source/Meadow.Foundation.sln
@@ -1632,8 +1632,13 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Keller XLine", "Keller XLine", "{2240AB38-3CC6-4800-8556-D3BB5C44B720}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Environmental.Keller.XLine", "Meadow.Foundation.Peripherals\Sensors.Environmental.Keller.XLine\Driver\Sensors.Environmental.Keller.XLine.csproj", "{729B86E1-49EE-4668-A599-8D7C28842F9E}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epd2in15g_Sample", "Meadow.Foundation.Peripherals\Displays.ePaperWaveShare\Samples\Epd2in15g_Sample\Epd2in15g_Sample.csproj", "{EA8D8CA1-BB32-49D6-88CF-9EB50ABDC44B}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flow", "Flow", "{C5AA856B-4199-43B1-AECE-8871E91A0EF1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sensors.Flow.HallEffect", "Meadow.Foundation.Peripherals\Sensors.Flow.HallEffect\Driver\Sensors.Flow.HallEffect.csproj", "{EE40720A-33B0-4151-80AE-F73F9C1A45D8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -3954,6 +3959,12 @@ Global
{EA8D8CA1-BB32-49D6-88CF-9EB50ABDC44B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA8D8CA1-BB32-49D6-88CF-9EB50ABDC44B}.Release|Any CPU.Build.0 = Release|Any CPU
{EA8D8CA1-BB32-49D6-88CF-9EB50ABDC44B}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -4768,6 +4779,8 @@ Global
{2240AB38-3CC6-4800-8556-D3BB5C44B720} = {78E463DA-0FA1-4AAE-A281-D3297C9388C9}
{729B86E1-49EE-4668-A599-8D7C28842F9E} = {2240AB38-3CC6-4800-8556-D3BB5C44B720}
{EA8D8CA1-BB32-49D6-88CF-9EB50ABDC44B} = {7311794D-7D2F-47E8-A5B0-C216CBD64A13}
+ {C5AA856B-4199-43B1-AECE-8871E91A0EF1} = {9F4EEBFB-F2B6-4B28-ABAD-D219F4AB15F3}
+ {EE40720A-33B0-4151-80AE-F73F9C1A45D8} = {C5AA856B-4199-43B1-AECE-8871E91A0EF1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}