|
@@ -221,176 +221,180 @@ static void updateTemperaturesFromRawValues();
|
221
|
221
|
//================================ Functions ================================
|
222
|
222
|
//===========================================================================
|
223
|
223
|
|
224
|
|
-void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
|
225
|
|
- float input = 0.0;
|
226
|
|
- int cycles = 0;
|
227
|
|
- bool heating = true;
|
|
224
|
+#if ENABLED(PIDTEMP)
|
228
|
225
|
|
229
|
|
- millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
|
230
|
|
- long t_high = 0, t_low = 0;
|
|
226
|
+ void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false*/) {
|
|
227
|
+ float input = 0.0;
|
|
228
|
+ int cycles = 0;
|
|
229
|
+ bool heating = true;
|
231
|
230
|
|
232
|
|
- long bias, d;
|
233
|
|
- float Ku, Tu;
|
234
|
|
- float workKp = 0, workKi = 0, workKd = 0;
|
235
|
|
- float max = 0, min = 10000;
|
|
231
|
+ millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
|
|
232
|
+ long t_high = 0, t_low = 0;
|
236
|
233
|
|
237
|
|
- #if HAS_AUTO_FAN
|
238
|
|
- millis_t next_auto_fan_check_ms = temp_ms + 2500UL;
|
239
|
|
- #endif
|
|
234
|
+ long bias, d;
|
|
235
|
+ float Ku, Tu;
|
|
236
|
+ float workKp = 0, workKi = 0, workKd = 0;
|
|
237
|
+ float max = 0, min = 10000;
|
240
|
238
|
|
241
|
|
- if (extruder >= EXTRUDERS
|
242
|
|
- #if !HAS_TEMP_BED
|
243
|
|
- || extruder < 0
|
|
239
|
+ #if HAS_AUTO_FAN
|
|
240
|
+ millis_t next_auto_fan_check_ms = temp_ms + 2500UL;
|
244
|
241
|
#endif
|
245
|
|
- ) {
|
246
|
|
- SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
|
247
|
|
- return;
|
248
|
|
- }
|
249
|
242
|
|
250
|
|
- SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START);
|
|
243
|
+ if (extruder >= EXTRUDERS
|
|
244
|
+ #if !HAS_TEMP_BED
|
|
245
|
+ || extruder < 0
|
|
246
|
+ #endif
|
|
247
|
+ ) {
|
|
248
|
+ SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
|
|
249
|
+ return;
|
|
250
|
+ }
|
251
|
251
|
|
252
|
|
- disable_all_heaters(); // switch off all heaters.
|
|
252
|
+ SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START);
|
253
|
253
|
|
254
|
|
- if (extruder < 0)
|
255
|
|
- soft_pwm_bed = bias = d = (MAX_BED_POWER) / 2;
|
256
|
|
- else
|
257
|
|
- soft_pwm[extruder] = bias = d = (PID_MAX) / 2;
|
|
254
|
+ disable_all_heaters(); // switch off all heaters.
|
258
|
255
|
|
259
|
|
- // PID Tuning loop
|
260
|
|
- for (;;) {
|
|
256
|
+ if (extruder < 0)
|
|
257
|
+ soft_pwm_bed = bias = d = (MAX_BED_POWER) / 2;
|
|
258
|
+ else
|
|
259
|
+ soft_pwm[extruder] = bias = d = (PID_MAX) / 2;
|
261
|
260
|
|
262
|
|
- millis_t ms = millis();
|
|
261
|
+ // PID Tuning loop
|
|
262
|
+ for (;;) {
|
263
|
263
|
|
264
|
|
- if (temp_meas_ready) { // temp sample ready
|
265
|
|
- updateTemperaturesFromRawValues();
|
|
264
|
+ millis_t ms = millis();
|
266
|
265
|
|
267
|
|
- input = (extruder < 0) ? current_temperature_bed : current_temperature[extruder];
|
|
266
|
+ if (temp_meas_ready) { // temp sample ready
|
|
267
|
+ updateTemperaturesFromRawValues();
|
268
|
268
|
|
269
|
|
- max = max(max, input);
|
270
|
|
- min = min(min, input);
|
|
269
|
+ input = (extruder < 0) ? current_temperature_bed : current_temperature[extruder];
|
271
|
270
|
|
272
|
|
- #if HAS_AUTO_FAN
|
273
|
|
- if (ELAPSED(ms, next_auto_fan_check_ms)) {
|
274
|
|
- checkExtruderAutoFans();
|
275
|
|
- next_auto_fan_check_ms = ms + 2500UL;
|
276
|
|
- }
|
277
|
|
- #endif
|
|
271
|
+ max = max(max, input);
|
|
272
|
+ min = min(min, input);
|
|
273
|
+
|
|
274
|
+ #if HAS_AUTO_FAN
|
|
275
|
+ if (ELAPSED(ms, next_auto_fan_check_ms)) {
|
|
276
|
+ checkExtruderAutoFans();
|
|
277
|
+ next_auto_fan_check_ms = ms + 2500UL;
|
|
278
|
+ }
|
|
279
|
+ #endif
|
278
|
280
|
|
279
|
|
- if (heating && input > temp) {
|
280
|
|
- if (ELAPSED(ms, t2 + 5000UL)) {
|
281
|
|
- heating = false;
|
282
|
|
- if (extruder < 0)
|
283
|
|
- soft_pwm_bed = (bias - d) >> 1;
|
284
|
|
- else
|
285
|
|
- soft_pwm[extruder] = (bias - d) >> 1;
|
286
|
|
- t1 = ms;
|
287
|
|
- t_high = t1 - t2;
|
288
|
|
- max = temp;
|
|
281
|
+ if (heating && input > temp) {
|
|
282
|
+ if (ELAPSED(ms, t2 + 5000UL)) {
|
|
283
|
+ heating = false;
|
|
284
|
+ if (extruder < 0)
|
|
285
|
+ soft_pwm_bed = (bias - d) >> 1;
|
|
286
|
+ else
|
|
287
|
+ soft_pwm[extruder] = (bias - d) >> 1;
|
|
288
|
+ t1 = ms;
|
|
289
|
+ t_high = t1 - t2;
|
|
290
|
+ max = temp;
|
|
291
|
+ }
|
289
|
292
|
}
|
290
|
|
- }
|
291
|
293
|
|
292
|
|
- if (!heating && input < temp) {
|
293
|
|
- if (ELAPSED(ms, t1 + 5000UL)) {
|
294
|
|
- heating = true;
|
295
|
|
- t2 = ms;
|
296
|
|
- t_low = t2 - t1;
|
297
|
|
- if (cycles > 0) {
|
298
|
|
- long max_pow = extruder < 0 ? MAX_BED_POWER : PID_MAX;
|
299
|
|
- bias += (d * (t_high - t_low)) / (t_low + t_high);
|
300
|
|
- bias = constrain(bias, 20, max_pow - 20);
|
301
|
|
- d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias;
|
302
|
|
-
|
303
|
|
- SERIAL_PROTOCOLPGM(MSG_BIAS); SERIAL_PROTOCOL(bias);
|
304
|
|
- SERIAL_PROTOCOLPGM(MSG_D); SERIAL_PROTOCOL(d);
|
305
|
|
- SERIAL_PROTOCOLPGM(MSG_T_MIN); SERIAL_PROTOCOL(min);
|
306
|
|
- SERIAL_PROTOCOLPGM(MSG_T_MAX); SERIAL_PROTOCOLLN(max);
|
307
|
|
- if (cycles > 2) {
|
308
|
|
- Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
|
309
|
|
- Tu = ((float)(t_low + t_high) / 1000.0);
|
310
|
|
- SERIAL_PROTOCOLPGM(MSG_KU); SERIAL_PROTOCOL(Ku);
|
311
|
|
- SERIAL_PROTOCOLPGM(MSG_TU); SERIAL_PROTOCOLLN(Tu);
|
312
|
|
- workKp = 0.6 * Ku;
|
313
|
|
- workKi = 2 * workKp / Tu;
|
314
|
|
- workKd = workKp * Tu / 8;
|
315
|
|
- SERIAL_PROTOCOLLNPGM(MSG_CLASSIC_PID);
|
316
|
|
- SERIAL_PROTOCOLPGM(MSG_KP); SERIAL_PROTOCOLLN(workKp);
|
317
|
|
- SERIAL_PROTOCOLPGM(MSG_KI); SERIAL_PROTOCOLLN(workKi);
|
318
|
|
- SERIAL_PROTOCOLPGM(MSG_KD); SERIAL_PROTOCOLLN(workKd);
|
319
|
|
- /**
|
320
|
|
- workKp = 0.33*Ku;
|
321
|
|
- workKi = workKp/Tu;
|
322
|
|
- workKd = workKp*Tu/3;
|
323
|
|
- SERIAL_PROTOCOLLNPGM(" Some overshoot ");
|
324
|
|
- SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
|
325
|
|
- SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
|
326
|
|
- SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
|
327
|
|
- workKp = 0.2*Ku;
|
328
|
|
- workKi = 2*workKp/Tu;
|
329
|
|
- workKd = workKp*Tu/3;
|
330
|
|
- SERIAL_PROTOCOLLNPGM(" No overshoot ");
|
331
|
|
- SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
|
332
|
|
- SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
|
333
|
|
- SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
|
334
|
|
- */
|
|
294
|
+ if (!heating && input < temp) {
|
|
295
|
+ if (ELAPSED(ms, t1 + 5000UL)) {
|
|
296
|
+ heating = true;
|
|
297
|
+ t2 = ms;
|
|
298
|
+ t_low = t2 - t1;
|
|
299
|
+ if (cycles > 0) {
|
|
300
|
+ long max_pow = extruder < 0 ? MAX_BED_POWER : PID_MAX;
|
|
301
|
+ bias += (d * (t_high - t_low)) / (t_low + t_high);
|
|
302
|
+ bias = constrain(bias, 20, max_pow - 20);
|
|
303
|
+ d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias;
|
|
304
|
+
|
|
305
|
+ SERIAL_PROTOCOLPGM(MSG_BIAS); SERIAL_PROTOCOL(bias);
|
|
306
|
+ SERIAL_PROTOCOLPGM(MSG_D); SERIAL_PROTOCOL(d);
|
|
307
|
+ SERIAL_PROTOCOLPGM(MSG_T_MIN); SERIAL_PROTOCOL(min);
|
|
308
|
+ SERIAL_PROTOCOLPGM(MSG_T_MAX); SERIAL_PROTOCOLLN(max);
|
|
309
|
+ if (cycles > 2) {
|
|
310
|
+ Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
|
|
311
|
+ Tu = ((float)(t_low + t_high) / 1000.0);
|
|
312
|
+ SERIAL_PROTOCOLPGM(MSG_KU); SERIAL_PROTOCOL(Ku);
|
|
313
|
+ SERIAL_PROTOCOLPGM(MSG_TU); SERIAL_PROTOCOLLN(Tu);
|
|
314
|
+ workKp = 0.6 * Ku;
|
|
315
|
+ workKi = 2 * workKp / Tu;
|
|
316
|
+ workKd = workKp * Tu / 8;
|
|
317
|
+ SERIAL_PROTOCOLLNPGM(MSG_CLASSIC_PID);
|
|
318
|
+ SERIAL_PROTOCOLPGM(MSG_KP); SERIAL_PROTOCOLLN(workKp);
|
|
319
|
+ SERIAL_PROTOCOLPGM(MSG_KI); SERIAL_PROTOCOLLN(workKi);
|
|
320
|
+ SERIAL_PROTOCOLPGM(MSG_KD); SERIAL_PROTOCOLLN(workKd);
|
|
321
|
+ /**
|
|
322
|
+ workKp = 0.33*Ku;
|
|
323
|
+ workKi = workKp/Tu;
|
|
324
|
+ workKd = workKp*Tu/3;
|
|
325
|
+ SERIAL_PROTOCOLLNPGM(" Some overshoot ");
|
|
326
|
+ SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
|
|
327
|
+ SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
|
|
328
|
+ SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
|
|
329
|
+ workKp = 0.2*Ku;
|
|
330
|
+ workKi = 2*workKp/Tu;
|
|
331
|
+ workKd = workKp*Tu/3;
|
|
332
|
+ SERIAL_PROTOCOLLNPGM(" No overshoot ");
|
|
333
|
+ SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(workKp);
|
|
334
|
+ SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(workKi);
|
|
335
|
+ SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(workKd);
|
|
336
|
+ */
|
|
337
|
+ }
|
335
|
338
|
}
|
|
339
|
+ if (extruder < 0)
|
|
340
|
+ soft_pwm_bed = (bias + d) >> 1;
|
|
341
|
+ else
|
|
342
|
+ soft_pwm[extruder] = (bias + d) >> 1;
|
|
343
|
+ cycles++;
|
|
344
|
+ min = temp;
|
336
|
345
|
}
|
337
|
|
- if (extruder < 0)
|
338
|
|
- soft_pwm_bed = (bias + d) >> 1;
|
339
|
|
- else
|
340
|
|
- soft_pwm[extruder] = (bias + d) >> 1;
|
341
|
|
- cycles++;
|
342
|
|
- min = temp;
|
343
|
346
|
}
|
344
|
347
|
}
|
345
|
|
- }
|
346
|
|
- #define MAX_OVERSHOOT_PID_AUTOTUNE 20
|
347
|
|
- if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
|
348
|
|
- SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH);
|
349
|
|
- return;
|
350
|
|
- }
|
351
|
|
- // Every 2 seconds...
|
352
|
|
- if (ELAPSED(ms, temp_ms + 2000UL)) {
|
353
|
|
- #if HAS_TEMP_HOTEND || HAS_TEMP_BED
|
354
|
|
- print_heaterstates();
|
355
|
|
- SERIAL_EOL;
|
356
|
|
- #endif
|
|
348
|
+ #define MAX_OVERSHOOT_PID_AUTOTUNE 20
|
|
349
|
+ if (input > temp + MAX_OVERSHOOT_PID_AUTOTUNE) {
|
|
350
|
+ SERIAL_PROTOCOLLNPGM(MSG_PID_TEMP_TOO_HIGH);
|
|
351
|
+ return;
|
|
352
|
+ }
|
|
353
|
+ // Every 2 seconds...
|
|
354
|
+ if (ELAPSED(ms, temp_ms + 2000UL)) {
|
|
355
|
+ #if HAS_TEMP_HOTEND || HAS_TEMP_BED
|
|
356
|
+ print_heaterstates();
|
|
357
|
+ SERIAL_EOL;
|
|
358
|
+ #endif
|
357
|
359
|
|
358
|
|
- temp_ms = ms;
|
359
|
|
- } // every 2 seconds
|
360
|
|
- // Over 2 minutes?
|
361
|
|
- if (((ms - t1) + (ms - t2)) > (10L * 60L * 1000L * 2L)) {
|
362
|
|
- SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT);
|
363
|
|
- return;
|
364
|
|
- }
|
365
|
|
- if (cycles > ncycles) {
|
366
|
|
- SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED);
|
367
|
|
- const char* estring = extruder < 0 ? "bed" : "";
|
368
|
|
- SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kp "); SERIAL_PROTOCOLLN(workKp);
|
369
|
|
- SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Ki "); SERIAL_PROTOCOLLN(workKi);
|
370
|
|
- SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kd "); SERIAL_PROTOCOLLN(workKd);
|
371
|
|
-
|
372
|
|
- // Use the result? (As with "M303 U1")
|
373
|
|
- if (set_result) {
|
374
|
|
- if (extruder < 0) {
|
375
|
|
- #if ENABLED(PIDTEMPBED)
|
376
|
|
- bedKp = workKp;
|
377
|
|
- bedKi = scalePID_i(workKi);
|
378
|
|
- bedKd = scalePID_d(workKd);
|
|
360
|
+ temp_ms = ms;
|
|
361
|
+ } // every 2 seconds
|
|
362
|
+ // Over 2 minutes?
|
|
363
|
+ if (((ms - t1) + (ms - t2)) > (10L * 60L * 1000L * 2L)) {
|
|
364
|
+ SERIAL_PROTOCOLLNPGM(MSG_PID_TIMEOUT);
|
|
365
|
+ return;
|
|
366
|
+ }
|
|
367
|
+ if (cycles > ncycles) {
|
|
368
|
+ SERIAL_PROTOCOLLNPGM(MSG_PID_AUTOTUNE_FINISHED);
|
|
369
|
+ const char* estring = extruder < 0 ? "bed" : "";
|
|
370
|
+ SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kp "); SERIAL_PROTOCOLLN(workKp);
|
|
371
|
+ SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Ki "); SERIAL_PROTOCOLLN(workKi);
|
|
372
|
+ SERIAL_PROTOCOLPGM("#define DEFAULT_"); SERIAL_PROTOCOL(estring); SERIAL_PROTOCOLPGM("Kd "); SERIAL_PROTOCOLLN(workKd);
|
|
373
|
+
|
|
374
|
+ // Use the result? (As with "M303 U1")
|
|
375
|
+ if (set_result) {
|
|
376
|
+ if (extruder < 0) {
|
|
377
|
+ #if ENABLED(PIDTEMPBED)
|
|
378
|
+ bedKp = workKp;
|
|
379
|
+ bedKi = scalePID_i(workKi);
|
|
380
|
+ bedKd = scalePID_d(workKd);
|
|
381
|
+ updatePID();
|
|
382
|
+ #endif
|
|
383
|
+ }
|
|
384
|
+ else {
|
|
385
|
+ PID_PARAM(Kp, extruder) = workKp;
|
|
386
|
+ PID_PARAM(Ki, extruder) = scalePID_i(workKi);
|
|
387
|
+ PID_PARAM(Kd, extruder) = scalePID_d(workKd);
|
379
|
388
|
updatePID();
|
380
|
|
- #endif
|
381
|
|
- }
|
382
|
|
- else {
|
383
|
|
- PID_PARAM(Kp, extruder) = workKp;
|
384
|
|
- PID_PARAM(Ki, extruder) = scalePID_i(workKi);
|
385
|
|
- PID_PARAM(Kd, extruder) = scalePID_d(workKd);
|
386
|
|
- updatePID();
|
|
389
|
+ }
|
387
|
390
|
}
|
|
391
|
+ return;
|
388
|
392
|
}
|
389
|
|
- return;
|
|
393
|
+ lcd_update();
|
390
|
394
|
}
|
391
|
|
- lcd_update();
|
392
|
395
|
}
|
393
|
|
-}
|
|
396
|
+
|
|
397
|
+#endif // PIDTEMP
|
394
|
398
|
|
395
|
399
|
void updatePID() {
|
396
|
400
|
#if ENABLED(PIDTEMP)
|