forked from nanoframework/nanoFramework.IoT.Device
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ServoMotor.cs
105 lines (92 loc) · 4.3 KB
/
ServoMotor.cs
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Device.Pwm;
namespace Iot.Device.ServoMotor
{
/// <summary>
/// Represents a rotary actuator or linear actuator that allows for precise control of angular or linear position.
/// </summary>
public sealed class ServoMotor : IDisposable
{
private PwmChannel _pwmChannel;
private double _maximumAngle;
private double _minimumPulseWidthMicroseconds;
private double _angleToMicroseconds;
/// <summary>
/// Initializes a new instance of the <see cref="ServoMotor"/> class.
/// </summary>
/// <param name="pwmChannel">The PWM channel used to control the servo motor.</param>
/// <param name="maximumAngle">The maximum angle the servo motor can move represented as a value between 0 and 360.</param>
/// <param name="minimumPulseWidthMicroseconds">The minimum pulse width, in microseconds, that represent an angle for 0 degrees.</param>
/// <param name="maximumPulseWidthMicroseconds">The maxnimum pulse width, in microseconds, that represent an angle for maximum angle.</param>
public ServoMotor(
PwmChannel pwmChannel,
double maximumAngle = 180,
double minimumPulseWidthMicroseconds = 1_000,
double maximumPulseWidthMicroseconds = 2_000)
{
_pwmChannel = pwmChannel;
Calibrate(maximumAngle, minimumPulseWidthMicroseconds, maximumPulseWidthMicroseconds);
}
/// <summary>
/// Sets calibration parameters.
/// </summary>
/// <param name="maximumAngle">The maximum angle the servo motor can move represented as a value between 0 and 360.</param>
/// <param name="minimumPulseWidthMicroseconds">The minimum pulse width, in microseconds, that represent an angle for 0 degrees.</param>
/// <param name="maximumPulseWidthMicroseconds">The maxnimum pulse width, in microseconds, that represent an angle for maximum angle.</param>
public void Calibrate(double maximumAngle, double minimumPulseWidthMicroseconds, double maximumPulseWidthMicroseconds)
{
if (maximumAngle < 0 || maximumAngle > 360)
{
throw new ArgumentOutOfRangeException(nameof(maximumAngle));
}
if (minimumPulseWidthMicroseconds < 0)
{
throw new ArgumentOutOfRangeException(nameof(minimumPulseWidthMicroseconds));
}
if (maximumPulseWidthMicroseconds < minimumPulseWidthMicroseconds)
{
throw new ArgumentOutOfRangeException(nameof(maximumPulseWidthMicroseconds));
}
_maximumAngle = maximumAngle;
_minimumPulseWidthMicroseconds = minimumPulseWidthMicroseconds;
_angleToMicroseconds = (maximumPulseWidthMicroseconds - minimumPulseWidthMicroseconds) / maximumAngle;
}
/// <summary>
/// Starts the servo motor.
/// </summary>
public void Start() => _pwmChannel.Start();
/// <summary>
/// Stops the servo motor.
/// </summary>
public void Stop() => _pwmChannel.Stop();
/// <summary>
/// Writes an angle to the servo motor.
/// </summary>
/// <param name="angle">The angle to write to the servo motor.</param>
public void WriteAngle(double angle)
{
if (angle < 0 || angle > _maximumAngle)
{
throw new ArgumentOutOfRangeException(nameof(angle));
}
WritePulseWidth((int)((_angleToMicroseconds * angle) + _minimumPulseWidthMicroseconds));
}
/// <summary>
/// Writes a pulse width to the servo motor.
/// </summary>
/// <param name="microseconds">The pulse width, in microseconds, to write to the servo motor.</param>
public void WritePulseWidth(int microseconds)
{
double dutyCycle = (double)microseconds / 1_000_000 * _pwmChannel.Frequency; // Convert to seconds 1st.
_pwmChannel.DutyCycle = dutyCycle;
}
/// <inheritdoc/>
public void Dispose()
{
_pwmChannel?.Dispose();
_pwmChannel = null;
}
}
}