Skip to content

Commit a2b69e2

Browse files
committed
go for it
1 parent 9b9a622 commit a2b69e2

File tree

6 files changed

+15
-275
lines changed

6 files changed

+15
-275
lines changed

Marlin/Configuration.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -692,8 +692,7 @@
692692
* @section mpctemp
693693
*/
694694
#if ENABLED(MPCTEMP)
695-
//#define MPC_AUTOTUNE // Include a method to do MPC auto-tuning (~5.7K bytes of flash)
696-
//#define MPC_AUTOTUNE_FANCY // Include a fancier method to do MPC auto-tuning (~6.3K bytes of flash)
695+
//#define MPC_AUTOTUNE // Include a method to do MPC auto-tuning (~6.3K bytes of flash)
697696
//#define MPC_EDIT_MENU // Add MPC editing to the "Advanced Settings" menu. (~1.3K bytes of flash)
698697
//#define MPC_AUTOTUNE_MENU // Add MPC auto-tuning to the "Advanced Settings" menu. (~350 bytes of flash)
699698

Marlin/src/gcode/temp/M306.cpp

+10-17
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@
4343
*
4444
* With MPC_AUTOTUNE:
4545
* T Autotune the extruder specified with 'E' or the active extruder.
46-
*
47-
* With MPC_AUTOTUNE_FANCY:
4846
* S0 : Autotuning method AUTO (default)
4947
* S1 : Autotuning method DIFFERENTIAL
5048
* S2 : Autotuning method ASYMPTOTIC
@@ -57,22 +55,17 @@ void GcodeSuite::M306() {
5755
return;
5856
}
5957

60-
#if EITHER(MPC_AUTOTUNE, MPC_AUTOTUNE_FANCY)
58+
#if ENABLED(MPC_AUTOTUNE)
6159
if (parser.seen_test('T')) {
62-
#if ENABLED(MPC_AUTOTUNE_FANCY)
63-
Temperature::MPCTuningType tuning_type;
64-
const uint8_t type = parser.byteval('S', 0);
65-
switch (type) {
66-
case 1: tuning_type = Temperature::MPCTuningType::FORCE_DIFFERENTIAL; break;
67-
case 2: tuning_type = Temperature::MPCTuningType::FORCE_ASYMPTOTIC; break;
68-
default: tuning_type = Temperature::MPCTuningType::AUTO; break;
69-
}
70-
LCD_MESSAGE(MSG_MPC_AUTOTUNE);
71-
thermalManager.MPC_autotune(e, tuning_type);
72-
#else
73-
LCD_MESSAGE(MSG_MPC_AUTOTUNE);
74-
thermalManager.MPC_autotune(e);
75-
#endif
60+
Temperature::MPCTuningType tuning_type;
61+
const uint8_t type = parser.byteval('S', 0);
62+
switch (type) {
63+
case 1: tuning_type = Temperature::MPCTuningType::FORCE_DIFFERENTIAL; break;
64+
case 2: tuning_type = Temperature::MPCTuningType::FORCE_ASYMPTOTIC; break;
65+
default: tuning_type = Temperature::MPCTuningType::AUTO; break;
66+
}
67+
LCD_MESSAGE(MSG_MPC_AUTOTUNE);
68+
thermalManager.MPC_autotune(e, tuning_type);
7669
ui.reset_status();
7770
return;
7871
}

Marlin/src/inc/SanityCheck.h

-5
Original file line numberDiff line numberDiff line change
@@ -976,14 +976,9 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
976976
#error "Only enable PIDTEMP or MPCTEMP, but not both."
977977
#undef MPCTEMP
978978
#undef MPC_AUTOTUNE
979-
#undef MPC_AUTOTUNE_FANCY
980979
#undef MPC_EDIT_MENU
981980
#undef MPC_AUTOTUNE_MENU
982981
#endif
983-
#if BOTH(MPC_AUTOTUNE, MPC_AUTOTUNE_FANCY)
984-
#error "Only enable MPC_AUTOTUNE or MPC_AUTOTUNE_FANCY, but not both."
985-
#undef MPC_AUTOTUNE_FANCY
986-
#endif
987982

988983
#if ENABLED(MPC_INCLUDE_FAN)
989984
#if !HAS_FAN

Marlin/src/module/temperature.cpp

+1-244
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ volatile bool Temperature::raw_temps_ready = false;
938938

939939
#endif // HAS_PID_HEATING
940940

941-
#if ENABLED(MPC_AUTOTUNE_FANCY)
941+
#if ENABLED(MPC_AUTOTUNE)
942942

943943
#if EITHER(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND)
944944
#define SINGLEFAN 1
@@ -1317,249 +1317,6 @@ volatile bool Temperature::raw_temps_ready = false;
13171317
TERN_(HAS_FAN, SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF_FAN255 ", ambient_xfer_coeff_fan255, 4));
13181318
}
13191319

1320-
#elif ENABLED(MPC_AUTOTUNE)
1321-
1322-
#if EITHER(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND)
1323-
#define SINGLEFAN 1
1324-
#endif
1325-
1326-
void Temperature::MPC_autotune(const uint8_t e) {
1327-
auto housekeeping = [] (millis_t &ms, const uint8_t e, celsius_float_t &current_temp, millis_t &next_report_ms) {
1328-
ms = millis();
1329-
1330-
if (updateTemperaturesIfReady()) { // temp sample ready
1331-
current_temp = degHotend(e);
1332-
TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms));
1333-
}
1334-
1335-
if (ELAPSED(ms, next_report_ms)) {
1336-
next_report_ms += 1000UL;
1337-
1338-
print_heater_states(e);
1339-
SERIAL_EOL();
1340-
}
1341-
1342-
hal.idletask();
1343-
TERN(DWIN_CREALITY_LCD, DWIN_Update(), ui.update());
1344-
1345-
if (!wait_for_heatup) {
1346-
SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_INTERRUPTED);
1347-
TERN_(DWIN_LCD_PROUI, DWIN_MPCTuning(MPC_INTERRUPTED));
1348-
return true;
1349-
}
1350-
1351-
return false;
1352-
};
1353-
1354-
struct OnExit {
1355-
uint8_t e;
1356-
OnExit(const uint8_t _e) { this->e = _e; }
1357-
~OnExit() {
1358-
wait_for_heatup = false;
1359-
1360-
ui.reset_status();
1361-
1362-
temp_hotend[e].target = 0.0f;
1363-
temp_hotend[e].soft_pwm_amount = 0;
1364-
#if HAS_FAN
1365-
set_fan_speed(TERN(SINGLEFAN, 0, e), 0);
1366-
planner.sync_fan_speeds(fan_speed);
1367-
#endif
1368-
1369-
do_z_clearance(MPC_TUNING_END_Z, false);
1370-
1371-
TERN_(TEMP_TUNING_MAINTAIN_FAN, adaptive_fan_slowing = true);
1372-
}
1373-
} on_exit(e);
1374-
1375-
SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_START, e);
1376-
MPCHeaterInfo &hotend = temp_hotend[e];
1377-
MPC_t &mpc = hotend.mpc;
1378-
1379-
TERN_(TEMP_TUNING_MAINTAIN_FAN, adaptive_fan_slowing = false);
1380-
1381-
// Move to center of bed, just above bed height and cool with max fan
1382-
gcode.home_all_axes(true);
1383-
disable_all_heaters();
1384-
#if HAS_FAN
1385-
zero_fan_speeds();
1386-
set_fan_speed(TERN(SINGLEFAN, 0, e), 255);
1387-
planner.sync_fan_speeds(fan_speed);
1388-
#endif
1389-
do_blocking_move_to(xyz_pos_t(MPC_TUNING_POS));
1390-
1391-
SERIAL_ECHOLNPGM(STR_MPC_COOLING_TO_AMBIENT);
1392-
#if ENABLED(DWIN_LCD_PROUI)
1393-
DWIN_MPCTuning(MPCTEMP_START);
1394-
LCD_ALERTMESSAGE(MSG_MPC_COOLING_TO_AMBIENT);
1395-
#else
1396-
LCD_MESSAGE(MSG_COOLING);
1397-
#endif
1398-
1399-
millis_t ms = millis(), next_report_ms = ms, next_test_ms = ms + 10000UL;
1400-
celsius_float_t current_temp = degHotend(e),
1401-
ambient_temp = current_temp;
1402-
1403-
wait_for_heatup = true;
1404-
for (;;) { // Can be interrupted with M108
1405-
if (housekeeping(ms, e, current_temp, next_report_ms)) return;
1406-
1407-
if (ELAPSED(ms, next_test_ms)) {
1408-
if (current_temp >= ambient_temp) {
1409-
ambient_temp = (ambient_temp + current_temp) / 2.0f;
1410-
break;
1411-
}
1412-
ambient_temp = current_temp;
1413-
next_test_ms += 10000UL;
1414-
}
1415-
}
1416-
wait_for_heatup = false;
1417-
1418-
#if HAS_FAN
1419-
set_fan_speed(TERN(SINGLEFAN, 0, e), 0);
1420-
planner.sync_fan_speeds(fan_speed);
1421-
#endif
1422-
1423-
hotend.modeled_ambient_temp = ambient_temp;
1424-
1425-
SERIAL_ECHOLNPGM(STR_MPC_HEATING_PAST_200);
1426-
TERN(DWIN_LCD_PROUI, LCD_ALERTMESSAGE(MSG_MPC_HEATING_PAST_200), LCD_MESSAGE(MSG_HEATING));
1427-
hotend.target = 200.0f; // So M105 looks nice
1428-
hotend.soft_pwm_amount = (MPC_MAX) >> 1;
1429-
const millis_t heat_start_time = next_test_ms = ms;
1430-
celsius_float_t temp_samples[16];
1431-
uint8_t sample_count = 0;
1432-
uint16_t sample_distance = 1;
1433-
float t1_time = 0;
1434-
1435-
wait_for_heatup = true;
1436-
for (;;) { // Can be interrupted with M108
1437-
if (housekeeping(ms, e, current_temp, next_report_ms)) return;
1438-
1439-
if (ELAPSED(ms, next_test_ms)) {
1440-
// Record samples between 100C and 200C
1441-
if (current_temp >= 100.0f) {
1442-
// If there are too many samples, space them more widely
1443-
if (sample_count == COUNT(temp_samples)) {
1444-
for (uint8_t i = 0; i < COUNT(temp_samples) / 2; i++)
1445-
temp_samples[i] = temp_samples[i*2];
1446-
sample_count /= 2;
1447-
sample_distance *= 2;
1448-
}
1449-
1450-
if (sample_count == 0) t1_time = float(ms - heat_start_time) / 1000.0f;
1451-
temp_samples[sample_count++] = current_temp;
1452-
}
1453-
1454-
if (current_temp >= 200.0f) break;
1455-
1456-
next_test_ms += 1000UL * sample_distance;
1457-
}
1458-
}
1459-
wait_for_heatup = false;
1460-
1461-
hotend.soft_pwm_amount = 0;
1462-
1463-
// Calculate physical constants from three equally-spaced samples
1464-
sample_count = (sample_count + 1) / 2 * 2 - 1;
1465-
const float t1 = temp_samples[0],
1466-
t2 = temp_samples[(sample_count - 1) >> 1],
1467-
t3 = temp_samples[sample_count - 1];
1468-
float asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3),
1469-
block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1));
1470-
1471-
mpc.ambient_xfer_coeff_fan0 = mpc.heater_power * (MPC_MAX) / 255 / (asymp_temp - ambient_temp);
1472-
mpc.block_heat_capacity = mpc.ambient_xfer_coeff_fan0 / block_responsiveness;
1473-
mpc.sensor_responsiveness = block_responsiveness / (1.0f - (ambient_temp - asymp_temp) * exp(-block_responsiveness * t1_time) / (t1 - asymp_temp));
1474-
TERN_(MPC_INCLUDE_FAN, mpc.fan255_adjustment = 0.0f);
1475-
1476-
hotend.modeled_block_temp = asymp_temp + (ambient_temp - asymp_temp) * exp(-block_responsiveness * (ms - heat_start_time) / 1000.0f);
1477-
hotend.modeled_sensor_temp = current_temp;
1478-
1479-
// Allow the system to stabilize under MPC, then get a better measure of ambient loss with and without fan
1480-
SERIAL_ECHOLNPGM(STR_MPC_MEASURING_AMBIENT, hotend.modeled_block_temp);
1481-
TERN(DWIN_LCD_PROUI, LCD_ALERTMESSAGE(MSG_MPC_MEASURING_AMBIENT), LCD_MESSAGE(MSG_MPC_MEASURING_AMBIENT));
1482-
hotend.target = hotend.modeled_block_temp;
1483-
next_test_ms = ms + MPC_dT * 1000;
1484-
constexpr millis_t settle_time = 20000UL, test_duration = 20000UL;
1485-
millis_t settle_end_ms = ms + settle_time,
1486-
test_end_ms = settle_end_ms + test_duration;
1487-
float total_energy_fan0 = 0.0f;
1488-
#if HAS_FAN
1489-
bool fan0_done = false;
1490-
float total_energy_fan255 = 0.0f;
1491-
#endif
1492-
float last_temp = current_temp;
1493-
1494-
wait_for_heatup = true;
1495-
for (;;) { // Can be interrupted with M108
1496-
if (housekeeping(ms, e, current_temp, next_report_ms)) return;
1497-
1498-
if (ELAPSED(ms, next_test_ms)) {
1499-
hotend.soft_pwm_amount = (int)get_pid_output_hotend(e) >> 1;
1500-
1501-
if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms) && TERN1(HAS_FAN, !fan0_done))
1502-
total_energy_fan0 += mpc.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * mpc.block_heat_capacity;
1503-
#if HAS_FAN
1504-
else if (ELAPSED(ms, test_end_ms) && !fan0_done) {
1505-
set_fan_speed(TERN(SINGLEFAN, 0, e), 255);
1506-
planner.sync_fan_speeds(fan_speed);
1507-
settle_end_ms = ms + settle_time;
1508-
test_end_ms = settle_end_ms + test_duration;
1509-
fan0_done = true;
1510-
}
1511-
else if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms))
1512-
total_energy_fan255 += mpc.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * mpc.block_heat_capacity;
1513-
#endif
1514-
else if (ELAPSED(ms, test_end_ms)) break;
1515-
1516-
last_temp = current_temp;
1517-
next_test_ms += MPC_dT * 1000;
1518-
}
1519-
1520-
if (!WITHIN(current_temp, t3 - 15.0f, hotend.target + 15.0f)) {
1521-
SERIAL_ECHOLNPGM(STR_MPC_TEMPERATURE_ERROR);
1522-
TERN_(DWIN_LCD_PROUI, DWIN_MPCTuning(MPC_TEMP_ERROR));
1523-
break;
1524-
}
1525-
}
1526-
wait_for_heatup = false;
1527-
1528-
const float power_fan0 = total_energy_fan0 * 1000 / test_duration;
1529-
mpc.ambient_xfer_coeff_fan0 = power_fan0 / (hotend.target - ambient_temp);
1530-
1531-
#if HAS_FAN
1532-
const float power_fan255 = total_energy_fan255 * 1000 / test_duration,
1533-
ambient_xfer_coeff_fan255 = power_fan255 / (hotend.target - ambient_temp);
1534-
mpc.applyFanAdjustment(ambient_xfer_coeff_fan255);
1535-
#endif
1536-
1537-
// Calculate a new and better asymptotic temperature and re-evaluate the other constants
1538-
asymp_temp = ambient_temp + mpc.heater_power * (MPC_MAX) / 255 / mpc.ambient_xfer_coeff_fan0;
1539-
block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1));
1540-
mpc.block_heat_capacity = mpc.ambient_xfer_coeff_fan0 / block_responsiveness;
1541-
mpc.sensor_responsiveness = block_responsiveness / (1.0f - (ambient_temp - asymp_temp) * exp(-block_responsiveness * t1_time) / (t1 - asymp_temp));
1542-
1543-
SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_FINISHED);
1544-
TERN_(DWIN_LCD_PROUI, DWIN_MPCTuning(MPC_DONE));
1545-
1546-
#if 0
1547-
SERIAL_ECHOLNPGM("t1_time ", t1_time);
1548-
SERIAL_ECHOLNPGM("sample_count ", sample_count);
1549-
SERIAL_ECHOLNPGM("sample_distance ", sample_distance);
1550-
for (uint8_t i = 0; i < sample_count; i++)
1551-
SERIAL_ECHOLNPGM("sample ", i, " : ", temp_samples[i]);
1552-
SERIAL_ECHOLNPGM("t1 ", t1, " t2 ", t2, " t3 ", t3);
1553-
SERIAL_ECHOLNPGM("asymp_temp ", asymp_temp);
1554-
SERIAL_ECHOLNPAIR_F("block_responsiveness ", block_responsiveness, 4);
1555-
#endif
1556-
1557-
SERIAL_ECHOLNPGM("MPC_BLOCK_HEAT_CAPACITY ", mpc.block_heat_capacity);
1558-
SERIAL_ECHOLNPAIR_F("MPC_SENSOR_RESPONSIVENESS ", mpc.sensor_responsiveness, 4);
1559-
SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF ", mpc.ambient_xfer_coeff_fan0, 4);
1560-
TERN_(HAS_FAN, SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF_FAN255 ", ambient_xfer_coeff_fan255, 4));
1561-
}
1562-
15631320
#endif // MPC_AUTOTUNE
15641321

15651322
int16_t Temperature::getHeaterPower(const heater_id_t heater_id) {

Marlin/src/module/temperature.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ class Temperature {
12171217

12181218
#endif // HAS_PID_HEATING
12191219

1220-
#if ENABLED(MPC_AUTOTUNE_FANCY)
1220+
#if ENABLED(MPC_AUTOTUNE)
12211221

12221222
// Utility class to perform MPCTEMP auto tuning measurements
12231223
class MPC_autotuner {
@@ -1276,11 +1276,7 @@ class Temperature {
12761276
enum MPCTuningType { AUTO, FORCE_ASYMPTOTIC, FORCE_DIFFERENTIAL };
12771277
static void MPC_autotune(const uint8_t e, MPCTuningType tuning_type);
12781278

1279-
#elif ENABLED(MPC_AUTOTUNE)
1280-
1281-
void MPC_autotune(const uint8_t e);
1282-
1283-
#endif
1279+
#endif // MPC_AUTOTUNE
12841280

12851281
#if ENABLED(PROBING_HEATERS_OFF)
12861282
static void pause_heaters(const bool p);

buildroot/tests/STM32F103RE_creality

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ exec_test $1 $2 "Ender-3 v2 - JyersUI (ABL Bilinear/Manual)" "$3"
2020

2121
use_example_configs "Creality/Ender-3 V2/CrealityV422/CrealityUI"
2222
opt_disable DWIN_CREALITY_LCD PIDTEMP
23-
opt_enable DWIN_MARLINUI_LANDSCAPE LCD_ENDSTOP_TEST AUTO_BED_LEVELING_UBL BLTOUCH Z_SAFE_HOMING MPCTEMP MPC_AUTOTUNE_FANCY
23+
opt_enable DWIN_MARLINUI_LANDSCAPE LCD_ENDSTOP_TEST AUTO_BED_LEVELING_UBL BLTOUCH Z_SAFE_HOMING MPCTEMP MPC_AUTOTUNE
2424
exec_test $1 $2 "Ender-3 v2 - MarlinUI (UBL+BLTOUCH, MPCTEMP, LCD_ENDSTOP_TEST)" "$3"
2525

2626
use_example_configs "Creality/Ender-3 S1/STM32F1"

0 commit comments

Comments
 (0)