diff --git a/control-core/src/machines/manager_iter.rs b/control-core/src/machines/manager_iter.rs
index 798d379cf..6d0ec4092 100644
--- a/control-core/src/machines/manager_iter.rs
+++ b/control-core/src/machines/manager_iter.rs
@@ -71,7 +71,7 @@ impl<'a> Iterator for MachineManagerIterator<'a> {
impl MachineManager {
// Returns an iterator over all machines (both ethercat and serial)
- pub fn iter(&self) -> MachineManagerIterator {
+ pub fn iter(&'_ self) -> MachineManagerIterator<'_> {
MachineManagerIterator {
iter: MachineManagerIter::EthercatMachines {
iter: self.ethercat_machines.iter(),
diff --git a/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx b/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx
index eb281dccd..8857ced98 100644
--- a/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx
+++ b/electron/src/machines/extruder/extruder2/Extruder2ControlPage.tsx
@@ -29,7 +29,6 @@ export function Extruder2ControlPage() {
pressure,
motorScrewRpm,
- motorPower,
combinedPower,
setExtruderMode,
@@ -119,9 +118,11 @@ export function Extruder2ControlPage() {
Inverter is overloaded! Please check the extruder and reduce load
if necessary.
- ) : state?.inverter_status_state.fault_occurence == true ? (
+ ) : state?.inverter_status_state.fault_occurence == true &&
+ state?.inverter_status_state.fault ? (
- Inverter encountered an error!! Press the restart button in Config
+ Inverter stopped:
+ {state?.inverter_status_state.fault?.fault_description}
) : state?.inverter_status_state.running == true &&
state.inverter_status_state.fault_occurence == false ? (
diff --git a/electron/src/machines/extruder/extruder2/extruder2Namespace.ts b/electron/src/machines/extruder/extruder2/extruder2Namespace.ts
index 0b4e81b20..4315e3d81 100644
--- a/electron/src/machines/extruder/extruder2/extruder2Namespace.ts
+++ b/electron/src/machines/extruder/extruder2/extruder2Namespace.ts
@@ -100,6 +100,15 @@ export const heatingStatesSchema = z.object({
back: heatingStateSchema,
middle: heatingStateSchema,
});
+// pub fault_code: FaultCode,
+// pub fault_description: String,
+// pub ts: Instant,
+
+export const faultStateSchema = z.object({
+ fault_code: z.number(),
+ fault_description: z.string(),
+ time_stamp: z.number(),
+});
/**
* Extruder settings state schema
@@ -113,6 +122,7 @@ export const extruderSettingsStateSchema = z.object({
* Inverter status state schema
*/
export const inverterStatusStateSchema = z.object({
+ fault: faultStateSchema.nullable(),
running: z.boolean(),
forward_running: z.boolean(),
reverse_running: z.boolean(),
diff --git a/server/src/machines/extruder1/api.rs b/server/src/machines/extruder1/api.rs
index 102a0b159..352332d52 100644
--- a/server/src/machines/extruder1/api.rs
+++ b/server/src/machines/extruder1/api.rs
@@ -75,7 +75,7 @@ impl LiveValuesEvent {
}
}
-#[derive(Serialize, Debug, Clone, PartialEq, BuildEvent)]
+#[derive(Serialize, Debug, Clone, BuildEvent)]
pub struct StateEvent {
pub is_default_state: bool,
/// rotation state
@@ -144,8 +144,16 @@ pub struct ExtruderSettingsState {
pub pressure_limit_enabled: bool,
}
-#[derive(Serialize, Debug, Clone, PartialEq)]
+#[derive(Serialize, Debug, Clone)]
+pub struct FaultState {
+ pub fault_code: u16,
+ pub fault_description: String,
+ pub time_stamp: u64,
+}
+
+#[derive(Serialize, Debug, Clone)]
pub struct InverterStatusState {
+ pub fault: Option,
/// RUN (Inverter running)
pub running: bool,
/// Forward running motor spins forward
diff --git a/server/src/machines/extruder1/mitsubishi_cs80/mod.rs b/server/src/machines/extruder1/mitsubishi_cs80/mod.rs
index eb22ee53b..0b353d19e 100644
--- a/server/src/machines/extruder1/mitsubishi_cs80/mod.rs
+++ b/server/src/machines/extruder1/mitsubishi_cs80/mod.rs
@@ -4,7 +4,7 @@ use control_core::modbus::{
modbus_serial_interface::ModbusSerialInterface,
};
use ethercat_hal::io::serial_interface::SerialInterface;
-use std::time::{Duration, Instant};
+use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use uom::si::{
electric_current::centiampere,
electric_potential::centivolt,
@@ -36,6 +36,8 @@ enum MitsubishiCS80Register {
//RunningFrequencyEEPROM,
/// Register 40201
MotorStatus,
+ /// Register 40501
+ FaultHistory,
}
impl MitsubishiCS80Register {
@@ -45,6 +47,7 @@ impl MitsubishiCS80Register {
Self::InverterStatusAndControl => 0x8,
Self::RunningFrequencyRAM => 0x0d,
Self::MotorStatus => 0x00C8, // a0x00C8 = frequency , 0x00C9 = current ,0x00C10 = voltage
+ Self::FaultHistory => 0x01F4,
}
}
@@ -54,35 +57,39 @@ impl MitsubishiCS80Register {
}
/// These Requests Serve as Templates for controlling the inverter
+/// i added None = 0 ... and so on so its clearer how the impl From works
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub enum MitsubishiCS80Requests {
- None,
+ None = 0,
/// Register 40002, Reset/Restart the Inverter
- ResetInverter,
+ ResetInverter = 1,
/// Register 40004, Clear ALL parameters
- ClearAllParameters,
+ ClearAllParameters = 2,
/// Register 40006, Clear a non communication parameter
- ClearNonCommunicationParameter,
+ ClearNonCommunicationParameter = 3,
/// Register 40007, Clear all Non Communication related Parameters
- ClearNonCommunicationParameters,
+ ClearNonCommunicationParameters = 4,
/// Register 40009, Read Inverter Status
- ReadInverterStatus,
+ ReadInverterStatus = 5,
/// Register 40009, Stops the Motor
- StopMotor,
+ StopMotor = 6,
/// Register 40009, Starts the Motor in Forward Rotation
- StartForwardRotation,
+ StartForwardRotation = 7,
/// Register 40009, Starts the Motor in Reverse Rotation
- StartReverseRotation,
+ StartReverseRotation = 8,
/// Register 40014, Read the current frequency the motor runs at (RAM)
- ReadRunningFrequency,
+ ReadRunningFrequency = 9,
/// Register 40014, Write the frequency
- WriteRunningFrequency,
+ WriteRunningFrequency = 10,
/// Read Register 40201, 40202 and 40203 frequency,current and voltage
- ReadMotorStatus,
+ ReadMotorStatus = 11,
/// Write "Arbitrary" Parameters
- WriteParameter,
+ WriteParameter = 12,
+ /// Read Last 3 Inverter Faults (including the current one)
+ ReadFaults = 13,
}
+/// None = 0, ResetInverter = 1 ... like its defined in the enum
impl From for u32 {
fn from(request: MitsubishiCS80Requests) -> Self {
request as u32
@@ -107,6 +114,7 @@ impl TryFrom for MitsubishiCS80Requests {
10 => Ok(Self::WriteRunningFrequency),
11 => Ok(Self::ReadMotorStatus),
12 => Ok(Self::WriteParameter),
+ 13 => Ok(Self::ReadFaults),
_ => Err(()),
}
}
@@ -244,6 +252,19 @@ impl From for MitsubishiCS80Request {
RequestType::ReadWrite,
u16::MAX,
),
+ MitsubishiCS80Requests::ReadFaults => {
+ let reg_bytes = MitsubishiCS80Register::FaultHistory.address_be_bytes();
+ Self::new(
+ ModbusRequest {
+ slave_id: 1,
+ function_code: ModbusFunctionCode::ReadHoldingRegister,
+ data: vec![reg_bytes[0], reg_bytes[1], 0x0, 0x3], // read 3 registers
+ },
+ request,
+ RequestType::OperationCommand,
+ u16::MAX, // MAX because we want it to be sent asap when it is added to the "queue"
+ )
+ }
// For unimplemented variants, return a default request
_ => Self::new(
@@ -281,6 +302,165 @@ pub struct MotorStatus {
pub voltage: ElectricPotential,
}
+#[derive(Debug, Clone)]
+pub enum FaultCode {
+ ExcessivePressure = 0x9, // This is a custom FaultCode for our Pressure limit
+ OvercurrentTripAcceleration = 0x10,
+ OvercurrentTripConstSpeed = 0x11,
+ OvercurrentTripDeceleration = 0x12,
+ RegenerativeOvervoltageTripAcceleration = 0x20,
+ RegenerativeOvervoltageTripConstSpeed = 0x21,
+ RegenerativeOvervoltageTripDeceleration = 0x22,
+ InverterOverloadTrip = 0x30, // electronic thermal O/L
+ MotorOverloadTrip = 0x31, // electronic thermal O/L, not really sure what the difference is ...
+ HeatsinkOverheat = 0x40,
+ Undervoltage = 0x51,
+ InputPhaseLoss = 0x52,
+ StallPreventionStop = 0x60,
+ OutputSideEarthFaulOverCurrent = 0x80,
+ OutputPhaseLoss = 0x81,
+ ExternalThermalRelayOperation = 0x90,
+ ParamStorageFault1 = 0xb0,
+ ParamStorageFault2 = 0xb3,
+ ParamUnitDisconnect = 0xb1,
+ RetryCountExcess = 0xb2,
+ CPUFAULT1 = 0xc0,
+ CPUFAULT2 = 0xf5,
+ AbnormalOutputCurrentDetection = 0xc4,
+ InrushCurrentLimitCircuitFault = 0xc5,
+ FourMilliAmpereInputFault = 0xe4,
+ InverterOutputFault = 0xfa,
+}
+
+impl From for u16 {
+ fn from(fault: FaultCode) -> Self {
+ fault as u16
+ }
+}
+
+impl TryFrom for FaultCode {
+ type Error = anyhow::Error;
+
+ fn try_from(value: u16) -> Result {
+ match value {
+ 0x9 => Ok(FaultCode::ExcessivePressure),
+ 0x10 => Ok(FaultCode::OvercurrentTripAcceleration),
+ 0x11 => Ok(FaultCode::OvercurrentTripConstSpeed),
+ 0x12 => Ok(FaultCode::OvercurrentTripDeceleration),
+ 0x20 => Ok(FaultCode::RegenerativeOvervoltageTripAcceleration),
+ 0x21 => Ok(FaultCode::RegenerativeOvervoltageTripConstSpeed),
+ 0x22 => Ok(FaultCode::RegenerativeOvervoltageTripDeceleration),
+ 0x30 => Ok(FaultCode::InverterOverloadTrip),
+ 0x31 => Ok(FaultCode::MotorOverloadTrip),
+ 0x40 => Ok(FaultCode::HeatsinkOverheat),
+ 0x51 => Ok(FaultCode::Undervoltage),
+ 0x52 => Ok(FaultCode::InputPhaseLoss),
+ 0x60 => Ok(FaultCode::StallPreventionStop),
+ 0x80 => Ok(FaultCode::OutputSideEarthFaulOverCurrent),
+ 0x81 => Ok(FaultCode::OutputPhaseLoss),
+ 0x90 => Ok(FaultCode::ExternalThermalRelayOperation),
+ 0xb0 => Ok(FaultCode::ParamStorageFault1),
+ 0xb1 => Ok(FaultCode::ParamUnitDisconnect),
+ 0xb2 => Ok(FaultCode::RetryCountExcess),
+ 0xb3 => Ok(FaultCode::ParamStorageFault2),
+ 0xc0 => Ok(FaultCode::CPUFAULT1),
+ 0xc4 => Ok(FaultCode::AbnormalOutputCurrentDetection),
+ 0xc5 => Ok(FaultCode::InrushCurrentLimitCircuitFault),
+ 0xe4 => Ok(FaultCode::FourMilliAmpereInputFault),
+ 0xf5 => Ok(FaultCode::CPUFAULT2),
+ 0xfa => Ok(FaultCode::InverterOutputFault),
+ _ => Err(anyhow::anyhow!(
+ "FAULTCODE IS UNKNOWN! Could indicate a defect"
+ )),
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Fault {
+ pub fault_code: FaultCode,
+ pub fault_description: String,
+ pub ts: u64,
+}
+
+impl FaultCode {
+ fn description(&self) -> String {
+ match self {
+ FaultCode::ExcessivePressure => {
+ "Pressure exceeds limit, try more heat or less rpm".to_owned()
+ }
+ FaultCode::OvercurrentTripAcceleration => {
+ "Overcurrent trip during acceleration".to_owned()
+ }
+ FaultCode::OvercurrentTripConstSpeed => {
+ "Overcurrent trip during constant speed".to_owned()
+ }
+ FaultCode::OvercurrentTripDeceleration => {
+ "Overcurrent trip during deceleration or stop".to_owned()
+ }
+ FaultCode::RegenerativeOvervoltageTripAcceleration => {
+ "Regenerative overvoltage trip during acceleration".to_owned()
+ }
+ FaultCode::RegenerativeOvervoltageTripConstSpeed => {
+ "Regenerative overvoltage trip during constant speed".to_owned()
+ }
+ FaultCode::RegenerativeOvervoltageTripDeceleration => {
+ "Regenerative overvoltage trip during deceleration or stop".to_owned()
+ }
+ FaultCode::InverterOverloadTrip => {
+ "Inverter overload trip (electronic thermal O/L)".to_owned()
+ }
+ FaultCode::MotorOverloadTrip => {
+ "Motor overload trip (electronic thermal O/L)".to_owned()
+ }
+ FaultCode::HeatsinkOverheat => "Heatsink overheat".to_owned(),
+ FaultCode::Undervoltage => "Undervoltage".to_owned(),
+ FaultCode::InputPhaseLoss => "Input phase loss".to_owned(),
+ FaultCode::StallPreventionStop => "Stall prevention stop".to_owned(),
+ FaultCode::OutputSideEarthFaulOverCurrent => {
+ "Output side earth (ground) fault overcurrent".to_owned()
+ }
+ FaultCode::OutputPhaseLoss => "Output phase loss".to_owned(),
+ FaultCode::ExternalThermalRelayOperation => {
+ "External thermal relay operation".to_owned()
+ }
+ FaultCode::ParamStorageFault1 => "Parameter storage device fault".to_owned(),
+ FaultCode::ParamStorageFault2 => "Parameter storage device fault".to_owned(),
+ FaultCode::ParamUnitDisconnect => "PU disconnection".to_owned(),
+ FaultCode::RetryCountExcess => "Retry count excess".to_owned(),
+ FaultCode::CPUFAULT1 => "CPU fault".to_owned(),
+ FaultCode::CPUFAULT2 => "CPU fault".to_owned(),
+ FaultCode::AbnormalOutputCurrentDetection => {
+ "Abnormal output current detection".to_owned()
+ }
+ FaultCode::InrushCurrentLimitCircuitFault => {
+ "Inrush current limit circuit fault".to_owned()
+ }
+ FaultCode::FourMilliAmpereInputFault => "4 mA input fault".to_owned(),
+ FaultCode::InverterOutputFault => "Inverter output fault".to_owned(),
+ }
+ }
+}
+
+pub fn build_fault(fault_code: u16) -> Option {
+ let fault_code: Result = fault_code.try_into();
+ let fault_code = match fault_code {
+ Ok(fault_code) => fault_code,
+ Err(_) => return None,
+ };
+ let fault_description = fault_code.description();
+ let fault = Fault {
+ fault_code,
+ fault_description,
+ ts: SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_millis() as u64,
+ };
+
+ return Some(fault);
+}
+
#[derive(Debug)]
pub struct MitsubishiCS80 {
// Communication
@@ -288,6 +468,7 @@ pub struct MitsubishiCS80 {
pub motor_status: MotorStatus,
pub modbus_serial_interface: ModbusSerialInterface,
pub last_ts: Instant,
+ pub last_fault: Option,
}
#[derive(Debug, Clone, Copy)]
@@ -347,6 +528,7 @@ impl MitsubishiCS80 {
last_ts: Instant::now(),
motor_status: MotorStatus::default(),
status: MitsubishiCS80Status::default(),
+ last_fault: None,
}
}
@@ -379,21 +561,51 @@ impl MitsubishiCS80 {
};
let bits: &BitSlice = BitSlice::<_, Lsb0>::from_slice(&status_bytes);
- if bits.len() >= 16 {
- self.status = MitsubishiCS80Status {
- fault_occurence: bits[7],
- running: bits[8],
- forward_running: bits[9],
- reverse_running: bits[10],
- su: bits[11],
- ol: bits[12],
- no_function: bits[13],
- fu: bits[14],
- abc_: bits[15],
- };
+ if bits.len() < 16 {
+ return;
+ }
+
+ self.status = MitsubishiCS80Status {
+ fault_occurence: bits[7],
+ running: bits[8],
+ forward_running: bits[9],
+ reverse_running: bits[10],
+ su: bits[11],
+ ol: bits[12],
+ no_function: bits[13],
+ fu: bits[14],
+ abc_: bits[15],
+ };
+
+ if self.status.fault_occurence {
+ // add request to check the specific fault
+ self.add_request(MitsubishiCS80Requests::ReadFaults.into());
}
}
+ fn handle_read_fault(&mut self, resp: &ModbusResponse) {
+ if resp.data[0] % 2 == 1 {
+ tracing::error!(
+ "[{}::handle_read_fault] invalid fault data received",
+ module_path!()
+ );
+
+ // if data length is odd, dont continue
+ return;
+ }
+
+ let fault_code = u16::from_be_bytes([resp.data[1], resp.data[2]]);
+ let fault = build_fault(fault_code);
+
+ if !fault.is_none() {
+ tracing::info!(
+ "inverter fault occured: {}",
+ &fault.clone().unwrap().fault_description,
+ );
+ }
+ self.last_fault = fault;
+ }
+
fn handle_response(&mut self, control_request_type: u32) {
let response_type = match MitsubishiCS80Requests::try_from(control_request_type) {
Ok(request_type) => request_type,
@@ -406,11 +618,11 @@ impl MitsubishiCS80 {
match response_type {
MitsubishiCS80Requests::ReadInverterStatus => {
- self.handle_read_inverter_status(&response);
- }
- MitsubishiCS80Requests::ReadMotorStatus => {
- self.handle_motor_status(&response);
+ self.handle_read_inverter_status(&response)
}
+ MitsubishiCS80Requests::ReadMotorStatus => self.handle_motor_status(&response),
+ MitsubishiCS80Requests::ReadFaults => self.handle_read_fault(&response),
+
// Other request types don't need response handling
_ => {}
}
@@ -474,8 +686,10 @@ impl MitsubishiCS80 {
return;
}
- self.add_request(MitsubishiCS80Requests::ReadInverterStatus.into());
- self.add_request(MitsubishiCS80Requests::ReadMotorStatus.into());
+ // self.add_request(MitsubishiCS80Requests::ReadInverterStatus.into());
+ // self.add_request(MitsubishiCS80Requests::ReadMotorStatus.into());
+ self.add_request(MitsubishiCS80Requests::ReadFaults.into());
+
self.modbus_serial_interface.act(now).await;
self.handle_response(self.modbus_serial_interface.last_message_id);
}
diff --git a/server/src/machines/extruder1/mod.rs b/server/src/machines/extruder1/mod.rs
index b271d456e..8567913ec 100644
--- a/server/src/machines/extruder1/mod.rs
+++ b/server/src/machines/extruder1/mod.rs
@@ -1,3 +1,4 @@
+use crate::machines::extruder1::api::FaultState;
use crate::machines::{MACHINE_EXTRUDER_V1, VENDOR_QITECH};
use api::{
ExtruderSettingsState, ExtruderV2Events, ExtruderV2Namespace, HeatingState, HeatingStates,
@@ -20,6 +21,7 @@ use uom::si::{
pressure::bar,
thermodynamic_temperature::degree_celsius,
};
+
pub mod act;
pub mod api;
pub mod mitsubishi_cs80;
@@ -79,6 +81,15 @@ pub struct ExtruderV2 {
impl ExtruderV2 {
pub fn build_state_event(&mut self) -> StateEvent {
+ let fault = match self.screw_speed_controller.get_last_fault() {
+ Some(fault) => Some(FaultState {
+ fault_code: fault.fault_code.into(),
+ fault_description: fault.fault_description,
+ time_stamp: fault.ts,
+ }),
+ None => None,
+ };
+
StateEvent {
is_default_state: !std::mem::replace(&mut self.emitted_default_state, true),
rotation_state: RotationState {
@@ -156,6 +167,7 @@ impl ExtruderV2 {
output_frequency_detection: self.screw_speed_controller.inverter.status.fu,
abc_fault: self.screw_speed_controller.inverter.status.abc_,
fault_occurence: self.screw_speed_controller.inverter.status.fault_occurence,
+ fault: fault,
},
pid_settings: PidSettingsStates {
temperature: PidSettings {
@@ -252,10 +264,10 @@ impl ExtruderV2 {
}
pub fn emit_state(&mut self) {
- let state = self.build_state_event();
- self.last_state_event = Some(state.clone());
- let event = state.build();
- self.namespace.emit(ExtruderV2Events::State(event));
+ let event = self.build_state_event();
+ self.namespace
+ .emit(ExtruderV2Events::State(event.clone().build()));
+ self.last_state_event = Some(event);
}
// Extruder Settings Api Impl
diff --git a/server/src/machines/extruder1/screw_speed_controller.rs b/server/src/machines/extruder1/screw_speed_controller.rs
index 9728873d1..a9f436f96 100644
--- a/server/src/machines/extruder1/screw_speed_controller.rs
+++ b/server/src/machines/extruder1/screw_speed_controller.rs
@@ -15,6 +15,8 @@ use uom::si::{
pressure::bar,
};
+use crate::machines::extruder1::mitsubishi_cs80::Fault;
+
use super::mitsubishi_cs80::{MitsubishiCS80, MotorStatus};
#[derive(Debug)]
@@ -23,15 +25,21 @@ pub struct ScrewSpeedController {
pub target_pressure: Pressure,
pub target_rpm: AngularVelocity,
pub inverter: MitsubishiCS80,
+
pressure_sensor: AnalogInput,
last_update: Instant,
+
uses_rpm: bool,
forward_rotation: bool,
+
transmission: FixedTransmission,
frequency: Frequency,
+
maximum_frequency: Frequency,
minimum_frequency: Frequency,
+
motor_on: bool,
+
nozzle_pressure_limit: Pressure,
nozzle_pressure_limit_enabled: bool,
}
@@ -64,6 +72,10 @@ impl ScrewSpeedController {
}
}
+ pub fn get_last_fault(&mut self) -> Option {
+ return self.inverter.last_fault.clone();
+ }
+
pub fn get_motor_enabled(&mut self) -> bool {
return self.motor_on;
}
@@ -200,18 +212,18 @@ impl ScrewSpeedController {
return Pressure::new::(actual_pressure);
}
+ /// check if current pressure exceeds our limit if enabled
+ pub fn check_pressure_exceed_limit(&mut self, pressure: Pressure) -> bool {
+ return (pressure >= self.nozzle_pressure_limit)
+ && self.nozzle_pressure_limit_enabled
+ && self.motor_on;
+ }
+
pub fn update(&mut self, now: Instant, is_extruding: bool) {
- // TODO: move this logic elsewhere or make non async
block_on(self.inverter.act(now));
- let wiring_error = self.get_wiring_error();
- if wiring_error {
- // emit in act
- }
-
let measured_pressure = self.get_pressure();
-
- if !self.uses_rpm && !is_extruding && self.motor_on {
+ if !self.uses_rpm && !is_extruding {
let frequency = Frequency::new::(0.0);
self.inverter.set_frequency_target(frequency);
self.turn_motor_off();
@@ -219,20 +231,17 @@ impl ScrewSpeedController {
return;
}
- if (measured_pressure >= self.nozzle_pressure_limit)
- && self.nozzle_pressure_limit_enabled
- && self.motor_on
- {
+ if self.check_pressure_exceed_limit(measured_pressure) {
self.turn_motor_off();
self.last_update = now;
return;
}
- if is_extruding == true && self.motor_on == false {
+ if is_extruding && !self.motor_on {
self.turn_motor_on();
}
- if !self.uses_rpm && is_extruding == true {
+ if !self.uses_rpm && is_extruding {
let error = self.target_pressure - measured_pressure;
let freq_change = self.pid.update(error.get::(), now);