This repository has been archived by the owner on Jul 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PIDLoop.cs
109 lines (102 loc) · 3.52 KB
/
PIDLoop.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
106
107
108
109
using System;
namespace MechJim {
public class PIDLoop {
public double Kp { get; set; }
private double _Ki;
private double _loopKi;
public double Ki { get {return _Ki;} set { _Ki = value; _loopKi = value; } }
public double Kd { get; set; }
public double Input { get; set; }
public double Setpoint { get; set; }
public double Error { get; set; }
public double Output { get; set; }
public double MinOutput { get; set; }
public double MaxOutput { get; set; }
public double ErrorSum { get; set; }
public double PTerm { get; set; }
public double ITerm { get; set; }
public double DTerm { get; set; }
public bool ExtraUnwind { get; set; }
public double ChangeRate { get; set; }
public bool unWinding { get; set; }
public PIDLoop() : this(1, 0, 0) { }
public PIDLoop(double kp, double ki, double kd, double maxoutput = double.MaxValue, double minoutput = double.MinValue, bool extraUnwind = false) {
Kp = kp;
Ki = ki;
Kd = kd;
Input = 0;
Setpoint = 0;
Error = 0;
Output = 0;
MaxOutput = maxoutput;
MinOutput = minoutput;
ErrorSum = 0;
PTerm = 0;
ITerm = 0;
DTerm = 0;
ExtraUnwind = extraUnwind;
}
public double Update(double input, double setpoint, double minOutput, double maxOutput) {
MaxOutput = maxOutput;
MinOutput = minOutput;
Setpoint = setpoint;
return Update(input);
}
public double Update(double input, double setpoint, double maxOutput) {
return Update(input, setpoint, -maxOutput, maxOutput);
}
public double Update(double input)
{
double error = Setpoint - input;
double pTerm = error * Kp;
double iTerm = 0;
double dTerm = 0;
double dt = TimeWarp.fixedDeltaTime;
if (_loopKi != 0) {
if (ExtraUnwind) {
if (Math.Sign(error) != Math.Sign(ErrorSum)) {
if (!unWinding) {
_loopKi *= 2;
unWinding = true;
}
} else if (unWinding) {
_loopKi = _Ki;
unWinding = false;
}
}
iTerm = ITerm + error * dt * _loopKi;
}
ChangeRate = (input - Input) / dt;
if (Kd != 0) {
dTerm = -ChangeRate * Kd;
}
Output = pTerm + iTerm + dTerm;
if (Output > MaxOutput) {
Output = MaxOutput;
if (_loopKi != 0) {
iTerm = Output - Math.Min(pTerm + dTerm, MaxOutput);
}
}
if (Output < MinOutput) {
Output = MinOutput;
if (_loopKi != 0) {
iTerm = Output - Math.Max(pTerm + dTerm, MinOutput);
}
}
Input = input;
Error = error;
PTerm = pTerm;
ITerm = iTerm;
DTerm = dTerm;
if (_loopKi != 0)
ErrorSum = iTerm / _loopKi;
else
ErrorSum = 0;
return Output;
}
public void ResetI() {
ErrorSum = 0;
ITerm = 0;
}
}
}