Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/potentiometer #1107

Merged
merged 10 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
/// </summary>
public class Potentiometer : IPotentiometer, IDisposable
{
/// <inheritdoc/>
public event EventHandler<IChangeResult<Resistance>>? Changed;

private IAnalogInputPort inputPort;
private Voltage referenceVoltage;
private bool portCreated = false;
private Resistance? oldValue;

/// <summary>
/// Gets whether this instance has been disposed.
Expand All @@ -22,18 +26,17 @@
/// <summary>
/// Gets the maximum resistance value of the potentiometer.
/// </summary>
public Resistance MaxResistance { get; }
public Resistance MaxResistance { get; private set; }

/// <summary>
/// Initializes a new instance of the Potentiometer class with default reference voltage.
/// </summary>
/// <param name="inputPort">The input port to read the potentiometer value from.</param>
/// <param name="maxResistance">The maximum resistance value of the potentiometer.</param>
public Potentiometer(IAnalogInputPort inputPort, Resistance maxResistance)

Check warning on line 36 in Source/Meadow.Foundation.Core/Sensors/Potentiometer/Potentiometer.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field 'inputPort' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
{
this.inputPort = inputPort;
MaxResistance = maxResistance;
referenceVoltage = inputPort.ReferenceVoltage;
Initialize(inputPort, maxResistance, inputPort.ReferenceVoltage);
portCreated = false;
}

/// <summary>
Expand Down Expand Up @@ -63,6 +66,22 @@
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<Voltage> e)
{
var newValue = new Resistance(MaxResistance.Ohms * e.New.Volts / referenceVoltage.Volts);
Changed?.Invoke(this, new ChangeResult<Resistance>(newValue, oldValue));
oldValue = newValue;
}

/// <summary>
/// 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Meadow.Hardware;

namespace Meadow.Foundation.Sensors;

public class SimulatedDigitalOutputPort : IDigitalOutputPort

Check warning on line 5 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'SimulatedDigitalOutputPort'
{
private bool state;

public bool InitialState { get; }

Check warning on line 9 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'SimulatedDigitalOutputPort.InitialState'
public string Name { get; }

Check warning on line 10 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'SimulatedDigitalOutputPort.Name'

public SimulatedDigitalOutputPort(string name, bool initialState)

Check warning on line 12 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'SimulatedDigitalOutputPort.SimulatedDigitalOutputPort(string, bool)'
{
Name = name;
InitialState = state = initialState;
}

public virtual bool State

Check warning on line 18 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'SimulatedDigitalOutputPort.State'
{
get => state;
set
{
state = value;
Resolver.Log.Info($"Output {Name} = {State}");
}
}

public IDigitalChannelInfo? Channel => null;

Check warning on line 28 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of reference types in return type of 'IDigitalChannelInfo? SimulatedDigitalOutputPort.Channel.get' doesn't match implicitly implemented member 'IDigitalChannelInfo IPort<IDigitalChannelInfo>.Channel.get' (possibly because of nullability attributes).
public IPin? Pin => null;

Check warning on line 29 in Source/Meadow.Foundation.Core/Simulation/Ports/SimulatedDigitalOutputPort.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of reference types in return type of 'IPin? SimulatedDigitalOutputPort.Pin.get' doesn't match implicitly implemented member 'IPin IPort<IDigitalChannelInfo>.Pin.get' (possibly because of nullability attributes).

public void Dispose()
{
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,6 @@

namespace Meadow.Foundation.Sensors;

/*
/// <summary>
/// Represents a simulated tone generator that implements both IToneGenerator and ISimulatedSensor interfaces.
/// </summary>
public class SimulatedToneGenerator : IToneGenerator, ISimulatedSensor
{
}

/// <summary>
/// Represents a simulated RgbPwmLed that implements both IRgbPwmLed and ISimulatedSensor interfaces.
/// </summary>
public class SimulatedRgbPwmLed : IRgbPwmLed, ISimulatedSensor
{
}

/// <summary>
/// Represents a simulated barometric pressure sensor that implements both IBarometricPressureSensor and ISimulatedSensor interfaces.
/// </summary>
public class SimulatedBarometricPressureSensor : IBarometricPressureSensor, ISimulatedSensor
{
}

/// <summary>
/// Represents a simulated gas resistance sensor that implements both IGasResistanceSensor and ISimulatedSensor interfaces.
/// </summary>
public class SimulatedGasResistanceSensor : IGasResistanceSensor, ISimulatedSensor
{
}
*/

/// <summary>
/// A base class for simple simulated single-unit sensors
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<VolumetricFlow> Read()
{
return Task.FromResult(Flow);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ public class ListBox : MicroLayout
/// Spacing, in pixels, between items
/// </summary>
public int ItemSpacing { get; } = 1;

/// <summary>
/// Spacing, in pixels, between the control left and the left of each item
/// </summary>
public int ItemLeftMargin { get; set; } = 2;

/// <summary>
/// Items to display in the ListBox
/// </summary>
Expand All @@ -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,
Expand Down Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Meadow.Hardware;
using Meadow.Units;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Meadow.Foundation.ICs.DigiPots;

Expand All @@ -20,6 +22,9 @@ public class ResistorArray : IPotentiometer, IRheostat
private Mcp4xxx _parent;
private int _index;
private ISpiCommunications _spiComms;
private EventHandler<IChangeResult<Resistance>>? _changedEvent;
private Timer? _pollTimer;
private Resistance? _lastValue;

/// <inheritdoc/>
public Resistance MaxResistance => _parent.MaxResistance;
Expand All @@ -39,6 +44,35 @@ public Resistance Resistance
}
}

/// <inheritdoc/>
public event EventHandler<IChangeResult<Resistance>>? 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<Resistance>(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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,5 +643,11 @@ private PortBank GetPortBankForPin(IPin pin)
}
return PortBank.A;
}

/// <inheritdoc/>
public IDigitalSignalAnalyzer CreateDigitalSignalAnalyzer(IPin pin, bool captureDutyCycle)
{
return new SoftDigitalSignalAnalyzer(pin, captureDutyCycle: captureDutyCycle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public void AllOn()
/// <param name="state"><b>True</b> to set the pin state high, <b>False</b> to set it low</param>
protected abstract void SetPinState(IPin pin, bool state);

void WriteUint16(ushort value)
private void WriteUint16(ushort value)
{
Span<byte> buffer = stackalloc byte[2];
buffer[0] = (byte)value;
Expand All @@ -313,6 +313,12 @@ private void InterruptPortChanged(object sender, DigitalPortResult e)
}
}

/// <inheritdoc/>
public IDigitalSignalAnalyzer CreateDigitalSignalAnalyzer(IPin pin, bool captureDutyCycle)
{
return new SoftDigitalSignalAnalyzer(pin, captureDutyCycle: captureDutyCycle);
}

/// <summary>
/// Dispose of the object
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Meadow.Hardware;

namespace Meadow.Peripherals.Sensors.Flow;

/// <summary>
/// Driver for the GR-105 Hall effect water flow sensor.
/// </summary>
/// <remarks>
/// Configures the sensor with its factory calibration values:
/// - Scale factor: 5.5 Hz per L/min
/// </remarks>
public class Gr105 : HallEffectBase
{
/// <summary>
/// Initializes a new instance of the GR-105 flow sensor.
/// </summary>
/// <param name="pin">The digital input pin connected to the sensor's signal line.</param>
public Gr105(IPin pin)
: base(pin, 5.5d)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Meadow.Hardware;

namespace Meadow.Peripherals.Sensors.Flow;

/// <summary>
/// Driver for the GR-201 Hall effect water flow sensor.
/// </summary>
/// <remarks>
/// Configures the sensor with its factory calibration values:
/// - Scale factor: 7.5 Hz per L/min
/// </remarks>
public class Gr201 : HallEffectBase
{
/// <summary>
/// Initializes a new instance of the GR-201 flow sensor.
/// </summary>
/// <param name="pin">The digital input pin connected to the sensor's signal line.</param>
public Gr201(IPin pin)
: base(pin, 7.5d)
{
}
}
Loading
Loading