-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpid_class.py
86 lines (74 loc) · 2.79 KB
/
pid_class.py
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
import math
import os
class PID:
def __init__(self):
self.file_name = "PID.txt"
self.kP = 160
self.kI = 0
self.kD = 3
self.max_I_val = 25.0
self.P = 0
self.I = 0
self.D = 0
self.setpoint = math.radians(0)
self.process_variable = 0
self.dt = 0
self.last_error = 0
self.error_val = 0
self.y = 0
self.need_to_calc_y = True #prevents having to calculate the y_val more often than needed
def update_constants(self):
print(os.listdir())
with open(self.file_name, 'r') as infile:
kP, kI, kD, max_I = (float(infile.readline()) for i in range(4))
if kP != self.kP or kI != self.kI or kD != self.kD or max_I != self.max_I_val:
print("New constants fixed. resetting I-val.")
self.I = 0
self.kP = kP
self.kI = kI
self.kD = kD
self.max_I_val = max_I
def set_setpoint(self, new_setpoint):
""" changes the setpoint to a new value.
new_setpoint: the new setpoint, in radians """
# TODO: reset other values?
print(f"old setpoint: {self.setpoint}\tnew: {new_setpoint}")
self.setpoint = new_setpoint
def set_process_variable(self, measurement, dt):
""" measurement: the latest measured value
dt: the time between this measurement and the last one """
self.need_to_calc_y = True
self.process_variable = measurement
self.dt = dt
def calculate_error_val(self):
self.last_error = self.error_val
self.error_val = self.setpoint - self.process_variable
def calc_deriviate(self):
self.D = (self.error_val - self.last_error) / self.dt
def calc_proportional(self):
self.P = self.error_val
def calc_integral(self):
# TODO: add min and max-val
# Resets the integral term when passing the top position
#if (self.last_error < 0 < self.error_val) or \
# (self.last_error > 0 > self.error_val):
# self.I = 0
self.I += self.error_val
if self.I > self.max_I_val:
self.I = self.max_I_val
elif self.I < -self.max_I_val:
self.I = -self.max_I_val
def get_control_variable(self):
if not self.need_to_calc_y:
return self.y
self.calculate_error_val()
self.calc_proportional()
self.calc_integral()
self.calc_deriviate()
# TODO: try with squared P value
self.y = self.P * self.kP + self.I * self.kI + self.D * self.kD
self.need_to_calc_y = False
return self.y
# How to use:
# Set control variable val + time between measurements
# use get_control_variable to get output value