Skip to main content

Units

Throughout the Meadow stack, strongly-typed units such as Temperature, Length, Frequency, and Speed, are used in place of primitive types like float or integer to prevent errors due to unit ambiguity, conversion, or mismatch.

Units in Action

These units are used extensively in both Meadow.Core APIs as well as Meadow.Foundation drivers. For instance, when reading from an IAnalogInputPort, the value returned is of the Voltage unit type:

IAnalogInputPort analogIn = Device.CreateAnalogInputPort(Device.Pins.A00);
Voltage voltageReading = await analogIn.Read();

Similarly, in Meadow.Foundation, the AnalogTemperatureSensor driver returns a Temperature object when reading it:

AnalogTemperature analogTemperature = new AnalogTemperature (
Device, Device.Pins.A00, AnalogTemperature.KnownSensorType.LM35
);
Temperature temperature = await analogTemperature.Read();

Unit Conversions

Each of these units have an enum of UnitTypes that they can be described as, as well as accessed as, via properties.

For instance the Temperature type has properties such as Fahrenheit, Celsius, Kelvin, etc. that allow you to access the unit value, converted to that particular UnitType. Consider the following code:

var temp = new Temperature(32, UnitType.Fahrenheit);
Console.WriteLine($"{temp.Celsius:N2}C"); // outputs `0C`
Console.WriteLine($"{temp.Fahrenheit:N2}F"); // outputs `32F`

The units are all lightweight struct types which help to reduce heap allocations (when not boxed by Nullable), and have built in math operator and comparison support so you can perform math operations and comparison such as:

Temperature t1 = new Temperature(1);
Temperature t2 = new Temperature(10);
Assert.That(t1 != t2);
Assert.That((t1 + t2) == new Temperature(11));
Assert.That((t2 - t1) == new Temperature(9));
Assert.That(t1 < t2);

IChangeResult<UNIT>

To help support the units architecture, the IChangeResult<UNIT> is used where .NET APIs typically use an EventArgs type which has the properties of New and Old, to carry data from the current event/notification, as well as the last event, for comparison, if one existed:

public interface IChangeResult<UNIT> where UNIT: struct
{
UNIT New { get; set; }
UNIT? Old { get; set; }
}

Nullability

Note the Old property is nullable because, typically, on the first notification, there won't be a previous reading, and this provides the ability to use C# 8's nullable patterns to prevent the dreaded Null Reference Error:

Console.WriteLine($"new: {result.New.Celsius:N2}C, old: {result.Old?.Celsius:N2}C");

IChangeResult in Use

IChangeResult<UNIT> is used for nearly all events and notifications in Meadow. For instance, the TemperatureUpdated event in ITemperatureSensor has the following signature:

event EventHandler<IChangeResult<Temperature>> TemperatureUpdated;

Additionally, there is an accompanying ChangeResult<UNIT> class that provides a concrete implementation for the interface.

As opposed to EventArgs, ChangeResult<UNIT> has the advantage of being a struct, which helps prevent prevent allocations and Garbage Collector (GC) churn.

Units List

The following is a complete list of unit types currently available:

  • AbsoluteHumidity
  • Acceleration
  • Acceleration3D
  • Angle
  • AngularAcceleration
  • AngularAcceleration3D
  • AngularVelocity
  • Azimuth
  • Concentration
  • Current
  • Density
  • Energy
  • Frequency
  • Illuminance
  • Length
  • MagneticField
  • MagneticField3D
  • Mass
  • Power
  • Pressure
  • RelativeHumidity
  • Speed
  • Temperature
  • Torque
  • Voltage
  • Volume

Next - Events and IObservable