-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUltrasonicDistanceSensor.cs
More file actions
84 lines (67 loc) · 3.05 KB
/
UltrasonicDistanceSensor.cs
File metadata and controls
84 lines (67 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System.Device.Gpio;
using Iot.Device.Hcsr04;
using UnitsNet;
namespace Distance {
internal enum MeasureUnit { mm = 1, cm = 10, m = 100 }
internal class UltrasonicDistanceSensor : Device
{
private readonly int _triggerPin;
private readonly int _echoPin;
private Hcsr04 _sensor;
private const int AccuracyErrorInMillimeters = 3000;
public MeasureUnit DefaultMeasureUnit = MeasureUnit.mm;
public UltrasonicDistanceSensor(int triggerPin, int echoPin, GpioController controller) : base(controller)
{
_triggerPin = triggerPin;
_echoPin = echoPin;
_sensor = new Hcsr04(controller, triggerPin, echoPin, false);
}
/// <summary>
/// Measures the distance in <see cref="DefaultMeasureUnit"/> using ultrasonic speed
/// </summary>
/// <returns>Returns distance in <see cref="DefaultMeasureUnit"/></returns>
public double Measure()
{
return Measure(1);
}
/// <summary>
/// Measures the distance in <see cref="DefaultMeasureUnit"/> using ultrasonic speed.
/// Accuracy achieved by repeated measurements and sensor error removal
/// </summary>
/// <param name="precisionRepeats">Times to repeat mesurments to calculate average between them</param>
/// <returns>Returns distance in <see cref="DefaultMeasureUnit"/></returns>
public double Measure(int precisionRepeats)
{
return CalculateAverageDistanceExcludingError(precisionRepeats) / (double)DefaultMeasureUnit;
}
private double CalculateAverageDistanceExcludingError(int precisionRepeats)
{
var measurements = CollectMeasurments(precisionRepeats);
Array.Sort(measurements);
var ethalonMeasurment = measurements[(int)Math.Floor(measurements.Length / 2d)];
var accurateMeasurements = new List<Length>(measurements.Length);
foreach(var measurement in measurements)
{
var differenceWithEthalon = measurement - ethalonMeasurment;
if(Math.Abs(differenceWithEthalon.Millimeters) <= AccuracyErrorInMillimeters)
accurateMeasurements.Add(measurement);
}
var averageResult = accurateMeasurements.Average(measurement => measurement.Millimeters);
return averageResult == 0 ? double.PositiveInfinity : averageResult;
}
private Length[] CollectMeasurments(int precisionRepeats) {
var allMeasurments = new Length[precisionRepeats];
for(var measurment = 0; measurment < precisionRepeats; measurment++)
{
allMeasurments[measurment] = ReadDistanceFromSensor();
}
return allMeasurments;
}
private Length ReadDistanceFromSensor() {
Thread.Sleep(60);
return _sensor.TryGetDistance(out Length result)
? result
: Length.FromMillimeters(0);
}
}
}