From 8360553f46c3d991b53bdae7aa748f068a44621b Mon Sep 17 00:00:00 2001 From: Adrian Stevens Date: Sun, 6 Aug 2023 15:06:36 -0700 Subject: [PATCH] Improved sampling logic --- .../Sensors.Distance.Me007ys/Driver/Me007y.cs | 94 ++++++++++++------- .../Samples/Me007ys_Sample/MeadowApp.cs | 8 +- 2 files changed, 65 insertions(+), 37 deletions(-) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Driver/Me007y.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Driver/Me007y.cs index f56266106c..b01577035c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Driver/Me007y.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Driver/Me007y.cs @@ -2,6 +2,8 @@ using Meadow.Peripherals.Sensors; using Meadow.Units; using System; +using System.Net.Http.Headers; +using System.Threading; using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Distance @@ -9,7 +11,7 @@ namespace Meadow.Foundation.Sensors.Distance /// /// Represents the ME007YS serial distance sensor /// - public class Me007ys : ByteCommsSensorBase, IRangeFinder + public class Me007ys : PollingSensorBase, IRangeFinder, ISleepAwarePeripheral { /// /// Raised when the value of the reading changes @@ -28,9 +30,10 @@ public class Me007ys : ByteCommsSensorBase, IRangeFinder static readonly byte[] readBuffer = new byte[16]; - DateTime lastUpdate = DateTime.MinValue; + private TaskCompletionSource dataReceivedTaskCompletionSource; + + bool createdSerialPort = false; - TimeSpan? updateInterval; /// /// Creates a new ME007YS object communicating over serial @@ -39,7 +42,9 @@ public class Me007ys : ByteCommsSensorBase, IRangeFinder /// The serial port public Me007ys(IMeadowDevice device, SerialPortName serialPortName) : this(device.CreateSerialPort(serialPortName, portSpeed)) - { } + { + createdSerialPort = true; + } /// /// Creates a new ME007YS object communicating over serial @@ -47,8 +52,7 @@ public Me007ys(IMeadowDevice device, SerialPortName serialPortName) /// The serial message port public Me007ys(ISerialPort serialMessage) { - this.serialPort = serialMessage; - this.serialPort.DataReceived += SerialPort_DataReceived; + serialPort = serialMessage; } /// @@ -56,7 +60,15 @@ public Me007ys(ISerialPort serialMessage) /// public void MeasureDistance() { - _ = ReadSensor(); + _ = Read(); + } + + /// + /// Convenience method to get the current sensor reading + /// + public override Task Read() + { + return ReadSensor(); } /// @@ -65,8 +77,7 @@ public void MeasureDistance() /// protected override Task ReadSensor() { - var len = Distance != null ? Distance.Value : new Length(0); - return Task.FromResult(len); + return ReadSingleValueAsync(); } /// @@ -87,12 +98,12 @@ public override void StartUpdating(TimeSpan? updateInterval) { lock (samplingLock) { - if (IsSampling) return; - IsSampling = true; - - this.updateInterval = updateInterval; + if(serialPort.IsOpen == false) + { + serialPort.Open(); + } - serialPort.Open(); + base.StartUpdating(updateInterval); } } @@ -103,41 +114,58 @@ public override void StopUpdating() { lock (samplingLock) { - if (!IsSampling) { return; } - IsSampling = false; - - updateInterval = null; - - serialPort.Close(); + serialPort?.Close(); + base.StopUpdating(); } } //This sensor will write a single byte of 0xFF alternating with //3 bytes: 2 bytes for distance and a 3rd for the checksum //when 3 bytes are available we know we have a distance reading ready - private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) + public async Task ReadSingleValueAsync() + { + if (serialPort.IsOpen == false) + serialPort.Open(); + + dataReceivedTaskCompletionSource = new TaskCompletionSource(); + + serialPort.DataReceived += SerialPortDataReceived; + + var result = await dataReceivedTaskCompletionSource.Task; + + serialPort.DataReceived -= SerialPortDataReceived; + + return result; + } + + private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) { var len = serialPort.BytesToRead; serialPort.Read(readBuffer, 0, Math.Min(len, readBuffer.Length)); - if (len == 3) { var mm = readBuffer[0] << 8 | readBuffer[1]; - ChangeResult changeResult = new ChangeResult() - { - New = new Length(mm, Length.UnitType.Millimeters), - Old = Distance, - }; - - Distance = changeResult.New; - - if (updateInterval == null || DateTime.Now - lastUpdate >= updateInterval) + if (mm != 0) { - lastUpdate = DateTime.Now; - RaiseEventsAndNotify(changeResult); + var length = new Length(mm, Length.UnitType.Millimeters); + dataReceivedTaskCompletionSource.SetResult(length); } } } + + public Task BeforeSleep(CancellationToken cancellationToken) + { + if(createdSerialPort && serialPort != null && serialPort.IsOpen) + { + serialPort.Close(); + } + return Task.CompletedTask; + } + + public Task AfterWake(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Samples/Me007ys_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Samples/Me007ys_Sample/MeadowApp.cs index 8a20ffd95d..3d3e07c1bf 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Samples/Me007ys_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Me007ys/Samples/Me007ys_Sample/MeadowApp.cs @@ -18,7 +18,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - me007ys = new Me007ys(Device, Device.PlatformOS.GetSerialPortName("COM4")); + me007ys = new Me007ys(Device, Device.PlatformOS.GetSerialPortName("COM1")); var consumer = Me007ys.CreateObserver( handler: result => @@ -44,14 +44,14 @@ public override Task Initialize() public override async Task Run() { var distance = await me007ys.Read(); - Resolver.Log.Info($"Distance is: {distance.Centimeters}cm"); + Resolver.Log.Info($"Initial distance is: {distance.Centimeters:N2}cm / {distance.Inches:N2}in"); - me007ys.StartUpdating(TimeSpan.FromSeconds(1)); + me007ys.StartUpdating(TimeSpan.FromSeconds(2)); } private void Me007y_DistanceUpdated(object sender, IChangeResult e) { - Resolver.Log.Info($"Length: {e.New.Centimeters}cm"); + Resolver.Log.Info($"Distance: {e.New.Centimeters:N2}cm / {e.New.Inches:N2}in"); } //