diff --git a/Firmware/language_all.cpp b/Firmware/language_all.cpp index 950fde70f..87c7bf513 100644 --- a/Firmware/language_all.cpp +++ b/Firmware/language_all.cpp @@ -692,6 +692,11 @@ const char * const MSG_DWELL_LANG_TABLE[LANG_NUM] PROGMEM = { MSG_DWELL_DE }; +const char MSG_EEPROM_SAVING_EN[] PROGMEM = "Saving"; +const char * const MSG_EEPROM_SAVING_LANG_TABLE[1] PROGMEM = { + MSG_EEPROM_SAVING_EN +}; + const char MSG_ENDSTOPS_HIT_EN[] PROGMEM = "endstops hit: "; const char * const MSG_ENDSTOPS_HIT_LANG_TABLE[1] PROGMEM = { MSG_ENDSTOPS_HIT_EN @@ -1736,6 +1741,21 @@ const char * const MSG_PICK_Z_LANG_TABLE[LANG_NUM] PROGMEM = { MSG_PICK_Z_DE }; +const char MSG_PID_EXTRUDER_EN[] PROGMEM = "PID calibration"; +const char * const MSG_PID_EXTRUDER_LANG_TABLE[1] PROGMEM = { + MSG_PID_EXTRUDER_EN +}; + +const char MSG_PID_FINISHED_EN[] PROGMEM = "PID cal. finished"; +const char * const MSG_PID_FINISHED_LANG_TABLE[1] PROGMEM = { + MSG_PID_FINISHED_EN +}; + +const char MSG_PID_RUNNING_EN[] PROGMEM = "PID cal. "; +const char * const MSG_PID_RUNNING_LANG_TABLE[1] PROGMEM = { + MSG_PID_RUNNING_EN +}; + const char MSG_PLANNER_BUFFER_BYTES_EN[] PROGMEM = " PlannerBufferBytes: "; const char * const MSG_PLANNER_BUFFER_BYTES_LANG_TABLE[1] PROGMEM = { MSG_PLANNER_BUFFER_BYTES_EN @@ -2446,6 +2466,11 @@ const char * const MSG_SET_ORIGIN_LANG_TABLE[1] PROGMEM = { MSG_SET_ORIGIN_EN }; +const char MSG_SET_TEMPERATURE_EN[] PROGMEM = "Set temperature"; +const char * const MSG_SET_TEMPERATURE_LANG_TABLE[1] PROGMEM = { + MSG_SET_TEMPERATURE_EN +}; + const char MSG_SHOW_END_STOPS_EN[] PROGMEM = "Show end stops"; const char MSG_SHOW_END_STOPS_CZ[] PROGMEM = "Stav konc. spin."; const char MSG_SHOW_END_STOPS_IT[] PROGMEM = "Stato finecorsa"; diff --git a/Firmware/language_all.h b/Firmware/language_all.h index dfadc2569..aa1ee4256 100644 --- a/Firmware/language_all.h +++ b/Firmware/language_all.h @@ -139,6 +139,8 @@ extern const char* const MSG_DISABLE_STEPPERS_LANG_TABLE[LANG_NUM]; #define MSG_DISABLE_STEPPERS LANG_TABLE_SELECT(MSG_DISABLE_STEPPERS_LANG_TABLE) extern const char* const MSG_DWELL_LANG_TABLE[LANG_NUM]; #define MSG_DWELL LANG_TABLE_SELECT(MSG_DWELL_LANG_TABLE) +extern const char* const MSG_EEPROM_SAVING_LANG_TABLE[1]; +#define MSG_EEPROM_SAVING LANG_TABLE_SELECT_EXPLICIT(MSG_EEPROM_SAVING_LANG_TABLE, 0) extern const char* const MSG_ENDSTOPS_HIT_LANG_TABLE[1]; #define MSG_ENDSTOPS_HIT LANG_TABLE_SELECT_EXPLICIT(MSG_ENDSTOPS_HIT_LANG_TABLE, 0) extern const char* const MSG_ENDSTOP_HIT_LANG_TABLE[1]; @@ -345,6 +347,12 @@ extern const char* const MSG_PAUSE_PRINT_LANG_TABLE[LANG_NUM]; #define MSG_PAUSE_PRINT LANG_TABLE_SELECT(MSG_PAUSE_PRINT_LANG_TABLE) extern const char* const MSG_PICK_Z_LANG_TABLE[LANG_NUM]; #define MSG_PICK_Z LANG_TABLE_SELECT(MSG_PICK_Z_LANG_TABLE) +extern const char* const MSG_PID_EXTRUDER_LANG_TABLE[1]; +#define MSG_PID_EXTRUDER LANG_TABLE_SELECT_EXPLICIT(MSG_PID_EXTRUDER_LANG_TABLE, 0) +extern const char* const MSG_PID_FINISHED_LANG_TABLE[1]; +#define MSG_PID_FINISHED LANG_TABLE_SELECT_EXPLICIT(MSG_PID_FINISHED_LANG_TABLE, 0) +extern const char* const MSG_PID_RUNNING_LANG_TABLE[1]; +#define MSG_PID_RUNNING LANG_TABLE_SELECT_EXPLICIT(MSG_PID_RUNNING_LANG_TABLE, 0) extern const char* const MSG_PLANNER_BUFFER_BYTES_LANG_TABLE[1]; #define MSG_PLANNER_BUFFER_BYTES LANG_TABLE_SELECT_EXPLICIT(MSG_PLANNER_BUFFER_BYTES_LANG_TABLE, 0) extern const char* const MSG_PLEASE_WAIT_LANG_TABLE[LANG_NUM]; @@ -483,6 +491,8 @@ extern const char* const MSG_SET_HOME_OFFSETS_LANG_TABLE[1]; #define MSG_SET_HOME_OFFSETS LANG_TABLE_SELECT_EXPLICIT(MSG_SET_HOME_OFFSETS_LANG_TABLE, 0) extern const char* const MSG_SET_ORIGIN_LANG_TABLE[1]; #define MSG_SET_ORIGIN LANG_TABLE_SELECT_EXPLICIT(MSG_SET_ORIGIN_LANG_TABLE, 0) +extern const char* const MSG_SET_TEMPERATURE_LANG_TABLE[1]; +#define MSG_SET_TEMPERATURE LANG_TABLE_SELECT_EXPLICIT(MSG_SET_TEMPERATURE_LANG_TABLE, 0) extern const char* const MSG_SHOW_END_STOPS_LANG_TABLE[LANG_NUM]; #define MSG_SHOW_END_STOPS LANG_TABLE_SELECT(MSG_SHOW_END_STOPS_LANG_TABLE) extern const char* const MSG_SILENT_MODE_OFF_LANG_TABLE[LANG_NUM]; diff --git a/Firmware/language_en.h b/Firmware/language_en.h index ab1450ea8..e4f2b9794 100644 --- a/Firmware/language_en.h +++ b/Firmware/language_en.h @@ -268,4 +268,9 @@ #define MSG_PRINTER_DISCONNECTED "Printer disconnected" #define MSG_FINISHING_MOVEMENTS "Finishing movements" #define MSG_PRINT_PAUSED "Print paused" -#define MSG_RESUMING_PRINT "Resuming print" \ No newline at end of file +#define MSG_RESUMING_PRINT "Resuming print" +#define MSG_PID_EXTRUDER "PID calibration" +#define MSG_SET_TEMPERATURE "Set temperature" +#define MSG_PID_FINISHED "PID cal. finished" +#define MSG_PID_RUNNING "PID cal. " +#define MSG_EEPROM_SAVING "Saving" \ No newline at end of file diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index d2f6e3f88..77ef6e989 100644 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -51,7 +51,12 @@ float current_temperature_bed = 0.0; int redundant_temperature_raw = 0; float redundant_temperature = 0.0; #endif + + #ifdef PIDTEMP + float _Kp, _Ki, _Kd; + int pid_cycle, pid_number_of_cycles; + bool pid_tuning_finished = false; float Kp=DEFAULT_Kp; float Ki=(DEFAULT_Ki*PID_dT); float Kd=(DEFAULT_Kd/PID_dT); @@ -181,10 +186,12 @@ unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0); //============================= functions ============================ //=========================================================================== -void PID_autotune(float temp, int extruder, int ncycles) -{ + void PID_autotune(float temp, int extruder, int ncycles) + { + pid_number_of_cycles = ncycles; + pid_tuning_finished = false; float input = 0.0; - int cycles=0; + pid_cycle=0; bool heating = true; unsigned long temp_millis = millis(); @@ -195,7 +202,6 @@ void PID_autotune(float temp, int extruder, int ncycles) long bias, d; float Ku, Tu; - float Kp, Ki, Kd; float max = 0, min = 10000; #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \ @@ -210,6 +216,8 @@ void PID_autotune(float temp, int extruder, int ncycles) #endif ){ SERIAL_ECHOLN("PID Autotune failed. Bad extruder number."); + pid_tuning_finished = true; + pid_cycle = 0; return; } @@ -267,7 +275,7 @@ void PID_autotune(float temp, int extruder, int ncycles) heating=true; t2=millis(); t_low=t2 - t1; - if(cycles > 0) { + if(pid_cycle > 0) { bias += (d*(t_high - t_low))/(t_low + t_high); bias = constrain(bias, 20 ,(extruder<0?(MAX_BED_POWER):(PID_MAX))-20); if(bias > (extruder<0?(MAX_BED_POWER):(PID_MAX))/2) d = (extruder<0?(MAX_BED_POWER):(PID_MAX)) - 1 - bias; @@ -277,33 +285,33 @@ void PID_autotune(float temp, int extruder, int ncycles) SERIAL_PROTOCOLPGM(" d: "); SERIAL_PROTOCOL(d); SERIAL_PROTOCOLPGM(" min: "); SERIAL_PROTOCOL(min); SERIAL_PROTOCOLPGM(" max: "); SERIAL_PROTOCOLLN(max); - if(cycles > 2) { + if(pid_cycle > 2) { Ku = (4.0*d)/(3.14159*(max-min)/2.0); Tu = ((float)(t_low + t_high)/1000.0); SERIAL_PROTOCOLPGM(" Ku: "); SERIAL_PROTOCOL(Ku); SERIAL_PROTOCOLPGM(" Tu: "); SERIAL_PROTOCOLLN(Tu); - Kp = 0.6*Ku; - Ki = 2*Kp/Tu; - Kd = Kp*Tu/8; + _Kp = 0.6*Ku; + _Ki = 2*_Kp/Tu; + _Kd = _Kp*Tu/8; SERIAL_PROTOCOLLNPGM(" Classic PID "); - SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); - SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); - SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(_Kp); + SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(_Ki); + SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(_Kd); /* - Kp = 0.33*Ku; - Ki = Kp/Tu; - Kd = Kp*Tu/3; + _Kp = 0.33*Ku; + _Ki = _Kp/Tu; + _Kd = _Kp*Tu/3; SERIAL_PROTOCOLLNPGM(" Some overshoot "); - SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); - SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); - SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); - Kp = 0.2*Ku; - Ki = 2*Kp/Tu; - Kd = Kp*Tu/3; + SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(_Kp); + SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(_Ki); + SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(_Kd); + _Kp = 0.2*Ku; + _Ki = 2*_Kp/Tu; + _Kd = _Kp*Tu/3; SERIAL_PROTOCOLLNPGM(" No overshoot "); - SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); - SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); - SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(_Kp); + SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(_Ki); + SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(_Kd); */ } } @@ -311,13 +319,15 @@ void PID_autotune(float temp, int extruder, int ncycles) soft_pwm_bed = (bias + d) >> 1; else soft_pwm[extruder] = (bias + d) >> 1; - cycles++; + pid_cycle++; min=temp; } } } if(input > (temp + 20)) { SERIAL_PROTOCOLLNPGM("PID Autotune failed! Temperature too high"); + pid_tuning_finished = true; + pid_cycle = 0; return; } if(millis() - temp_millis > 2000) { @@ -338,10 +348,14 @@ void PID_autotune(float temp, int extruder, int ncycles) } if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) { SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout"); + pid_tuning_finished = true; + pid_cycle = 0; return; } - if(cycles > ncycles) { + if(pid_cycle > ncycles) { SERIAL_PROTOCOLLNPGM("PID Autotune finished! Put the last Kp, Ki and Kd constants from above into Configuration.h"); + pid_tuning_finished = true; + pid_cycle = 0; return; } lcd_update(); diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 4a2e8bf96..547e35b80 100644 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -58,7 +58,9 @@ extern float current_temperature_bed; #endif #ifdef PIDTEMP - extern float Kp,Ki,Kd,Kc; + extern int pid_cycle, pid_number_of_cycles; + extern float Kp,Ki,Kd,Kc,_Kp,_Ki,_Kd; + extern bool pid_tuning_finished; float scalePID_i(float i); float scalePID_d(float d); float unscalePID_i(float i); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index d8b746e7d..7b0e68421 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -106,6 +106,7 @@ int farm_status = 0; unsigned long allert_timer = millis(); bool printer_connected = true; +float pid_temp = DEFAULT_PID_TEMP; bool long_press_active = false; long long_press_timer = millis(); @@ -774,6 +775,47 @@ void lcd_commands() } } + if (lcd_commands_type == LCD_COMMAND_PID_EXTRUDER) { + char cmd1[30]; + unsigned long display_time; //just timer for showing pid finished message on lcd; + if (lcd_commands_step == 0) { + custom_message_type = 3; + custom_message_state = 1; + custom_message = true; + lcdDrawUpdate = 3; + lcd_commands_step = 3; + } + if (lcd_commands_step == 3 && !blocks_queued()) { //PID calibration + strcpy(cmd1, "M303 E0 S"); + strcat(cmd1, ftostr3(pid_temp)); + enquecommand(cmd1); + lcd_setstatuspgm(MSG_PID_RUNNING); + lcd_commands_step = 2; + } + if (lcd_commands_step == 2 && pid_tuning_finished) { //saving to eeprom + pid_tuning_finished = false; + custom_message_state = 0; + lcd_setstatuspgm(MSG_PID_FINISHED); + strcpy(cmd1, "M301 P"); + strcat(cmd1, ftostr32(_Kp)); + strcat(cmd1, " I"); + strcat(cmd1, ftostr32(_Ki)); + strcat(cmd1, " D"); + strcat(cmd1, ftostr32(_Kd)); + enquecommand(cmd1); + enquecommand_P(PSTR("M500")); + display_time = millis(); + lcd_commands_step = 1; + } + if ((lcd_commands_step == 1) && ((millis()- display_time)>2000)) { //calibration finished message + lcd_setstatuspgm(WELCOME_MSG); + custom_message_type = 0; + custom_message = false; + pid_temp = DEFAULT_PID_TEMP; + lcd_commands_step = 0; + lcd_commands_type = 0; + } + } } @@ -1510,6 +1552,25 @@ static void lcd_adjust_bed() END_MENU(); } +void pid_extruder() { + + lcd_implementation_clear(); + lcd.setCursor(1, 0); + lcd_printPGM(MSG_SET_TEMPERATURE); + pid_temp += int(encoderPosition); + if (pid_temp > HEATER_0_MAXTEMP) pid_temp = HEATER_0_MAXTEMP; + if (pid_temp < HEATER_0_MINTEMP) pid_temp = HEATER_0_MINTEMP; + encoderPosition = 0; + lcd.setCursor(1, 2); + lcd.print(ftostr3(pid_temp)); + if (lcd_clicked()) { + lcd_commands_type = LCD_COMMAND_PID_EXTRUDER; + lcd_return_to_status(); + lcd_update(2); + } + +} + void lcd_adjust_z() { int enc_dif = 0; int cursor_pos = 1; @@ -2539,6 +2600,7 @@ MENU_ITEM(function, MSG_CALIBRATE_BED, lcd_mesh_calibration); #endif MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28 W")); MENU_ITEM(submenu, MSG_BED_CORRECTION_MENU, lcd_adjust_bed); + MENU_ITEM(submenu, MSG_PID_EXTRUDER, pid_extruder); MENU_ITEM(submenu, MSG_SHOW_END_STOPS, menu_show_end_stops); MENU_ITEM(gcode, MSG_CALIBRATE_BED_RESET, PSTR("M44")); #ifndef SNMM diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 0334a38b6..4bfd692ab 100644 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -93,6 +93,7 @@ void lcd_mylang(); #define LCD_COMMAND_FARM_MODE_CONFIRM 4 #define LCD_COMMAND_LONG_PAUSE 5 #define LCD_COMMAND_LONG_PAUSE_RESUME 6 + #define LCD_COMMAND_PID_EXTRUDER 7 extern unsigned long lcd_timeoutToStatus; extern int lcd_commands_type; diff --git a/Firmware/ultralcd_implementation_hitachi_HD44780.h b/Firmware/ultralcd_implementation_hitachi_HD44780.h index 25a17cdc3..c59cf4471 100644 --- a/Firmware/ultralcd_implementation_hitachi_HD44780.h +++ b/Firmware/ultralcd_implementation_hitachi_HD44780.h @@ -948,6 +948,17 @@ static void lcd_implementation_status_screen() { lcd.print(lcd_status_message); } + // PID tuning in progress + if (custom_message_type == 3) { + lcd.print(lcd_status_message); + if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0) { + lcd.setCursor(10, 3); + lcd.print(itostr3(pid_cycle)); + + lcd.print('/'); + lcd.print(itostr3left(pid_number_of_cycles)); + } + } } else {