-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1103 from WildernessLabs/bug/ct-interface
CTs are ICurrentSensors
- Loading branch information
Showing
1 changed file
with
129 additions
and
129 deletions.
There are no files selected for viewing
258 changes: 129 additions & 129 deletions
258
...Meadow.Foundation.Peripherals/Sensors.Power.CurrentTransducer/Driver/CurrentTransducer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,157 +1,157 @@ | ||
using Meadow.Hardware; | ||
using Meadow.Peripherals.Sensors; | ||
using Meadow.Units; | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Meadow.Foundation.Sensors.Power | ||
namespace Meadow.Foundation.Sensors.Power; | ||
|
||
/// <summary> | ||
/// Represents a general Current Transducer (CT) sensor | ||
/// </summary> | ||
public partial class CurrentTransducer : SamplingSensorBase<Current>, ICurrentSensor | ||
{ | ||
/// <summary> | ||
/// Represents a general Current Transducer (CT) sensor | ||
/// The analog input port connected to the transducer | ||
/// </summary> | ||
protected IAnalogInputPort AnalogPort { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The maximum voltage the CT outputs | ||
/// </summary> | ||
protected Voltage MaxVoltage { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The sensed current at the maximum output voltage | ||
/// </summary> | ||
protected Current MaxCurrent { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The minimum voltage the CT outputs | ||
/// </summary> | ||
protected Voltage MinVoltage { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The sensed current at the minimum output voltage | ||
/// </summary> | ||
public partial class CurrentTransducer : SamplingSensorBase<Current> | ||
protected Current MinCurrent { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The minimum output voltage | ||
/// </summary> | ||
protected Current MinVoltageDelta { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The last sensed Current | ||
/// </summary> | ||
public Current? Current { get; protected set; } | ||
|
||
/// <summary> | ||
/// Creates a new CurrentTransducer instance | ||
/// </summary> | ||
/// <param name="analogPort">The analog input port connected to the transducer</param> | ||
/// <param name="maxVoltage">The maximum voltage the CT outputs</param> | ||
/// <param name="maxCurrent">The sensed current at the maximum output voltage</param> | ||
/// <param name="minVoltage">The minimum voltage the CT outputs</param> | ||
/// <param name="minCurrent">The sensed current at the minimum output voltage</param> | ||
public CurrentTransducer(IAnalogInputPort analogPort, Voltage maxVoltage, Current maxCurrent, Voltage? minVoltage = null, Current? minCurrent = null) | ||
{ | ||
/// <summary> | ||
/// The analog input port connected to the transducer | ||
/// </summary> | ||
protected IAnalogInputPort AnalogPort { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The maximum voltage the CT outputs | ||
/// </summary> | ||
protected Voltage MaxVoltage { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The sensed current at the maximum output voltage | ||
/// </summary> | ||
protected Current MaxCurrent { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The minimum voltage the CT outputs | ||
/// </summary> | ||
protected Voltage MinVoltage { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The sensed current at the minimum output voltage | ||
/// </summary> | ||
protected Current MinCurrent { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The minimum output voltage | ||
/// </summary> | ||
protected Current MinVoltageDelta { get; private set; } = default!; | ||
|
||
/// <summary> | ||
/// The last sensed Current | ||
/// </summary> | ||
public Current? Current { get; protected set; } | ||
|
||
/// <summary> | ||
/// Creates a new CurrentTransducer instance | ||
/// </summary> | ||
/// <param name="analogPort">The analog input port connected to the transducer</param> | ||
/// <param name="maxVoltage">The maximum voltage the CT outputs</param> | ||
/// <param name="maxCurrent">The sensed current at the maximum output voltage</param> | ||
/// <param name="minVoltage">The minimum voltage the CT outputs</param> | ||
/// <param name="minCurrent">The sensed current at the minimum output voltage</param> | ||
public CurrentTransducer(IAnalogInputPort analogPort, Voltage maxVoltage, Current maxCurrent, Voltage? minVoltage = null, Current? minCurrent = null) | ||
{ | ||
Initialize(analogPort, maxVoltage, maxCurrent, minVoltage, minCurrent); | ||
} | ||
Initialize(analogPort, maxVoltage, maxCurrent, minVoltage, minCurrent); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a new CurrentTransducer instance | ||
/// </summary> | ||
protected CurrentTransducer() | ||
{ | ||
} | ||
/// <summary> | ||
/// Creates a new CurrentTransducer instance | ||
/// </summary> | ||
protected CurrentTransducer() | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Initializes the CurrentTransducer instance | ||
/// Use this method when a derived class must do pre-initialization work | ||
/// </summary> | ||
/// <param name="analogPort">The analog input port connected to the transducer</param> | ||
/// <param name="maxVoltage">The maximum voltage the CT outputs</param> | ||
/// <param name="maxCurrent">The sensed current at the maximum output voltage</param> | ||
/// <param name="minVoltage">The minimum voltage the CT outputs</param> | ||
/// <param name="minCurrent">The sensed current at the minimum output voltage</param> | ||
protected virtual void Initialize(IAnalogInputPort analogPort, Voltage maxVoltage, Current maxCurrent, Voltage? minVoltage = null, Current? minCurrent = null) | ||
{ | ||
AnalogPort = analogPort; | ||
MaxVoltage = maxVoltage; | ||
MaxCurrent = maxCurrent; | ||
MinVoltage = minVoltage ?? new Voltage(0, Voltage.UnitType.Volts); | ||
MinCurrent = minCurrent ?? new Current(0, Units.Current.UnitType.Amps); | ||
|
||
AnalogPort.Subscribe | ||
( | ||
IAnalogInputPort.CreateObserver( | ||
result => | ||
/// <summary> | ||
/// Initializes the CurrentTransducer instance | ||
/// Use this method when a derived class must do pre-initialization work | ||
/// </summary> | ||
/// <param name="analogPort">The analog input port connected to the transducer</param> | ||
/// <param name="maxVoltage">The maximum voltage the CT outputs</param> | ||
/// <param name="maxCurrent">The sensed current at the maximum output voltage</param> | ||
/// <param name="minVoltage">The minimum voltage the CT outputs</param> | ||
/// <param name="minCurrent">The sensed current at the minimum output voltage</param> | ||
protected virtual void Initialize(IAnalogInputPort analogPort, Voltage maxVoltage, Current maxCurrent, Voltage? minVoltage = null, Current? minCurrent = null) | ||
{ | ||
AnalogPort = analogPort; | ||
MaxVoltage = maxVoltage; | ||
MaxCurrent = maxCurrent; | ||
MinVoltage = minVoltage ?? new Voltage(0, Voltage.UnitType.Volts); | ||
MinCurrent = minCurrent ?? new Current(0, Units.Current.UnitType.Amps); | ||
|
||
AnalogPort.Subscribe | ||
( | ||
IAnalogInputPort.CreateObserver( | ||
result => | ||
{ | ||
ChangeResult<Current> changeResult = new() | ||
{ | ||
ChangeResult<Current> changeResult = new() | ||
{ | ||
New = ConvertVoltageToCurrent(result.New), | ||
Old = Current | ||
}; | ||
Current = changeResult.New; | ||
RaiseEventsAndNotify(changeResult); | ||
} | ||
) | ||
); | ||
} | ||
New = ConvertVoltageToCurrent(result.New), | ||
Old = Current | ||
}; | ||
Current = changeResult.New; | ||
RaiseEventsAndNotify(changeResult); | ||
} | ||
) | ||
); | ||
} | ||
|
||
/// <summary> | ||
/// Converts an output voltage from the CT to a sensed current using linear interpolation | ||
/// </summary> | ||
/// <param name="voltage">The ADC voltage read by the AnalogPort</param> | ||
/// <returns>The current being sensed by the CT</returns> | ||
protected virtual Current ConvertVoltageToCurrent(Voltage voltage) | ||
{ | ||
// the default implementation just does a simple linear conversion | ||
return new Current( | ||
(MaxCurrent.Amps - MinCurrent.Amps) / | ||
(MaxVoltage.Volts - MinVoltage.Volts) | ||
* voltage.Volts); | ||
} | ||
/// <summary> | ||
/// Converts an output voltage from the CT to a sensed current using linear interpolation | ||
/// </summary> | ||
/// <param name="voltage">The ADC voltage read by the AnalogPort</param> | ||
/// <returns>The current being sensed by the CT</returns> | ||
protected virtual Current ConvertVoltageToCurrent(Voltage voltage) | ||
{ | ||
// the default implementation just does a simple linear conversion | ||
return new Current( | ||
(MaxCurrent.Amps - MinCurrent.Amps) / | ||
(MaxVoltage.Volts - MinVoltage.Volts) | ||
* voltage.Volts); | ||
} | ||
|
||
///<inheritdoc/> | ||
protected override async Task<Current> ReadSensor() | ||
{ | ||
var adc = await AnalogPort.Read(); | ||
var newCurrent = ConvertVoltageToCurrent(adc); | ||
Current = newCurrent; | ||
return newCurrent; | ||
} | ||
///<inheritdoc/> | ||
protected override async Task<Current> ReadSensor() | ||
{ | ||
var adc = await AnalogPort.Read(); | ||
var newCurrent = ConvertVoltageToCurrent(adc); | ||
Current = newCurrent; | ||
return newCurrent; | ||
} | ||
|
||
///<inheritdoc/> | ||
public override void StartUpdating(TimeSpan? updateInterval = null) | ||
///<inheritdoc/> | ||
public override void StartUpdating(TimeSpan? updateInterval = null) | ||
{ | ||
lock (samplingLock) | ||
{ | ||
lock (samplingLock) | ||
{ | ||
if (IsSampling) return; | ||
IsSampling = true; | ||
if (IsSampling) return; | ||
IsSampling = true; | ||
|
||
base.SamplingTokenSource = new CancellationTokenSource(); | ||
CancellationToken ct = SamplingTokenSource.Token; | ||
base.SamplingTokenSource = new CancellationTokenSource(); | ||
CancellationToken ct = SamplingTokenSource.Token; | ||
|
||
AnalogPort.StartUpdating(updateInterval); | ||
} | ||
AnalogPort.StartUpdating(updateInterval); | ||
} | ||
} | ||
|
||
///<inheritdoc/> | ||
public override void StopUpdating() | ||
///<inheritdoc/> | ||
public override void StopUpdating() | ||
{ | ||
lock (samplingLock) | ||
{ | ||
lock (samplingLock) | ||
{ | ||
if (!IsSampling) return; | ||
if (!IsSampling) return; | ||
|
||
AnalogPort.StopUpdating(); | ||
AnalogPort.StopUpdating(); | ||
|
||
SamplingTokenSource?.Cancel(); | ||
SamplingTokenSource?.Cancel(); | ||
|
||
// state machine | ||
IsSampling = false; | ||
} | ||
// state machine | ||
IsSampling = false; | ||
} | ||
} | ||
} |