-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpid_balance.py
108 lines (87 loc) · 2.95 KB
/
pid_balance.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import time
from mpu9250_jmdev.registers import *
from mpu9250_jmdev.mpu_9250 import MPU9250
import time
import board
from adafruit_motorkit import MotorKit
import numpy as np
from scipy.signal import butter, lfilter
from pidcontroller import PIDController
def clamp(n, min_value, max_value):
return max(min_value, min(n, max_value))
# Function to create a Butterworth low-pass filter
def butter_lowpass(cutoff, fs, order=5):
nyquist = 0.5 * fs
normal_cutoff = cutoff / nyquist
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
# Parameters
cutoff_frequency = 10.0 # cutoff frequency in Hz
sampling_rate = 100.0 # sampling rate in Hz
filter_order = 4 # order of the filter
buffer_size = 10 # size of the data buffer
# Initialize filter coefficients
b, a = butter_lowpass(cutoff_frequency, sampling_rate, filter_order)
# Initialize buffer to store the gyro data
gyro_buffer = np.zeros(buffer_size)
def update_gyro_buffer(new_reading):
"""
Updates the gyro buffer with a new reading, applying the Butterworth filter
in real-time.
"""
# Shift the buffer to make room for the new reading at the end
global gyro_buffer
gyro_buffer = np.roll(gyro_buffer, -1)
gyro_buffer[-1] = new_reading
# Apply the filter to the current buffer
filtered_data = lfilter(b, a, gyro_buffer)
# Return the latest filtered value
return filtered_data[-1]
# Create an MPU9250 instance
mpu = MPU9250(
address_ak=AK8963_ADDRESS,
address_mpu_master=MPU9050_ADDRESS_68, # In case the MPU9250 is connected to another I2C device
address_mpu_slave=None,
bus=1,
gfs=GFS_1000,
afs=AFS_8G,
mfs=AK8963_BIT_16,
mode=AK8963_MODE_C100HZ)
# Configure the MPU9250
mpu.configure()
kit = MotorKit(i2c=board.I2C())
min_power = 0.153
p = .45
setpoint = 0.03
deadband = 0.02
while True:
# Read the accelerometer, gyroscope, and magnetometer values
accel_data = mpu.readAccelerometerMaster()
gyro_data = mpu.readGyroscopeMaster()
mag_data = mpu.readMagnetometerMaster()
# Print the sensor values
#print("Accelerometer:", accel_data)
#print(accel_data[1])
#print("Gyroscope:", gyro_data)
#print("Magnetometer:", mag_data)
# Wait for 1 second before the next reading
#time.sleep(.01)
new_gyro_reading = mpu.readAccelerometerMaster()[1]
# Get the filtered reading
filtered_reading = update_gyro_buffer(new_gyro_reading)
error = filtered_reading - setpoint
PID = PIDController(0.5,0,0.05)
PID.setTarget(setpoint)
PIDx = PID.step(filtered_reading)
#print(error)
if (abs(PIDx) > deadband):
if (PIDx > 0):
output = float(clamp(p*error + min_power,-1,1))
else:
output = float(clamp(p*error - min_power,-1,1))
else:
output = 0
print([filtered_reading,PIDx,output])
kit.motor1.throttle = -1 * output
kit.motor2.throttle = output
time.sleep(0.002)