omnitiles/control/
linear_controller.rs1use crate::control::Pid;
7use crate::drivers::ActuonixLinear;
8use stm32f7xx_hal::prelude::*;
9
10#[derive(Copy, Clone, Debug, PartialEq)]
11pub enum LinearMode {
12 PositionControl,
13 Disabled,
14}
15
16pub struct LinearController<
18 const CS_P: char,
19 const CS_N: u8,
20 const SLP_P: char,
21 const SLP_N: u8,
22 const DIS_P: char,
23 const DIS_N: u8,
24 Pwm1,
25 Pwm2,
26 ReadPos,
27> {
28 pub actuator: ActuonixLinear<CS_P, CS_N, SLP_P, SLP_N, DIS_P, DIS_N, Pwm1, Pwm2, ReadPos>,
29 pub pid: Pid,
30 pub mode: LinearMode,
31
32 pub target_position_mm: f32,
33 pub min_position_mm: f32,
34 pub max_position_mm: f32,
35 pub on_target_tolerance_mm: f32,
36}
37
38impl<
39 const CS_P: char,
40 const CS_N: u8,
41 const SLP_P: char,
42 const SLP_N: u8,
43 const DIS_P: char,
44 const DIS_N: u8,
45 Pwm1,
46 Pwm2,
47 ReadPos,
48 > LinearController<CS_P, CS_N, SLP_P, SLP_N, DIS_P, DIS_N, Pwm1, Pwm2, ReadPos>
49where
50 Pwm1: _embedded_hal_PwmPin<Duty = u16>,
51 Pwm2: _embedded_hal_PwmPin<Duty = u16>,
52 ReadPos: FnMut() -> u16,
53{
54 pub fn new(
56 actuator: ActuonixLinear<CS_P, CS_N, SLP_P, SLP_N, DIS_P, DIS_N, Pwm1, Pwm2, ReadPos>,
57 pid: Pid,
58 min_position_mm: f32,
59 max_position_mm: f32,
60 on_target_tolerance_mm: f32,
61 ) -> Self {
62 Self {
63 actuator,
64 pid,
65 mode: LinearMode::PositionControl,
66 target_position_mm: 0.0,
67 min_position_mm,
68 max_position_mm,
69 on_target_tolerance_mm,
70 }
71 }
72
73 pub fn set_target_position_mm(&mut self, mm: f32) {
75 self.target_position_mm = mm.clamp(self.min_position_mm, self.max_position_mm);
76 self.pid.reset();
77 }
78
79 pub fn step(&mut self, dt: f32) {
81 self.actuator.enforce_limits();
82
83 match self.mode {
84 LinearMode::Disabled => return,
85
86 LinearMode::PositionControl => {
87 let position_mm = self.actuator.position_mm();
88 let target = self
89 .target_position_mm
90 .clamp(self.min_position_mm, self.max_position_mm);
91 let error = target - position_mm;
92
93 if error.abs() <= self.on_target_tolerance_mm {
94 self.actuator.brake();
95 return;
96 }
97
98 let output = self.pid.update(target, position_mm, dt);
99 self.actuator.set_speed(output);
100 }
101 }
102 }
103}