@@ -938,7 +938,7 @@ volatile bool Temperature::raw_temps_ready = false;
938
938
939
939
#endif // HAS_PID_HEATING
940
940
941
- #if ENABLED(MPC_AUTOTUNE_FANCY )
941
+ #if ENABLED(MPC_AUTOTUNE )
942
942
943
943
#if EITHER(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND)
944
944
#define SINGLEFAN 1
@@ -1317,249 +1317,6 @@ volatile bool Temperature::raw_temps_ready = false;
1317
1317
TERN_ (HAS_FAN, SERIAL_ECHOLNPAIR_F (" MPC_AMBIENT_XFER_COEFF_FAN255 " , ambient_xfer_coeff_fan255, 4 ));
1318
1318
}
1319
1319
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 ¤t_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
-
1563
1320
#endif // MPC_AUTOTUNE
1564
1321
1565
1322
int16_t Temperature::getHeaterPower (const heater_id_t heater_id) {
0 commit comments