pid-balancer/control_functions.py

121 lines
3.5 KiB
Python
Raw Normal View History

from OpenGL.images import returnFormat
2024-12-25 16:52:07 +01:00
from adafruit_hcsr04 import HCSR04 as hcsr04
import board
import data_transfer_functions as dt
from adafruit_servokit import ServoKit
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt
import statistics as st
2024-12-25 16:52:07 +01:00
# Variables to control sensor
TRIGGER_PIN = board.D4
ECHO_PIN = board.D17
TIMEOUT = 0.1
MIN_DISTANCE = 4
MAX_DISTANCE = 40
# Variables to control logging.
LOG = True
SCREEN = True
DEBUG = False
2024-12-25 16:52:07 +01:00
# PID measurements
time = 0
integral = 0
time_prev = -1e-6
e_prev = 0
# PID values
P_value = 2
I_value = 0
D_value = 0
sample_array = []
2024-12-25 16:52:07 +01:00
def initial():
...
def read_distance_sensor(fixed_file_stamp):
with (hcsr04(trigger_pin=TRIGGER_PIN, echo_pin=ECHO_PIN, timeout=TIMEOUT) as sonar):
samples = 0
max_samples = 10
timestamp_last = 0.0
timestamp_first = 0.0
while samples != max_samples:
2024-12-25 16:52:07 +01:00
try:
distance = sonar.distance
if MIN_DISTANCE < distance < MAX_DISTANCE:
dt.log_data(fixed_file_stamp,"sensor", distance, None) if LOG else None
print("Distance: ", distance) if SCREEN else None
sample_array.append(distance)
if samples == 0: timestamp_first, _ = dt.timestamper()
if samples == max_samples - 1: timestamp_last, _ = dt.timestamper()
timestamp_first_float = float(timestamp_first)
timestamp_last_float = float(timestamp_last)
samples = samples + 1
median_distance = st.median(sample_array)
mean_timestamp = st.mean([timestamp_first_float, timestamp_last_float])
print(median_distance) if LOG else None
print(mean_timestamp)
2024-12-25 16:52:07 +01:00
else:
dt.log_data(fixed_file_stamp,"sensor", distance,"Ignored") if LOG and DEBUG else None
2024-12-25 16:52:07 +01:00
print("Distance: ", distance) if SCREEN else None
except RuntimeError:
dt.log_data(fixed_file_stamp, "sensor", 999.999, "Timeout") if LOG and DEBUG else None
2024-12-25 16:52:07 +01:00
print("Timeout") if SCREEN else None
return median_distance, mean_timestamp
2024-12-25 16:52:07 +01:00
def read_setpoint():
...
def calculate_velocity():
...
2024-12-25 16:52:07 +01:00
def PID_calculations(setpoint):
2024-12-25 16:52:07 +01:00
global I_result, previous_time, previous_error
2024-12-25 16:52:07 +01:00
offset_value = 320
measurement, current_time = read_distance_sensor
2024-12-25 16:52:07 +01:00
error = setpoint - measurement
if previous_time is None:
previous_error: float = 0.0
previous_time: float = current_time
I_result: float = 0.0
error_sum: float = error * 0.008 # sensor sampling number approximation.
error_sum: float = error_sum + (error * (current_time - previous_time))
P_result: float = P_value * error
I_result: float = I_value * error_sum
D_result: float = D_value * ((error - previous_error) / (current_time - previous_time))
PID_result: float = offset_value + P_result + I_result + D_result
previous_error: float = error
previous_time: float = current_time
2024-12-25 16:52:07 +01:00
return PID_result
def calculate_new_servo_pos():
...
def send_data_to_servo():
kit = ServoKit(channels=16)
kit.servo[0].set_pulse_width_range(500, 2500)
kit.servo[0].angle = 180