MPC_PTC (#27911)

This commit is contained in:
tombrazier 2025-06-14 01:10:03 +01:00 committed by GitHub
parent 9ad9323aac
commit 89416a583c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 47 additions and 12 deletions

View file

@ -735,7 +735,12 @@
//#define MPC_AUTOTUNE_MENU // Add MPC auto-tuning to the "Advanced Settings" menu. (~350 bytes of flash)
#define MPC_MAX 255 // (0..255) Current to nozzle while MPC is active.
#define MPC_HEATER_POWER { 40.0f } // (W) Heat cartridge powers.
#define MPC_HEATER_POWER { 40.0f } // (W) Nominal heat cartridge powers.
//#define MPC_PTC // Hotend power changes with temperature (e.g., PTC heat cartridges).
#if ENABLED(MPC_PTC)
#define MPC_HEATER_ALPHA { 0.0028f } // Temperature coefficient of resistance of the heat cartridges.
#define MPC_HEATER_REFTEMP { 20 } // (°C) Reference temperature for MPC_HEATER_POWER and MPC_HEATER_ALPHA.
#endif
#define MPC_INCLUDE_FAN // Model the fan speed?

View file

@ -64,9 +64,13 @@ void GcodeSuite::M306() {
case 2: tuning_type = Temperature::MPCTuningType::FORCE_ASYMPTOTIC; break;
default: tuning_type = Temperature::MPCTuningType::AUTO; break;
}
LCD_MESSAGE(MSG_MPC_AUTOTUNE);
thermalManager.MPC_autotune(e, tuning_type);
ui.reset_status();
if (TERN0(MPC_PTC, tuning_type == Temperature::MPCTuningType::FORCE_ASYMPTOTIC))
SERIAL_ECHOLNPGM("Aymptotic tuning not avaiable for PTC hotends");
else {
LCD_MESSAGE(MSG_MPC_AUTOTUNE);
thermalManager.MPC_autotune(e, tuning_type);
ui.reset_status();
}
return;
}
#endif
@ -74,6 +78,10 @@ void GcodeSuite::M306() {
if (parser.seen("ACFPRH")) {
MPC_t &mpc = thermalManager.temp_hotend[e].mpc;
if (parser.seenval('P')) mpc.heater_power = parser.value_float();
#if ENABLED(MPC_PTC)
if (parser.seenval('L')) mpc.heater_alpha = parser.value_float();
if (parser.seenval('Q')) mpc.heater_reftemp = parser.value_float();
#endif
if (parser.seenval('C')) mpc.block_heat_capacity = parser.value_float();
if (parser.seenval('R')) mpc.sensor_responsiveness = parser.value_float();
if (parser.seenval('A')) mpc.ambient_xfer_coeff_fan0 = parser.value_float();
@ -94,16 +102,20 @@ void GcodeSuite::M306_report(const bool forReplay/*=true*/) {
HOTEND_LOOP() {
report_echo_start(forReplay);
MPC_t &mpc = thermalManager.temp_hotend[e].mpc;
SERIAL_ECHOPGM(" M306 E", e,
SERIAL_ECHOLNPGM(" M306 E", e,
" P", p_float_t(mpc.heater_power, 2),
#if ENABLED(MPC_PTC)
" L", p_float_t(mpc.heater_alpha, 4),
" Q", p_float_t(mpc.heater_reftemp, 2),
#endif
" C", p_float_t(mpc.block_heat_capacity, 2),
" R", p_float_t(mpc.sensor_responsiveness, 4),
" A", p_float_t(mpc.ambient_xfer_coeff_fan0, 4)
" A", p_float_t(mpc.ambient_xfer_coeff_fan0, 4),
#if ENABLED(MPC_INCLUDE_FAN)
" F", p_float_t(mpc.fanCoefficient(), 4),
#endif
" H", p_float_t(mpc.filament_heat_capacity_permm, 4)
);
#if ENABLED(MPC_INCLUDE_FAN)
SERIAL_ECHOPGM(" F", p_float_t(mpc.fanCoefficient(), 4));
#endif
SERIAL_ECHOLNPGM(" H", p_float_t(mpc.filament_heat_capacity_permm, 4));
}
}

View file

@ -1026,6 +1026,7 @@ static_assert(NUM_SERVOS <= NUM_SERVO_PLUGS, "NUM_SERVOS (or some servo index) i
#undef MPC_AUTOTUNE
#undef MPC_EDIT_MENU
#undef MPC_AUTOTUNE_MENU
#undef MPC_PTC
#endif
#if ENABLED(MPC_INCLUDE_FAN)

View file

@ -3710,6 +3710,10 @@ void MarlinSettings::reset() {
#if ENABLED(MPCTEMP)
constexpr float _mpc_heater_power[] = MPC_HEATER_POWER;
#if ENABLED(MPC_PTC)
constexpr float _mpc_heater_alpha[] = MPC_HEATER_ALPHA;
constexpr float _mpc_heater_reftemp[] = MPC_HEATER_REFTEMP;
#endif
constexpr float _mpc_block_heat_capacity[] = MPC_BLOCK_HEAT_CAPACITY;
constexpr float _mpc_sensor_responsiveness[] = MPC_SENSOR_RESPONSIVENESS;
constexpr float _mpc_ambient_xfer_coeff[] = MPC_AMBIENT_XFER_COEFF;
@ -3719,6 +3723,10 @@ void MarlinSettings::reset() {
constexpr float _filament_heat_capacity_permm[] = FILAMENT_HEAT_CAPACITY_PERMM;
static_assert(COUNT(_mpc_heater_power) == HOTENDS, "MPC_HEATER_POWER must have HOTENDS items.");
#if ENABLED(MPC_PTC)
static_assert(COUNT(_mpc_heater_alpha) == HOTENDS, "MPC_HEATER_ALPHA must have HOTENDS items.");
static_assert(COUNT(_mpc_heater_reftemp) == HOTENDS, "MPC_HEATER_REFTEMP must have HOTENDS items.");
#endif
static_assert(COUNT(_mpc_block_heat_capacity) == HOTENDS, "MPC_BLOCK_HEAT_CAPACITY must have HOTENDS items.");
static_assert(COUNT(_mpc_sensor_responsiveness) == HOTENDS, "MPC_SENSOR_RESPONSIVENESS must have HOTENDS items.");
static_assert(COUNT(_mpc_ambient_xfer_coeff) == HOTENDS, "MPC_AMBIENT_XFER_COEFF must have HOTENDS items.");
@ -3730,6 +3738,10 @@ void MarlinSettings::reset() {
HOTEND_LOOP() {
MPC_t &mpc = thermalManager.temp_hotend[e].mpc;
mpc.heater_power = _mpc_heater_power[e];
#if ENABLED(MPC_PTC)
mpc.heater_alpha = _mpc_heater_alpha[e];
mpc.heater_reftemp = _mpc_heater_reftemp[e];
#endif
mpc.block_heat_capacity = _mpc_block_heat_capacity[e];
mpc.sensor_responsiveness = _mpc_sensor_responsiveness[e];
mpc.ambient_xfer_coeff_fan0 = _mpc_ambient_xfer_coeff[e];

View file

@ -1864,7 +1864,8 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T
}
// Update the modeled temperatures
float blocktempdelta = hotend.soft_pwm_amount * mpc.heater_power * (MPC_dT / 127) / mpc.block_heat_capacity;
const float _heater_power = DIV_TERN(MPC_PTC, mpc.heater_power, 1.0f + mpc.heater_alpha * (hotend.modeled_block_temp - mpc.heater_reftemp));
float blocktempdelta = hotend.soft_pwm_amount * _heater_power * (MPC_dT / 127) / mpc.block_heat_capacity;
blocktempdelta += (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff * MPC_dT / mpc.block_heat_capacity;
hotend.modeled_block_temp += blocktempdelta;
@ -1888,7 +1889,7 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T
power -= (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff;
}
float pid_output = power * 254.0f / mpc.heater_power + 1.0f; // Ensure correct quantization into a range of 0 to 127
float pid_output = power * 254.0f / _heater_power + 1.0f; // Ensure correct quantization into a range of 0 to 127
LIMIT(pid_output, 0, MPC_MAX);
/* <-- add a slash to enable

View file

@ -386,6 +386,10 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t;
static bool e_paused; // Pause E filament permm tracking
static int32_t e_position; // For E tracking
float heater_power; // M306 P
#if ENABLED(MPC_PTC)
float heater_alpha; // M306 L
float heater_reftemp; // M306 Q
#endif
float block_heat_capacity; // M306 C
float sensor_responsiveness; // M306 R
float ambient_xfer_coeff_fan0; // M306 A