Skip to content

Commit a19c612

Browse files
committed
add pump control + pid for pump task
1 parent 3312292 commit a19c612

File tree

6 files changed

+95
-19
lines changed

6 files changed

+95
-19
lines changed

stm32-modules/include/vacuum-module/firmware/pump_policy.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class PumpPolicy {
1818
auto enable_pump_tach(bool enable) -> bool;
1919
auto get_pump_rpm() -> float;
2020
auto sleep_ms(uint32_t ms) -> void;
21+
[[nodiscard]] auto get_time_ms() const -> uint32_t;
2122
auto enable_pump_control(bool enable) -> void;
2223

2324
private:

stm32-modules/include/vacuum-module/vacuum-module/messages.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,21 +111,25 @@ struct SetStatusBarStateMessage {
111111
};
112112

113113
// For internal driving
114-
struct GetPressureMessage {};
114+
struct PressureControlMessage {};
115115
struct PumpControlMessage {};
116116

117117
struct SetTargetPressureMessage {
118118
uint32_t id = 0;
119119
double pressure_setpoint = 0;
120120
double ramp_rate = 0;
121121
uint32_t duration_s = 0;
122+
bool start_pump = false;
122123
bool vent_after = false;
123124
};
124125

125-
struct SetTargetPWMMessage {
126+
struct SetPumpStateMessage {
126127
uint32_t id = 0;
127128
bool from_host = false;
128-
double pwm_setpoint = 0;
129+
// This is from inner pressureTask, can we use this from host?
130+
// or do we need something like pwm/duty cycle?
131+
double rpm_setpoint = 0;
132+
bool run_pump = false;
129133
};
130134

131135
using HostCommsMessage =
@@ -140,9 +144,9 @@ using SystemMessage =
140144

141145
using UIMessage = ::std::variant<std::monostate, SetStatusBarStateMessage>;
142146

143-
using PressureMessage = ::std::variant<std::monostate, GetPressureMessage,
147+
using PressureMessage = ::std::variant<std::monostate, PressureControlMessage,
144148
SetTargetPressureMessage>;
145149

146-
using PumpMessage = ::std::variant<std::monostate, PumpControlMessage, SetTargetPWMMessage>;
150+
using PumpMessage = ::std::variant<std::monostate, PumpControlMessage, SetPumpStateMessage>;
147151

148152
}; // namespace messages

stm32-modules/include/vacuum-module/vacuum-module/pressure_task.hpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ struct PressureControl {
6262
double ramp_rate = 0;
6363
uint32_t duration_s = 0;
6464
bool vent_after = false;
65+
bool start_pump = false;
6566

6667
PressureRamp rampgen;
6768
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
6869
PID pid; // Current PID loop
6970
uint32_t last_tick = 0;
70-
bool enable_pump = false;
7171
};
7272

7373
const PressureControl pressure_control = {
@@ -178,11 +178,11 @@ class PressureTask {
178178
}
179179

180180
template <PressureControlPolicy Policy>
181-
auto visit_message(const messages::GetPressureMessage& m, Policy& policy)
181+
auto visit_message(const messages::PressureControlMessage& m, Policy& policy)
182182
-> void {
183183
// Get delta time
184184
auto timestamp = policy.get_time_ms();
185-
auto delta = (timestamp - _pressure_control.last_tick) * MS_TO_SECONDS;
185+
auto delta_s = (timestamp - _pressure_control.last_tick) * MS_TO_SECONDS;
186186
_pressure_control.last_tick = timestamp;
187187

188188
// TODO: add FIR filter for abs pressure.
@@ -201,15 +201,16 @@ class PressureTask {
201201
std::get<LPSDriverType>(get_sensor(ATM_PRESSURE).driver)
202202
.get_pressure();
203203

204-
// Compute the new target pwm with ramp rate
204+
// Compute the new pwm with ramp rate
205205
double target_setpoint =
206206
_pressure_control.rampgen.update_setpoint(timestamp);
207207
auto guage_pressure = abs_a_pressure_mbar - atm_pressure_hpa;
208208
auto difference = target_setpoint - guage_pressure;
209-
auto pwm = _pressure_control.pid.compute(difference, delta);
209+
auto rpm = _pressure_control.pid.compute(difference, delta_s);
210+
// TODO: clamp the rpm here to something sensible
210211

211-
// Send new pwm to pump task
212-
auto msg = messages::SetTargetPWMMessage{.pwm_setpoint = pwm};
212+
// Send new rpm to pump task
213+
auto msg = messages::SetPumpStateMessage{.rpm_setpoint = rpm, .run_pump = true};
213214
static_cast<void>(
214215
_task_registry->send_to_address(msg, Queues::PumpAddress));
215216
}
@@ -222,14 +223,15 @@ class PressureTask {
222223
_pressure_control.ramp_rate = m.ramp_rate;
223224
_pressure_control.duration_s = m.duration_s;
224225
_pressure_control.vent_after = m.vent_after;
226+
_pressure_control.start_pump = m.start_pump;
225227

226228
// Update ramp rate generator
227229
// TODO: Do we need to stop pump when we update ramp rate?
228230
auto current_pressure = _pressure_control.current_pressure;
229231
auto timestamp = policy.get_time_ms();
230232
_pressure_control.rampgen.start_ramp(
231233
current_pressure, m.pressure_setpoint, m.ramp_rate, timestamp);
232-
// TODO: kick off pressure control here
234+
// TODO: kick off pressure control here, or in sep gcode? maybe StartPump?
233235
// 0. set target pressure, ramp rate, etc
234236
// 1. start the pressure driving task (if not started)
235237
// 1. set the pwm

stm32-modules/include/vacuum-module/vacuum-module/pump_task.hpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cstdint>
44

55
#include "core/ack_cache.hpp"
6+
#include "core/pid.hpp"
67
#include "core/queue_aggregator.hpp"
78
#include "core/version.hpp"
89
#include "firmware/pump_policy.hpp"
@@ -15,6 +16,29 @@
1516
namespace pump_task {
1617

1718
static constexpr const uint32_t CONTROL_PERIOD_MS = 20;
19+
static constexpr const double MS_TO_SECONDS = 0.001F;
20+
21+
struct PumpControl {
22+
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
23+
double target_rpm = 0.0F;
24+
double current_rpm = 0.0F;
25+
26+
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
27+
PID pid; // Current PID loop
28+
uint32_t last_tick = 0;
29+
bool enable_pump = false;
30+
bool pump_running = false;
31+
};
32+
33+
const PumpControl pump_control = {
34+
.target_rpm = 0.0f,
35+
.pid = PID{.kp = 1,
36+
.ki = 0.5,
37+
.kd = 0,
38+
.sampletime = CONTROL_PERIOD_MS * 1000,
39+
.windup_limit_high = 18000,
40+
.windup_limit_low = 0},
41+
};
1842

1943
template <typename P>
2044
concept PumpControlPolicy = requires(P p) {
@@ -95,18 +119,57 @@ class PumpTask {
95119
-> void {
96120
static_cast<void>(m);
97121
static_cast<void>(policy);
122+
123+
// Get delta time
124+
auto timestamp = policy.get_time_ms();
125+
auto delta_s = (timestamp - pump_control.last_tick) * MS_TO_SECONDS;
126+
_pump_control.last_tick = timestamp;
127+
128+
// TODO: Do we want ramp gen here for smooth interpolation?
129+
// Compute the new duty cycle
130+
auto current_rpm = policy.get_pump_rpm();
131+
auto difference = _pump_control.target_rpm - current_rpm;
132+
auto duty = _pump_control.pid.compute(difference, delta_s);
133+
134+
// set the motor duty cycle
135+
policy.set_pump_duty_cycle(duty);
98136
}
99137

100138
template <PumpControlPolicy Policy>
101-
auto visit_message(const messages::SetTargetPWMMessage& m, Policy& policy)
139+
auto visit_message(const messages::SetPumpStateMessage& m, Policy& policy)
102140
-> void {
103141
static_cast<void>(m);
104142
static_cast<void>(policy);
143+
144+
// TODO: validate incoming values
145+
_pump_control.target_rpm = m.rpm_setpoint;
146+
_pump_control.enable_pump = m.run_pump;
147+
auto timestamp = policy.get_time_ms();
148+
(void)timestamp;
149+
150+
if (!m.run_pump) {
151+
policy.enable_pump_control(false);
152+
policy.stop_pump_motor();
153+
// TODO: maybe check the rpm here and verify that the pump is off
154+
// Might want a way to ramp down when we turn off the pump.
155+
_pump_control.pump_running = false;
156+
return;
157+
}
158+
159+
// start pump if not running
160+
if (m.run_pump && !_pump_control.pump_running) {
161+
policy.enable_pump_tach(true);
162+
policy.enable_pump_control(true);
163+
policy.start_pump_motor();
164+
_pump_control.pump_running = true;
165+
}
105166
}
106167

107168
Queue& _message_queue;
108169
Aggregator* _task_registry;
109170
bool _initialized{false};
171+
172+
PumpControl _pump_control = pump_control;
110173
};
111174

112175
} // namespace pump_task

stm32-modules/vacuum-module/firmware/pressure_task/freertos_pressure_task.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static void run_hardware_task(void* param) {
4040
&last_wake_time,
4141
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
4242
pdMS_TO_TICKS(pressure_task::CONTROL_PERIOD_MS));
43-
static_cast<void>(_queue.try_send(messages::GetPressureMessage{}));
43+
static_cast<void>(_queue.try_send(messages::PressureControlMessage{}));
4444
}
4545
}
4646

stm32-modules/vacuum-module/firmware/pump_task/pump_policy.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ auto pump_policy::PumpPolicy::get_pump_rpm() -> float {
3838
return hw_get_pump_rpm();
3939
}
4040

41-
auto pump_policy::PumpPolicy::sleep_ms(uint32_t ms) -> void {
42-
vTaskDelay(pdMS_TO_TICKS(ms));
43-
}
44-
4541
auto pump_policy::PumpPolicy::enable_pump_control(bool enable) -> void {
4642
auto handle = static_cast<TaskHandle_t>(hardware_handle);
4743
if (enable) {
@@ -50,3 +46,13 @@ auto pump_policy::PumpPolicy::enable_pump_control(bool enable) -> void {
5046
vTaskSuspend(handle);
5147
}
5248
}
49+
50+
auto pump_policy::PumpPolicy::sleep_ms(uint32_t ms) -> void {
51+
vTaskDelay(pdMS_TO_TICKS(ms));
52+
}
53+
54+
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
55+
[[nodiscard]] auto pump_policy::PumpPolicy::get_time_ms() const -> uint32_t {
56+
return xTaskGetTickCount();
57+
}
58+

0 commit comments

Comments
 (0)