Skip to content

Commit

Permalink
Improved sampling logic
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianstevens committed Aug 6, 2023
1 parent faa0ecb commit 8360553
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
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
{
/// <summary>
/// Represents the ME007YS serial distance sensor
/// </summary>
public class Me007ys : ByteCommsSensorBase<Length>, IRangeFinder
public class Me007ys : PollingSensorBase<Length>, IRangeFinder, ISleepAwarePeripheral
{
/// <summary>
/// Raised when the value of the reading changes
Expand All @@ -28,9 +30,10 @@ public class Me007ys : ByteCommsSensorBase<Length>, IRangeFinder

static readonly byte[] readBuffer = new byte[16];

DateTime lastUpdate = DateTime.MinValue;
private TaskCompletionSource<Length> dataReceivedTaskCompletionSource;

bool createdSerialPort = false;

TimeSpan? updateInterval;

/// <summary>
/// Creates a new ME007YS object communicating over serial
Expand All @@ -39,24 +42,33 @@ public class Me007ys : ByteCommsSensorBase<Length>, IRangeFinder
/// <param name="serialPortName">The serial port</param>
public Me007ys(IMeadowDevice device, SerialPortName serialPortName)
: this(device.CreateSerialPort(serialPortName, portSpeed))
{ }
{
createdSerialPort = true;
}

/// <summary>
/// Creates a new ME007YS object communicating over serial
/// </summary>
/// <param name="serialMessage">The serial message port</param>
public Me007ys(ISerialPort serialMessage)
{
this.serialPort = serialMessage;
this.serialPort.DataReceived += SerialPort_DataReceived;
serialPort = serialMessage;
}

/// <summary>
/// Start a distance measurement
/// </summary>
public void MeasureDistance()
{
_ = ReadSensor();
_ = Read();
}

/// <summary>
/// Convenience method to get the current sensor reading
/// </summary>
public override Task<Length> Read()
{
return ReadSensor();
}

/// <summary>
Expand All @@ -65,8 +77,7 @@ public void MeasureDistance()
/// <returns></returns>
protected override Task<Length> ReadSensor()
{
var len = Distance != null ? Distance.Value : new Length(0);
return Task.FromResult(len);
return ReadSingleValueAsync();
}

/// <summary>
Expand All @@ -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);
}
}

Expand All @@ -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<Length> ReadSingleValueAsync()
{
if (serialPort.IsOpen == false)
serialPort.Open();

dataReceivedTaskCompletionSource = new TaskCompletionSource<Length>();

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<Length> changeResult = new ChangeResult<Length>()
{
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 =>
Expand All @@ -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<Length> e)
{
Resolver.Log.Info($"Length: {e.New.Centimeters}cm");
Resolver.Log.Info($"Distance: {e.New.Centimeters:N2}cm / {e.New.Inches:N2}in");
}

//<!=SNOP=>
Expand Down

0 comments on commit 8360553

Please sign in to comment.