added temperature_sensor and pid control

This commit is contained in:
93094049+kraemr@users.noreply.github.com committed 2025-05-09 19:18:49 +02:00
1 parent 4cf800cc3f
commit 09b7462f01
6 files changed
+77 -9

No files matched your search

-1
View File
@@ -56,7 +56,6 @@ pub trait EthercatDevice: NewEthercatDevice + Any + Send + Sync + Debug {
fn input_checked(&mut self, input: &BitSlice<u8, Lsb0>) -> Result<(), anyhow::Error> {
// validate input has correct length
let input_len = self.input_len();
println!("self: {:?} {:?}", self, input.clone());
if input.len() != input_len {
return Err(anyhow::anyhow!(
"[{}::Device::input_checked] Input length is {} and must be {} bits",
+15 -3
View File
@@ -1,6 +1,5 @@
use super::ExtruderV2;
use control_core::actors::Actor;
use ethercat_hal::io::temperature_input::TemperatureInputInput;
use std::time::{Duration, Instant};
impl Actor for ExtruderV2 {
@@ -14,17 +13,30 @@ impl Actor for ExtruderV2 {
self.temp_sensor_1.act(now_ts).await;
self.temp_sensor_2.act(now_ts).await;
self.temp_sensor_3.act(now_ts).await;
self.test.act(now_ts).await;
self.heating_relay_1.act(now_ts).await;
let now = Instant::now();
if now.duration_since(self.last_measurement_emit) > Duration::from_millis(16) {
// channel 1
self.heating_front.temperature = self.temp_sensor_1.temperature;
self.heating_front.temperature = self.temp_sensor_1.temperature; // set the temperature read from the sensor
// channel 2
self.heating_middle.temperature = self.temp_sensor_2.temperature;
// channel 3
self.heating_back.temperature = self.temp_sensor_3.temperature;
println!(
"temp {} target {}",
self.heating_front.temperature, self.heating_front.target_temperature
);
let on = self
.temperature_controller
.update(self.heating_front.temperature as f64, now_ts); // check if we need to set our relais to enabled to reach target temp
self.temperature_controller.target_temp =
self.heating_front.target_temperature as f64; // set target temperature
self.heating_relay_1.set(on); // set relay to on or off
self.emit_heating(self.heating_back.clone(), super::HeatingType::Back);
self.emit_heating(self.heating_front.clone(), super::HeatingType::Front);
self.emit_heating(self.heating_middle.clone(), super::HeatingType::Middle);
+7 -2
View File
@@ -3,6 +3,7 @@ use control_core::{
actors::{
analog_input_getter::AnalogInputGetter,
digital_output_blinker::DigitalOutputBlinker,
digital_output_setter::DigitalOutputSetter,
mitsubishi_inverter_rs485::{MitsubishiControlRequests, MitsubishiInverterRS485Actor},
temperature_input_getter::TemperatureInputGetter,
},
@@ -10,12 +11,14 @@ use control_core::{
modbus::ModbusRequest,
socketio::namespace::NamespaceCacheingLogic,
};
use ethercat_hal::io::temperature_input::TemperatureInput;
use serde::{Deserialize, Serialize};
use std::time::Instant;
use temperature_controller::TemperatureController;
pub mod act;
pub mod api;
pub mod new;
pub mod temperature_controller;
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
pub enum ExtruderV2Mode {
@@ -57,7 +60,9 @@ pub struct ExtruderV2 {
temp_sensor_3: TemperatureInputGetter,
temp_sensor_2: TemperatureInputGetter,
test: DigitalOutputBlinker,
temperature_controller: TemperatureController,
heating_relay_1: DigitalOutputSetter,
}
impl std::fmt::Display for ExtruderV2 {
+9 -3
View File
@@ -1,10 +1,13 @@
use std::time::{Duration, Instant};
use crate::machines::extruder1::temperature_controller::{self, TemperatureController};
use super::{ExtruderV2, ExtruderV2Mode, Heating, api::ExtruderV2Namespace};
use anyhow::Error;
use control_core::{
actors::{
analog_input_getter::AnalogInputGetter, digital_output_blinker::DigitalOutputBlinker,
digital_output_setter::DigitalOutputSetter,
mitsubishi_inverter_rs485::MitsubishiInverterRS485Actor,
temperature_input_getter::TemperatureInputGetter,
},
@@ -210,7 +213,7 @@ impl MachineNewTrait for ExtruderV2 {
let pressure_sensor = AnalogInputGetter::new(AnalogInput::new(el3021, EL3021Port::AI1));
let digital_out_1 = DigitalOutput::new(el2004, EL2004Port::DO1);
let temperature_controller = TemperatureController::new(0.4, 0.001, 0.001, 0.0);
let extruder: ExtruderV2 = Self {
inverter: MitsubishiInverterRS485Actor::new(SerialInterface::new(
el6021,
@@ -223,7 +226,7 @@ impl MachineNewTrait for ExtruderV2 {
heating_front: Heating {
temperature: 150.0,
heating: false,
target_temperature: 150.0,
target_temperature: 60.0,
},
heating_back: Heating {
temperature: 150.0,
@@ -243,7 +246,10 @@ impl MachineNewTrait for ExtruderV2 {
temp_sensor_1: t1_getter,
temp_sensor_2: t2_getter,
temp_sensor_3: t3_getter,
test: DigitalOutputBlinker::new(digital_out_1, Duration::from_secs(1)),
heating_relay_1: DigitalOutputSetter::new(digital_out_1),
temperature_controller,
};
Ok(extruder)
})
Whitespace-only changes.
@@ -0,0 +1,46 @@
use std::time::{Duration, Instant};
use control_core::controllers::pid::PidController;
const PWM_PERIOD: Duration = Duration::from_millis(200);
#[derive(Debug)]
pub struct TemperatureController {
pid: PidController,
pub target_temp: f64,
window_start: Instant,
}
impl TemperatureController {
pub fn new(kp: f64, ki: f64, kd: f64, target_temp: f64) -> Self {
Self {
pid: PidController::new(kp, ki, kd),
target_temp,
window_start: Instant::now(),
}
}
pub fn update(&mut self, measured_temp: f64, now: Instant) -> bool {
let error = self.target_temp - measured_temp;
let control = self.pid.update(error, now); // PID output
// println!("control {} error {}", control, error);
// Clamp PID output to 0.0 – 1.0 (as duty cycle)
let duty = control.clamp(0.0, 1.0);
// Time since window started
let elapsed = now.duration_since(self.window_start);
// Restart window if needed
if elapsed >= PWM_PERIOD {
self.window_start = now;
}
// Compare duty cycle to elapsed time
let on_time = PWM_PERIOD.mul_f64(duty);
println!("update Relais: {} duty: {}", elapsed < on_time, duty);
// Relay is ON if within duty cycle window
return elapsed < on_time;
}
}