diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 196d5756d..32122b962 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -15,6 +15,9 @@ Please, before you create a new bug report, please make sure you searched in ope **MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1] **MMU upgrade firmware version [e.g. 1.0.6, 1.0.6-RC2, ...] +**SD card or USB/Octoprint** + Please let us know if you print via SD card or USB/Octoprint + **Describe the bug** A clear and concise description of what the bug is. diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index 9d0874421..a4d797746 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -16,8 +16,8 @@ extern uint16_t nPrinterType; extern PGM_P sPrinterName; // Firmware version -#define FW_VERSION "3.9.0-RC3" -#define FW_COMMIT_NR 3401 +#define FW_VERSION "3.9.0" +#define FW_COMMIT_NR 3421 // FW_VERSION_UNKNOWN means this is an unofficial build. // The firmware should only be checked into github with this symbol. #define FW_DEV_VERSION FW_VERSION_UNKNOWN diff --git a/Firmware/Configuration_adv.h b/Firmware/Configuration_adv.h index e086ce388..4d688eb97 100644 --- a/Firmware/Configuration_adv.h +++ b/Firmware/Configuration_adv.h @@ -290,6 +290,7 @@ #define LA_K_DEF 0 // Default K factor (Unit: mm compression per 1mm/s extruder speed) #define LA_K_MAX 10 // Maximum acceptable K factor (exclusive, see notes in planner.cpp:plan_buffer_line) #define LA_LA10_MIN LA_K_MAX // Lin. Advance 1.0 threshold value (inclusive) + //#define LA_FLOWADJ // Adjust LA along with flow/M221 for uniform width //#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility //#define LA_LIVE_K // Allow adjusting K in the Tune menu //#define LA_DEBUG // If enabled, this will generate debug information output over USB. @@ -438,6 +439,10 @@ const unsigned int dropsegments=5; //everything with less than this number of st #undef BED_MINTEMP #undef BED_MAXTEMP #endif +#if TEMP_SENSOR_AMBIENT == 0 + #undef AMBIENT_MINTEMP + #undef AMBIENT_MAXTEMP +#endif #endif //__CONFIGURATION_ADV_H diff --git a/Firmware/Dcodes.cpp b/Firmware/Dcodes.cpp index 1f902c5ee..c77cd96e1 100644 --- a/Firmware/Dcodes.cpp +++ b/Firmware/Dcodes.cpp @@ -1,5 +1,5 @@ #include "Dcodes.h" -//#include "Marlin.h" +#include "Marlin.h" #include "Configuration.h" #include "language.h" #include "cmdqueue.h" @@ -226,9 +226,7 @@ void dcode_0() LOG("D0 - Reset\n"); if (code_seen('B')) //bootloader { - cli(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } else //reset { @@ -252,8 +250,7 @@ void dcode_1() cli(); for (int i = 0; i < 8192; i++) eeprom_write_byte((unsigned char*)i, (unsigned char)0xff); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } /*! @@ -420,8 +417,7 @@ void dcode_5() boot_dst_addr = (uint32_t)address; boot_src_addr = (uint32_t)(&data); bootapp_print_vars(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } while (count) { @@ -467,8 +463,7 @@ void dcode_7() boot_copy_size = (uint16_t)0xc00; boot_src_addr = (uint32_t)0x0003e400; boot_dst_addr = (uint32_t)0x0003f400; - wdt_enable(WDTO_15MS); - while(1); + softReset(); */ } diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 52444337a..a1736e9c2 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -299,7 +299,7 @@ extern float feedrate; extern int feedmultiply; extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in percent) for each extruder individually -extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner +extern float extruder_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner extern float current_position[NUM_AXIS] ; extern float destination[NUM_AXIS] ; extern float min_pos[3]; @@ -334,7 +334,6 @@ extern unsigned long stoptime; extern int bowden_length[4]; extern bool is_usb_printing; extern bool homing_flag; -extern bool temp_cal_active; extern bool loading_flag; extern unsigned int usb_printing_counter; @@ -513,4 +512,6 @@ void load_filament_final_feed(); void marlin_wait_for_click(); void raise_z_above(float target, bool plan=true); +extern "C" void softReset(); + #endif diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index a0ef55910..f1908f213 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -202,8 +202,6 @@ int bowden_length[4] = {385, 385, 385, 385}; bool is_usb_printing = false; bool homing_flag = false; -bool temp_cal_active = false; - unsigned long kicktime = _millis()+100000; unsigned int usb_printing_counter; @@ -650,6 +648,12 @@ void failstats_reset_print() #endif } +void softReset() +{ + cli(); + wdt_enable(WDTO_15MS); + while(1); +} #ifdef MESH_BED_LEVELING @@ -764,6 +768,7 @@ static void factory_reset(char level) } } + softReset(); break; @@ -1014,11 +1019,19 @@ void setup() lcd_splash(); Sound_Init(); // also guarantee "SET_OUTPUT(BEEPER)" + selectedSerialPort = eeprom_read_byte((uint8_t *)EEPROM_SECOND_SERIAL_ACTIVE); + if (selectedSerialPort == 0xFF) selectedSerialPort = 0; + eeprom_update_byte((uint8_t *)EEPROM_SECOND_SERIAL_ACTIVE, selectedSerialPort); + MYSERIAL.begin(BAUDRATE); + fdev_setup_stream(uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); //setup uart out stream + stdout = uartout; + #ifdef W25X20CL bool w25x20cl_success = w25x20cl_init(); + uint8_t optiboot_status = 1; if (w25x20cl_success) { - optiboot_w25x20cl_enter(); + optiboot_status = optiboot_w25x20cl_enter(); #if (LANG_MODE != 0) //secondary language support update_sec_lang_from_external_flash(); #endif //(LANG_MODE != 0) @@ -1040,15 +1053,13 @@ void setup() if ((farm_mode == 0xFF && farm_no == 0) || ((uint16_t)farm_no == 0xFFFF)) farm_mode = false; //if farm_mode has not been stored to eeprom yet and farm number is set to zero or EEPROM is fresh, deactivate farm mode if ((uint16_t)farm_no == 0xFFFF) farm_no = 0; - - selectedSerialPort = eeprom_read_byte((uint8_t*)EEPROM_SECOND_SERIAL_ACTIVE); - if (selectedSerialPort == 0xFF) selectedSerialPort = 0; if (farm_mode) { no_response = true; //we need confirmation by recieving PRUSA thx important_status = 8; prusa_statistics(8); selectedSerialPort = 1; + MYSERIAL.begin(BAUDRATE); #ifdef TMC2130 //increased extruder current (PFW363) tmc2130_current_h[E_AXIS] = 36; @@ -1062,12 +1073,12 @@ void setup() if(!(eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED))) eeprom_update_byte((unsigned char *)EEPROM_FAN_CHECK_ENABLED,true); } - MYSERIAL.begin(BAUDRATE); - fdev_setup_stream(uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); //setup uart out stream #ifndef W25X20CL SERIAL_PROTOCOLLNPGM("start"); -#endif //W25X20CL - stdout = uartout; +#else + if ((optiboot_status != 0) || (selectedSerialPort != 0)) + SERIAL_PROTOCOLLNPGM("start"); +#endif SERIAL_ECHO_START; printf_P(PSTR(" " FW_VERSION_FULL "\n")); @@ -1246,6 +1257,13 @@ void setup() w25x20cl_err_msg(); printf_P(_n("W25X20CL not responding.\n")); } +#ifdef EXTRUDER_ALTFAN_DETECT + SERIAL_ECHORPGM(_n("Extruder fan type: ")); + if (extruder_altfan_detect()) + SERIAL_ECHOLNRPGM(PSTR("ALTFAN")); + else + SERIAL_ECHOLNRPGM(PSTR("NOCTUA")); +#endif //EXTRUDER_ALTFAN_DETECT plan_init(); // Initialize planner; @@ -1332,8 +1350,7 @@ void setup() // Initialize current_position accounting for software endstops to // avoid unexpected initial shifts on the first move clamp_to_software_endstops(current_position); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], - current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); #ifdef FILAMENT_SENSOR fsensor_init(); @@ -1453,8 +1470,7 @@ void setup() if (eeprom_read_byte((uint8_t*)EEPROM_TEMP_CAL_ACTIVE) == 255) { eeprom_write_byte((uint8_t*)EEPROM_TEMP_CAL_ACTIVE, 0); - temp_cal_active = false; - } else temp_cal_active = eeprom_read_byte((uint8_t*)EEPROM_TEMP_CAL_ACTIVE); + } if (eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA) == 255) { //eeprom_write_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0); @@ -1462,7 +1478,6 @@ void setup() int16_t z_shift = 0; for (uint8_t i = 0; i < 5; i++) EEPROM_save_B(EEPROM_PROBE_TEMP_SHIFT + i * 2, &z_shift); eeprom_write_byte((uint8_t*)EEPROM_TEMP_CAL_ACTIVE, 0); - temp_cal_active = false; } if (eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 255) { eeprom_write_byte((uint8_t*)EEPROM_UVLO, 0); @@ -1535,7 +1550,7 @@ void setup() lcd_show_fullscreen_message_and_wait_P(_T(MSG_BABYSTEP_Z_NOT_SET)); lcd_update_enable(true); } - else if (calibration_status() == CALIBRATION_STATUS_CALIBRATED && temp_cal_active == true && calibration_status_pinda() == false) { + else if (calibration_status() == CALIBRATION_STATUS_CALIBRATED && eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() == false) { //lcd_show_fullscreen_message_and_wait_P(_i("Temperature calibration has not been run yet"));////MSG_PINDA_NOT_CALIBRATED c=20 r=4 lcd_update_enable(true); } @@ -1948,7 +1963,7 @@ static void set_bed_level_equation_lsq(double *plane_equation_coefficients) // put the bed at 0 so we don't go below it. current_position[Z_AXIS] = cs.zprobe_zoffset; // in the lsq we reach here after raising the extruder due to the loop structure - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } #else // not AUTO_BED_LEVELING_GRID @@ -1976,7 +1991,7 @@ static void set_bed_level_equation_3pts(float z_at_pt_1, float z_at_pt_2, float // put the bed at 0 so we don't go below it. current_position[Z_AXIS] = cs.zprobe_zoffset; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } @@ -2008,7 +2023,7 @@ static void run_z_probe() { current_position[Z_AXIS] = st_get_position_mm(Z_AXIS); // make sure the planner knows where we are as it may be a bit different than we last said to move to - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } static void do_blocking_move_to(float x, float y, float z) { @@ -2129,7 +2144,7 @@ void raise_z_above(float target, bool plan) if (axis_known_position[Z_AXIS] || z_min_endstop) { // current position is known or very low, it's safe to raise Z - if(plan) plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS], active_extruder); + if(plan) plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS]); return; } @@ -2142,15 +2157,14 @@ void raise_z_above(float target, bool plan) #ifdef TMC2130 tmc2130_home_enter(Z_AXIS_MASK); #endif //TMC2130 - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); st_synchronize(); #ifdef TMC2130 if (endstop_z_hit_on_purpose()) { // not necessarily exact, but will avoid further vertical moves current_position[Z_AXIS] = max_pos[Z_AXIS]; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], - current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } tmc2130_home_exit(); #endif //TMC2130 @@ -2168,22 +2182,22 @@ bool calibrate_z_auto() int axis_up_dir = -home_dir(Z_AXIS); tmc2130_home_enter(Z_AXIS_MASK); current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); set_destination_to_current(); destination[Z_AXIS] += (1.1 * max_length(Z_AXIS) * axis_up_dir); feedrate = homing_feedrate[Z_AXIS]; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate / 60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate / 60); st_synchronize(); // current_position[axis] = 0; - // plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + // plan_set_position_curposXYZE(); tmc2130_home_exit(); enable_endstops(false); current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); set_destination_to_current(); destination[Z_AXIS] += 10 * axis_up_dir; //10mm up feedrate = homing_feedrate[Z_AXIS] / 2; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate / 60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate / 60); st_synchronize(); enable_endstops(endstops_enabled); if (PRINTER_TYPE == PRINTER_MK3) { @@ -2192,7 +2206,7 @@ bool calibrate_z_auto() else { current_position[Z_AXIS] = Z_MAX_POS + 9.0; } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); return true; } #endif //TMC2130 @@ -2203,9 +2217,9 @@ static void check_Z_crash(void) if (READ(Z_TMC2130_DIAG) != 0) { //Z crash FORCE_HIGH_POWER_END; current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); current_position[Z_AXIS] += MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS], active_extruder); + plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS]); st_synchronize(); kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); } @@ -2235,24 +2249,24 @@ void homeaxis(int axis, uint8_t cnt) // and the following movement to endstop has a chance to achieve the required velocity // for the stall guard to work. current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); set_destination_to_current(); // destination[axis] = 11.f; destination[axis] = -3.f * axis_home_dir; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); // Move away from the possible collision with opposite endstop with the collision detection disabled. endstops_hit_on_purpose(); enable_endstops(false); current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); destination[axis] = 1. * axis_home_dir; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); // Now continue to move up to the left end stop with the collision detection enabled. enable_endstops(true); destination[axis] = 1.1 * axis_home_dir * max_length(axis); - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); for (uint8_t i = 0; i < cnt; i++) { @@ -2260,9 +2274,9 @@ void homeaxis(int axis, uint8_t cnt) endstops_hit_on_purpose(); enable_endstops(false); current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); destination[axis] = -10.f * axis_home_dir; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); endstops_hit_on_purpose(); // Now move left up to the collision, this time with a repeatable velocity. @@ -2273,7 +2287,7 @@ void homeaxis(int axis, uint8_t cnt) #else //TMC2130 feedrate = homing_feedrate[axis] / 2; #endif //TMC2130 - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); #ifdef TMC2130 uint16_t mscnt = tmc2130_rd_MSCNT(axis); @@ -2307,10 +2321,10 @@ void homeaxis(int axis, uint8_t cnt) float dist = - axis_home_dir * 0.01f * 64; #endif //TMC2130 current_position[axis] -= dist; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); current_position[axis] += dist; destination[axis] = current_position[axis]; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], 0.5f*feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(0.5f*feedrate/60); st_synchronize(); feedrate = 0.0; @@ -2322,22 +2336,22 @@ void homeaxis(int axis, uint8_t cnt) #endif int axis_home_dir = home_dir(axis); current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); destination[axis] = 1.5 * max_length(axis) * axis_home_dir; feedrate = homing_feedrate[axis]; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); #ifdef TMC2130 check_Z_crash(); #endif //TMC2130 current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); destination[axis] = -home_retract_mm(axis) * axis_home_dir; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); destination[axis] = 2*home_retract_mm(axis) * axis_home_dir; feedrate = homing_feedrate[axis]/2 ; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); st_synchronize(); #ifdef TMC2130 check_Z_crash(); @@ -2360,7 +2374,7 @@ void home_xy() set_destination_to_current(); homeaxis(X_AXIS); homeaxis(Y_AXIS); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); endstops_hit_on_purpose(); } @@ -2383,7 +2397,7 @@ void refresh_cmd_timeout(void) retracted[active_extruder]=true; prepare_move(); current_position[Z_AXIS]-=cs.retract_zlift; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); prepare_move(); feedrate = oldFeedrate; } else if(!retracting && retracted[active_extruder]) { @@ -2392,7 +2406,7 @@ void refresh_cmd_timeout(void) destination[Z_AXIS]=current_position[Z_AXIS]; destination[E_AXIS]=current_position[E_AXIS]; current_position[Z_AXIS]+=cs.retract_zlift; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); current_position[E_AXIS]-=(swapretract?(retract_length_swap+retract_recover_length_swap):(cs.retract_length+cs.retract_recover_length))*float(extrudemultiply)*0.01f; plan_set_e_position(current_position[E_AXIS]); float oldFeedrate = feedrate; @@ -2595,7 +2609,7 @@ static void gcode_G28(bool home_x_axis, long home_x_value, bool home_y_axis, lon int x_axis_home_dir = home_dir(X_AXIS); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); destination[X_AXIS] = 1.5 * max_length(X_AXIS) * x_axis_home_dir;destination[Y_AXIS] = 1.5 * max_length(Y_AXIS) * home_dir(Y_AXIS); feedrate = homing_feedrate[X_AXIS]; if(homing_feedrate[Y_AXIS]= 0) @@ -2984,7 +2998,7 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level) clean_up_after_endstop_move(l_feedmultiply); // Print head up. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); st_synchronize(); // if (result >= 0) babystep_apply(); #endif //HEATBED_V2 @@ -3097,18 +3111,18 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float //Retract E current_position[E_AXIS] += e_shift; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_RFEED, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_RFEED); st_synchronize(); //Lift Z current_position[Z_AXIS] += z_shift; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_ZFEED, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_ZFEED); st_synchronize(); //Move XY to side current_position[X_AXIS] = x_position; current_position[Y_AXIS] = y_position; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_XYFEED, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_XYFEED); st_synchronize(); //Beep, manage nozzle heater and wait for user to start unload filament @@ -3133,7 +3147,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float lcd_set_cursor(0, 2); lcd_puts_P(_T(MSG_PLEASE_WAIT)); current_position[X_AXIS] -= 100; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_XYFEED, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_XYFEED); st_synchronize(); lcd_show_fullscreen_message_and_wait_P(_i("Please open idler and remove filament manually."));////MSG_CHECK_IDLER c=20 r=4 } @@ -3170,7 +3184,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float if (!automatic) { current_position[E_AXIS] += FILAMENTCHANGE_RECFEED; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_EXFEED, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_EXFEED); } //Move XY back @@ -3228,12 +3242,12 @@ void gcode_M701() lcd_setstatuspgm(_T(MSG_LOADING_FILAMENT)); current_position[E_AXIS] += 40; - plan_buffer_line_curposXYZE(400 / 60, active_extruder); //fast sequence + plan_buffer_line_curposXYZE(400 / 60); //fast sequence st_synchronize(); raise_z_above(MIN_Z_FOR_LOAD, false); current_position[E_AXIS] += 30; - plan_buffer_line_curposXYZE(400 / 60, active_extruder); //fast sequence + plan_buffer_line_curposXYZE(400 / 60); //fast sequence load_filament_final_feed(); //slow sequence st_synchronize(); @@ -3279,37 +3293,24 @@ void gcode_M701() */ static void gcode_PRUSA_SN() { - if (farm_mode) { - selectedSerialPort = 0; - putchar(';'); - putchar('S'); - int numbersRead = 0; - ShortTimer timeout; - timeout.start(); + uint8_t selectedSerialPort_bak = selectedSerialPort; + char SN[20]; + selectedSerialPort = 0; + SERIAL_ECHOLNRPGM(PSTR(";S")); + uint8_t numbersRead = 0; + ShortTimer timeout; + timeout.start(); - while (numbersRead < 19) { - while (MSerial.available() > 0) { - uint8_t serial_char = MSerial.read(); - selectedSerialPort = 1; - putchar(serial_char); - numbersRead++; - selectedSerialPort = 0; - } - if (timeout.expired(100u)) break; + while (numbersRead < (sizeof(SN) - 1)) { + if (MSerial.available() > 0) { + SN[numbersRead] = MSerial.read(); + numbersRead++; } - selectedSerialPort = 1; - putchar('\n'); -#if 0 - for (int b = 0; b < 3; b++) { - _tone(BEEPER, 110); - _delay(50); - _noTone(BEEPER); - _delay(50); - } -#endif - } else { - puts_P(_N("Not in farm mode.")); + if (timeout.expired(100u)) break; } + SN[numbersRead] = 0; + selectedSerialPort = selectedSerialPort_bak; + SERIAL_ECHOLN(SN); } //! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors //! at the TACH_1 pin, which causes bad detection of print fan speed. @@ -3399,8 +3400,7 @@ static void gcode_G92() current_position[E_AXIS] = values[E_AXIS]; // Set all at once - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], - current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } } @@ -3807,9 +3807,7 @@ void process_commands() #if (defined(WATCHDOG) && (MOTHERBOARD == BOARD_EINSY_1_0a)) boot_app_magic = BOOT_APP_MAGIC; boot_app_flags = BOOT_APP_FLG_RUN; - wdt_enable(WDTO_15MS); - cli(); - while(1); + softReset(); #else //WATCHDOG asm volatile("jmp 0x3E000"); #endif //WATCHDOG @@ -4277,6 +4275,14 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) #endif //FWRETRACT + /*! + ### G21 - Sets Units to Millimters G21: Set Units to Millimeters + Units are in millimeters. Prusa doesn't support inches. + */ + case 21: + break; //Doing nothing. This is just to prevent serial UNKOWN warnings. + + /*! ### G28 - Home all Axes one at a time G28: Move to Origin (Home) Using `G28` without any parameters will perfom homing of all axes AND mesh bed leveling, while `G28 W` will just home all axes (no mesh bed leveling). @@ -4353,7 +4359,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) current_position[X_AXIS] = uncorrected_position.x; current_position[Y_AXIS] = uncorrected_position.y; current_position[Z_AXIS] = uncorrected_position.z; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); int l_feedmultiply = setup_for_endstop_move(); feedrate = homing_feedrate[Z_AXIS]; @@ -4467,7 +4473,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) apply_rotation_xyz(plan_bed_level_matrix, x_tmp, y_tmp, z_tmp); //Apply the correction sending the probe offset current_position[Z_AXIS] = z_tmp - real_z + current_position[Z_AXIS]; //The difference is added to current position and sent to planner. - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } break; #ifndef Z_PROBE_SLED @@ -4555,11 +4561,15 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) /*! ### G76 - PINDA probe temperature calibration G76: PINDA probe temperature calibration This G-code is used to calibrate the temperature drift of the PINDA (inductive Sensor). - + The PINDAv2 sensor has a built-in thermistor which has the advantage that the calibration can be done once for all materials. The Original i3 Prusa MK2/s uses PINDAv1 and this calibration improves the temperature drift, but not as good as the PINDAv2. + superPINDA sensor has internal temperature compensation and no thermistor output. There is no point of doing temperature calibration in such case. + If PINDA_THERMISTOR and DETECT_SUPERPINDA is defined during compilation, calibration is skipped with serial message "No PINDA thermistor". + This can be caused also if PINDA thermistor connection is broken or PINDA temperature is lower than PINDA_MINTEMP. + #### Example ``` @@ -4574,154 +4584,155 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) case 76: { #ifdef PINDA_THERMISTOR - if (true) - { + if (!has_temperature_compensation()) + { + SERIAL_ECHOLNPGM("No PINDA thermistor"); + break; + } - if (calibration_status() >= CALIBRATION_STATUS_XYZ_CALIBRATION) { - //we need to know accurate position of first calibration point - //if xyz calibration was not performed yet, interrupt temperature calibration and inform user that xyz cal. is needed - lcd_show_fullscreen_message_and_wait_P(_i("Please run XYZ calibration first.")); - break; - } - - if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) - { - // We don't know where we are! HOME! - // Push the commands to the front of the message queue in the reverse order! - // There shall be always enough space reserved for these commands. - repeatcommand_front(); // repeat G76 with all its parameters - enquecommand_front_P((PSTR("G28 W0"))); - break; - } - lcd_show_fullscreen_message_and_wait_P(_i("Stable ambient temperature 21-26C is needed a rigid stand is required."));////MSG_TEMP_CAL_WARNING c=20 r=4 - bool result = lcd_show_fullscreen_message_yes_no_and_wait_P(_T(MSG_STEEL_SHEET_CHECK), false, false); - - if (result) - { - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[Z_AXIS] = 50; - current_position[Y_AXIS] = 180; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - st_synchronize(); - lcd_show_fullscreen_message_and_wait_P(_T(MSG_REMOVE_STEEL_SHEET)); - current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + 1); - current_position[X_AXIS] = pgm_read_float(bed_ref_points_4); - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - st_synchronize(); - gcode_G28(false, false, true); + if (calibration_status() >= CALIBRATION_STATUS_XYZ_CALIBRATION) { + //we need to know accurate position of first calibration point + //if xyz calibration was not performed yet, interrupt temperature calibration and inform user that xyz cal. is needed + lcd_show_fullscreen_message_and_wait_P(_i("Please run XYZ calibration first.")); + break; + } - } - if ((current_temperature_pinda > 35) && (farm_mode == false)) { - //waiting for PIDNA probe to cool down in case that we are not in farm mode - current_position[Z_AXIS] = 100; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - if (lcd_wait_for_pinda(35) == false) { //waiting for PINDA probe to cool, if this takes more then time expected, temp. cal. fails - lcd_temp_cal_show_result(false); - break; - } - } - lcd_update_enable(true); - KEEPALIVE_STATE(NOT_BUSY); //no need to print busy messages as we print current temperatures periodicaly - SERIAL_ECHOLNPGM("PINDA probe calibration start"); + if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) + { + // We don't know where we are! HOME! + // Push the commands to the front of the message queue in the reverse order! + // There shall be always enough space reserved for these commands. + repeatcommand_front(); // repeat G76 with all its parameters + enquecommand_front_P((PSTR("G28 W0"))); + break; + } + lcd_show_fullscreen_message_and_wait_P(_i("Stable ambient temperature 21-26C is needed a rigid stand is required."));////MSG_TEMP_CAL_WARNING c=20 r=4 + bool result = lcd_show_fullscreen_message_yes_no_and_wait_P(_T(MSG_STEEL_SHEET_CHECK), false, false); - float zero_z; - int z_shift = 0; //unit: steps - float start_temp = 5 * (int)(current_temperature_pinda / 5); - if (start_temp < 35) start_temp = 35; - if (start_temp < current_temperature_pinda) start_temp += 5; - printf_P(_N("start temperature: %.1f\n"), start_temp); + if (result) + { + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[Z_AXIS] = 50; + current_position[Y_AXIS] = 180; + plan_buffer_line_curposXYZE(3000 / 60); + st_synchronize(); + lcd_show_fullscreen_message_and_wait_P(_T(MSG_REMOVE_STEEL_SHEET)); + current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + 1); + current_position[X_AXIS] = pgm_read_float(bed_ref_points_4); + plan_buffer_line_curposXYZE(3000 / 60); + st_synchronize(); + gcode_G28(false, false, true); + + } + if ((current_temperature_pinda > 35) && (farm_mode == false)) { + //waiting for PIDNA probe to cool down in case that we are not in farm mode + current_position[Z_AXIS] = 100; + plan_buffer_line_curposXYZE(3000 / 60); + if (lcd_wait_for_pinda(35) == false) { //waiting for PINDA probe to cool, if this takes more then time expected, temp. cal. fails + lcd_temp_cal_show_result(false); + break; + } + } + lcd_update_enable(true); + KEEPALIVE_STATE(NOT_BUSY); //no need to print busy messages as we print current temperatures periodicaly + SERIAL_ECHOLNPGM("PINDA probe calibration start"); + + float zero_z; + int z_shift = 0; //unit: steps + float start_temp = 5 * (int)(current_temperature_pinda / 5); + if (start_temp < 35) start_temp = 35; + if (start_temp < current_temperature_pinda) start_temp += 5; + printf_P(_N("start temperature: %.1f\n"), start_temp); // setTargetHotend(200, 0); - setTargetBed(70 + (start_temp - 30)); + setTargetBed(70 + (start_temp - 30)); - custom_message_type = CustomMsg::TempCal; - custom_message_state = 1; - lcd_setstatuspgm(_T(MSG_TEMP_CALIBRATION)); - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[X_AXIS] = PINDA_PREHEAT_X; - current_position[Y_AXIS] = PINDA_PREHEAT_Y; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[Z_AXIS] = PINDA_PREHEAT_Z; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - st_synchronize(); + custom_message_type = CustomMsg::TempCal; + custom_message_state = 1; + lcd_setstatuspgm(_T(MSG_TEMP_CALIBRATION)); + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[X_AXIS] = PINDA_PREHEAT_X; + current_position[Y_AXIS] = PINDA_PREHEAT_Y; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[Z_AXIS] = PINDA_PREHEAT_Z; + plan_buffer_line_curposXYZE(3000 / 60); + st_synchronize(); - while (current_temperature_pinda < start_temp) - { - delay_keep_alive(1000); - serialecho_temperatures(); - } + while (current_temperature_pinda < start_temp) + { + delay_keep_alive(1000); + serialecho_temperatures(); + } - eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0); //invalidate temp. calibration in case that in will be aborted during the calibration process + eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0); //invalidate temp. calibration in case that in will be aborted during the calibration process - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[X_AXIS] = pgm_read_float(bed_ref_points_4); - current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + 1); - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - st_synchronize(); + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[X_AXIS] = pgm_read_float(bed_ref_points_4); + current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + 1); + plan_buffer_line_curposXYZE(3000 / 60); + st_synchronize(); - bool find_z_result = find_bed_induction_sensor_point_z(-1.f); - if (find_z_result == false) { - lcd_temp_cal_show_result(find_z_result); - break; - } - zero_z = current_position[Z_AXIS]; + bool find_z_result = find_bed_induction_sensor_point_z(-1.f); + if (find_z_result == false) { + lcd_temp_cal_show_result(find_z_result); + break; + } + zero_z = current_position[Z_AXIS]; - printf_P(_N("\nZERO: %.3f\n"), current_position[Z_AXIS]); + printf_P(_N("\nZERO: %.3f\n"), current_position[Z_AXIS]); - int i = -1; for (; i < 5; i++) - { - float temp = (40 + i * 5); - printf_P(_N("\nStep: %d/6 (skipped)\nPINDA temperature: %d Z shift (mm):0\n"), i + 2, (40 + i*5)); - if (i >= 0) EEPROM_save_B(EEPROM_PROBE_TEMP_SHIFT + i * 2, &z_shift); - if (start_temp <= temp) break; - } + int i = -1; for (; i < 5; i++) + { + float temp = (40 + i * 5); + printf_P(_N("\nStep: %d/6 (skipped)\nPINDA temperature: %d Z shift (mm):0\n"), i + 2, (40 + i*5)); + if (i >= 0) EEPROM_save_B(EEPROM_PROBE_TEMP_SHIFT + i * 2, &z_shift); + if (start_temp <= temp) break; + } - for (i++; i < 5; i++) - { - float temp = (40 + i * 5); - printf_P(_N("\nStep: %d/6\n"), i + 2); - custom_message_state = i + 2; - setTargetBed(50 + 10 * (temp - 30) / 5); + for (i++; i < 5; i++) + { + float temp = (40 + i * 5); + printf_P(_N("\nStep: %d/6\n"), i + 2); + custom_message_state = i + 2; + setTargetBed(50 + 10 * (temp - 30) / 5); // setTargetHotend(255, 0); - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[X_AXIS] = PINDA_PREHEAT_X; - current_position[Y_AXIS] = PINDA_PREHEAT_Y; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[Z_AXIS] = PINDA_PREHEAT_Z; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - st_synchronize(); - while (current_temperature_pinda < temp) - { - delay_keep_alive(1000); - serialecho_temperatures(); - } - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - current_position[X_AXIS] = pgm_read_float(bed_ref_points_4); - current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + 1); - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); - st_synchronize(); - find_z_result = find_bed_induction_sensor_point_z(-1.f); - if (find_z_result == false) { - lcd_temp_cal_show_result(find_z_result); - break; - } - z_shift = (int)((current_position[Z_AXIS] - zero_z)*cs.axis_steps_per_unit[Z_AXIS]); + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[X_AXIS] = PINDA_PREHEAT_X; + current_position[Y_AXIS] = PINDA_PREHEAT_Y; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[Z_AXIS] = PINDA_PREHEAT_Z; + plan_buffer_line_curposXYZE(3000 / 60); + st_synchronize(); + while (current_temperature_pinda < temp) + { + delay_keep_alive(1000); + serialecho_temperatures(); + } + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(3000 / 60); + current_position[X_AXIS] = pgm_read_float(bed_ref_points_4); + current_position[Y_AXIS] = pgm_read_float(bed_ref_points_4 + 1); + plan_buffer_line_curposXYZE(3000 / 60); + st_synchronize(); + find_z_result = find_bed_induction_sensor_point_z(-1.f); + if (find_z_result == false) { + lcd_temp_cal_show_result(find_z_result); + break; + } + z_shift = (int)((current_position[Z_AXIS] - zero_z)*cs.axis_steps_per_unit[Z_AXIS]); - printf_P(_N("\nPINDA temperature: %.1f Z shift (mm): %.3f"), current_temperature_pinda, current_position[Z_AXIS] - zero_z); + printf_P(_N("\nPINDA temperature: %.1f Z shift (mm): %.3f"), current_temperature_pinda, current_position[Z_AXIS] - zero_z); - EEPROM_save_B(EEPROM_PROBE_TEMP_SHIFT + i * 2, &z_shift); + EEPROM_save_B(EEPROM_PROBE_TEMP_SHIFT + i * 2, &z_shift); - } - lcd_temp_cal_show_result(true); + } + lcd_temp_cal_show_result(true); - break; - } -#endif //PINDA_THERMISTOR +#else //PINDA_THERMISTOR setTargetBed(PINDA_MIN_T); float zero_z; @@ -4743,7 +4754,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) current_position[X_AXIS] = PINDA_PREHEAT_X; current_position[Y_AXIS] = PINDA_PREHEAT_Y; current_position[Z_AXIS] = PINDA_PREHEAT_Z; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); + plan_buffer_line_curposXYZE(3000 / 60); st_synchronize(); while (abs(degBed() - PINDA_MIN_T) > 1) { @@ -4759,11 +4770,11 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0); //invalidate temp. calibration in case that in will be aborted during the calibration process current_position[Z_AXIS] = 5; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); + plan_buffer_line_curposXYZE(3000 / 60); current_position[X_AXIS] = BED_X0; current_position[Y_AXIS] = BED_Y0; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); + plan_buffer_line_curposXYZE(3000 / 60); st_synchronize(); find_bed_induction_sensor_point_z(-1.f); @@ -4780,7 +4791,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) current_position[X_AXIS] = PINDA_PREHEAT_X; current_position[Y_AXIS] = PINDA_PREHEAT_Y; current_position[Z_AXIS] = PINDA_PREHEAT_Z; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); + plan_buffer_line_curposXYZE(3000 / 60); st_synchronize(); while (degBed() < t_c) { delay_keep_alive(1000); @@ -4791,10 +4802,10 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) serialecho_temperatures(); } current_position[Z_AXIS] = 5; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); + plan_buffer_line_curposXYZE(3000 / 60); current_position[X_AXIS] = BED_X0; current_position[Y_AXIS] = BED_Y0; - plan_buffer_line_curposXYZE(3000 / 60, active_extruder); + plan_buffer_line_curposXYZE(3000 / 60); st_synchronize(); find_bed_induction_sensor_point_z(-1.f); z_shift = (int)((current_position[Z_AXIS] - zero_z)*cs.axis_steps_per_unit[Z_AXIS]); @@ -4817,13 +4828,12 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) disable_e2(); setTargetBed(0); //set bed target temperature back to 0 lcd_show_fullscreen_message_and_wait_P(_T(MSG_TEMP_CALIBRATION_DONE)); - temp_cal_active = true; eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, 1); lcd_update_enable(true); lcd_update(2); - +#endif //PINDA_THERMISTOR } break; @@ -4937,7 +4947,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) // Cycle through all points and probe them // First move up. During this first movement, the babystepping will be reverted. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); // The move to the first calibration point. current_position[X_AXIS] = BED_X0; current_position[Y_AXIS] = BED_Y0; @@ -4952,7 +4962,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); #endif //SUPPORT_VERBOSITY - plan_buffer_line_curposXYZE(homing_feedrate[X_AXIS] / 30, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[X_AXIS] / 30); // Wait until the move is finished. st_synchronize(); @@ -4967,7 +4977,6 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) } #endif // SUPPORT_VERBOSITY int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 - const char *kill_message = NULL; while (mesh_point != nMeasPoints * nMeasPoints) { // Get coords of a measuring point. uint8_t ix = mesh_point % nMeasPoints; // from 0 to MESH_NUM_X_POINTS - 1 @@ -5004,7 +5013,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) if((ix == 0) && (iy == 0)) current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; else current_position[Z_AXIS] += 2.f / nMeasPoints; //use relative movement from Z coordinate where PINDa triggered on previous point. This makes calibration faster. float init_z_bckp = current_position[Z_AXIS]; - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); // Move to XY position of the sensor point. @@ -5025,7 +5034,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) #endif // SUPPORT_VERBOSITY //printf_P(PSTR("after clamping: [%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); - plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); st_synchronize(); // Go down until endstop is hit @@ -5037,7 +5046,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) if (init_z_bckp - current_position[Z_AXIS] < 0.1f) { //broken cable or initial Z coordinate too low. Go to MESH_HOME_Z_SEARCH and repeat last step (z-probe) again to distinguish between these two cases. //printf_P(PSTR("Another attempt! Current Z position: %f\n"), current_position[Z_AXIS]); current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point @@ -5092,7 +5101,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) MYSERIAL.print(current_position[Z_AXIS], 5); } #endif // SUPPORT_VERBOSITY - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); st_synchronize(); if (mesh_point != nMeasPoints * nMeasPoints) { Sound_MakeSound(e_SOUND_TYPE_StandardAlert); @@ -5109,14 +5118,14 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) // ~ Z-homing (can not be used "G28", because X & Y-homing would have been done before (Z-homing)) bState=enable_z_endstop(false); current_position[Z_AXIS] -= 1; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); st_synchronize(); enable_z_endstop(true); #ifdef TMC2130 tmc2130_home_enter(Z_AXIS_MASK); #endif // TMC2130 current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); st_synchronize(); #ifdef TMC2130 tmc2130_home_exit(); @@ -5244,9 +5253,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) go_home_with_z_lift(); // SERIAL_ECHOLNPGM("Go home finished"); //unretract (after PINDA preheat retraction) - if (degHotend(active_extruder) > EXTRUDE_MINTEMP && temp_cal_active == true && calibration_status_pinda() == true && target_temperature_bed >= 50) { + if ((degHotend(active_extruder) > EXTRUDE_MINTEMP) && eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() && (target_temperature_bed >= 50)) { current_position[E_AXIS] += default_retraction; - plan_buffer_line_curposXYZE(400, active_extruder); + plan_buffer_line_curposXYZE(400); } KEEPALIVE_STATE(NOT_BUSY); // Restore custom message state @@ -5268,7 +5277,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) if (mbl.active) { SERIAL_PROTOCOLPGM("Num X,Y: "); SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); + SERIAL_PROTOCOL(','); SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); SERIAL_PROTOCOLPGM("\nZ search height: "); SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); @@ -5278,7 +5287,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) SERIAL_PROTOCOLPGM(" "); SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); } - SERIAL_PROTOCOLPGM("\n"); + SERIAL_PROTOCOLLN(); } } else @@ -6286,7 +6295,7 @@ Sigma_Exit: for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) { SERIAL_PROTOCOLPGM(" T"); SERIAL_PROTOCOL(cur_extruder); - SERIAL_PROTOCOLPGM(":"); + SERIAL_PROTOCOL(':'); SERIAL_PROTOCOL_F(degHotend(cur_extruder),1); SERIAL_PROTOCOLPGM(" /"); SERIAL_PROTOCOL_F(degTargetHotend(cur_extruder),1); @@ -7291,17 +7300,26 @@ Sigma_Exit: */ case 220: // M220 S- set speed factor override percentage { - if (code_seen('B')) //backup current speed factor - { - saved_feedmultiply_mm = feedmultiply; - } - if(code_seen('S')) - { - feedmultiply = code_value() ; - } - if (code_seen('R')) { //restore previous feedmultiply - feedmultiply = saved_feedmultiply_mm; - } + bool codesWereSeen = false; + if (code_seen('B')) //backup current speed factor + { + saved_feedmultiply_mm = feedmultiply; + codesWereSeen = true; + } + if (code_seen('S')) + { + feedmultiply = code_value(); + codesWereSeen = true; + } + if (code_seen('R')) //restore previous feedmultiply + { + feedmultiply = saved_feedmultiply_mm; + codesWereSeen = true; + } + if (!codesWereSeen) + { + printf_P(PSTR("%i%%\n"), feedmultiply); + } } break; @@ -7317,23 +7335,26 @@ Sigma_Exit: */ case 221: // M221 S- set extrude factor override percentage { - if(code_seen('S')) - { - int tmp_code = code_value(); - if (code_seen('T')) + if (code_seen('S')) { - uint8_t extruder; - if(setTargetedHotend(221, extruder)){ - break; - } - extruder_multiply[extruder] = tmp_code; + int tmp_code = code_value(); + if (code_seen('T')) + { + uint8_t extruder; + if (setTargetedHotend(221, extruder)) + break; + extruder_multiply[extruder] = tmp_code; + } + else + { + extrudemultiply = tmp_code ; + } } else { - extrudemultiply = tmp_code ; + printf_P(PSTR("%i%%\n"), extrudemultiply); } - } - calculate_extruder_multipliers(); + calculate_extruder_multipliers(); } break; @@ -7971,9 +7992,8 @@ Sigma_Exit: { SERIAL_PROTOCOLPGM("P:"); SERIAL_PROTOCOL_F(current_temperature_pinda, 1); - SERIAL_PROTOCOLPGM("/"); - SERIAL_PROTOCOL(set_target_pinda); - SERIAL_PROTOCOLLN(""); + SERIAL_PROTOCOL('/'); + SERIAL_PROTOCOLLN(set_target_pinda); codenum = _millis(); } manage_heater(); @@ -8562,7 +8582,7 @@ Sigma_Exit: break; /*! - ### M999 - Restart after being stopped M999: Restart after being stopped by error + ### M999 - Restart after being stopped M999: Restart after being stopped by error @todo Usually doesn't work. Should be fixed or removed. Most of the time, if `Stopped` it set, the print fails and is unrecoverable. */ case 999: @@ -8722,7 +8742,7 @@ Sigma_Exit: #else //SNMM if (tmp_extruder >= EXTRUDERS) { SERIAL_ECHO_START; - SERIAL_ECHOPGM("T"); + SERIAL_ECHO('T'); SERIAL_PROTOCOLLN((int)tmp_extruder); SERIAL_ECHOLNRPGM(_n("Invalid extruder"));////MSG_INVALID_EXTRUDER } @@ -8752,7 +8772,7 @@ Sigma_Exit: } // Set the new active extruder and position active_extruder = tmp_extruder; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); // Move to the old position if 'F' was in the parameters if (make_move && Stopped == false) { prepare_move(); @@ -9302,13 +9322,13 @@ void prepare_move() // Do not use feedmultiply for E or Z only moves if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) { - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + plan_buffer_line_destinationXYZE(feedrate/60); } else { #ifdef MESH_BED_LEVELING mesh_plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply*(1./(60.f*100.f)), active_extruder); #else - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply*(1./(60.f*100.f)), active_extruder); + plan_buffer_line_destinationXYZE(feedrate*feedmultiply*(1./(60.f*100.f))); #endif } @@ -9442,7 +9462,32 @@ static void handleSafetyTimer() } #endif //SAFETYTIMER -#define FS_CHECK_COUNT 250 +#ifdef IR_SENSOR_ANALOG +#define FS_CHECK_COUNT 16 +/// Switching mechanism of the fsensor type. +/// Called from 2 spots which have a very similar behavior +/// 1: ClFsensorPCB::_Old -> ClFsensorPCB::_Rev04 and print _i("FS v0.4 or newer") +/// 2: ClFsensorPCB::_Rev04 -> oFsensorPCB=ClFsensorPCB::_Old and print _i("FS v0.3 or older") +void manage_inactivity_IR_ANALOG_Check(uint16_t &nFSCheckCount, ClFsensorPCB isVersion, ClFsensorPCB switchTo, const char *statusLineTxt_P) { + bool bTemp = (!CHECK_ALL_HEATERS); + bTemp = bTemp && (menu_menu == lcd_status_screen); + bTemp = bTemp && ((oFsensorPCB == isVersion) || (oFsensorPCB == ClFsensorPCB::_Undef)); + bTemp = bTemp && fsensor_enabled; + if (bTemp) { + nFSCheckCount++; + if (nFSCheckCount > FS_CHECK_COUNT) { + nFSCheckCount = 0; // not necessary + oFsensorPCB = switchTo; + eeprom_update_byte((uint8_t *)EEPROM_FSENSOR_PCB, (uint8_t)oFsensorPCB); + printf_IRSensorAnalogBoardChange(); + lcd_setstatuspgm(statusLineTxt_P); + } + } else { + nFSCheckCount = 0; + } +} +#endif + void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h { #ifdef FILAMENT_SENSOR @@ -9455,15 +9500,15 @@ static uint16_t nFSCheckCount=0; { //-// if (mcode_in_progress != 600) //M600 not in progress #ifdef PAT9125 - bInhibitFlag=(menu_menu==lcd_menu_extruder_info); // Support::ExtruderInfo menu active + bInhibitFlag=(menu_menu==lcd_menu_extruder_info); // Support::ExtruderInfo menu active #endif // PAT9125 #ifdef IR_SENSOR - bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active + bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active #ifdef IR_SENSOR_ANALOG - bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Settings::HWsetup::FSdetect menu active + bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Settings::HWsetup::FSdetect menu active #endif // IR_SENSOR_ANALOG #endif // IR_SENSOR - if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active + if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active { if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && ! eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE)) { @@ -9474,7 +9519,7 @@ static uint16_t nFSCheckCount=0; if( current_voltage_raw_IR > maxVolt )maxVolt = current_voltage_raw_IR; if( current_voltage_raw_IR < minVolt )minVolt = current_voltage_raw_IR; -#if 0 +#if 0 // Start: IR Sensor debug info { // debug print static uint16_t lastVolt = ~0U; if( current_voltage_raw_IR != lastVolt ){ @@ -9482,38 +9527,29 @@ static uint16_t nFSCheckCount=0; lastVolt = current_voltage_raw_IR; } } -#endif - // the trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage - // to be detected as the new fsensor - // We can either fake it by extending the detection window to a looooong time - // or do some other countermeasures +#endif // End: IR Sensor debug info + //! The trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage + //! to be detected as the new fsensor + //! We can either fake it by extending the detection window to a looooong time + //! or do some other countermeasures - // what we want to detect: - // if minvolt gets below ~0.6V, it means there is an old fsensor - // if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor - // So I'm waiting for a situation, when minVolt gets to range <0, 0.7> and maxVolt gets into range <4.4, 5> - // If and only if minVolt is in range <0.6, 0.7> and maxVolt is in range <4.4, 4.5>, I'm considering a situation with the new fsensor - // otherwise, I don't care - - if( minVolt >= Voltage2Raw(0.3F) && minVolt <= Voltage2Raw(0.5F) - && maxVolt >= Voltage2Raw(4.2F) && maxVolt <= Voltage2Raw(4.6F) + //! what we want to detect: + //! if minvolt gets below ~0.3V, it means there is an old fsensor + //! if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor + //! So I'm waiting for a situation, when minVolt gets to range <0, 1.5> and maxVolt gets into range <3.0, 5> + //! If and only if minVolt is in range <0.3, 1.5> and maxVolt is in range <3.0, 4.6>, I'm considering a situation with the new fsensor + if( minVolt >= IRsensor_Ldiode_TRESHOLD && minVolt <= IRsensor_Lmax_TRESHOLD + && maxVolt >= IRsensor_Hmin_TRESHOLD && maxVolt <= IRsensor_Hopen_TRESHOLD ){ - bool bTemp = (!CHECK_ALL_HEATERS); - bTemp = bTemp && (menu_menu==lcd_status_screen); - bTemp = bTemp && ((oFsensorPCB==ClFsensorPCB::_Old)||(oFsensorPCB==ClFsensorPCB::_Undef)); - bTemp = bTemp && fsensor_enabled; - if(bTemp){ - nFSCheckCount++; - if(nFSCheckCount>FS_CHECK_COUNT){ - nFSCheckCount=0; // not necessary - oFsensorPCB=ClFsensorPCB::_Rev04; - eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB); - printf_IRSensorAnalogBoardChange(true); - lcd_setstatuspgm(_i("FS v0.4 or newer"));////c=18 - } - } else { - nFSCheckCount=0; - } + manage_inactivity_IR_ANALOG_Check(nFSCheckCount, ClFsensorPCB::_Old, ClFsensorPCB::_Rev04, _i("FS v0.4 or newer") ); ////c=18 + } + //! If and only if minVolt is in range <0.0, 0.3> and maxVolt is in range <4.6, 5.0V>, I'm considering a situation with the old fsensor + //! Note, we are not relying on one voltage here - getting just +5V can mean an old fsensor or a broken new sensor - that's why + //! we need to have both voltages detected correctly to allow switching back to the old fsensor. + else if( minVolt < IRsensor_Ldiode_TRESHOLD + && maxVolt > IRsensor_Hopen_TRESHOLD && maxVolt <= IRsensor_VMax_TRESHOLD + ){ + manage_inactivity_IR_ANALOG_Check(nFSCheckCount, ClFsensorPCB::_Rev04, oFsensorPCB=ClFsensorPCB::_Old, _i("FS v0.3 or older")); ////c=18 } #endif // IR_SENSOR_ANALOG if (fsensor_check_autoload()) @@ -9524,7 +9560,7 @@ static uint16_t nFSCheckCount=0; //-// if (degHotend0() > EXTRUDE_MINTEMP) if(0) { - Sound_MakeCustom(50,1000,false); + Sound_MakeCustom(50,1000,false); loading_flag = true; enquecommand_front_P((PSTR("M701"))); } @@ -9535,20 +9571,17 @@ if(0) show_preheat_nozzle_warning(); lcd_update_enable(true); */ - eFilamentAction=FilamentAction::AutoLoad; - bFilamentFirstRun=false; - if(target_temperature[0]>=EXTRUDE_MINTEMP) - { - bFilamentPreheatState=true; -// mFilamentItem(target_temperature[0],target_temperature_bed); - menu_submenu(mFilamentItemForce); - } - else - { - menu_submenu(lcd_generic_preheat_menu); - lcd_timeoutToStatus.start(); - } - } + eFilamentAction=FilamentAction::AutoLoad; + bFilamentFirstRun=false; + if(target_temperature[0]>=EXTRUDE_MINTEMP){ + bFilamentPreheatState=true; +// mFilamentItem(target_temperature[0],target_temperature_bed); + menu_submenu(mFilamentItemForce); + } else { + menu_submenu(lcd_generic_preheat_menu); + lcd_timeoutToStatus.start(); + } + } } } else @@ -9940,7 +9973,7 @@ static void wait_for_heater(long codenum, uint8_t extruder) { } else { - SERIAL_PROTOCOLLN("?"); + SERIAL_PROTOCOLLN('?'); } } #else @@ -10071,16 +10104,16 @@ void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_poi card.openFile(filename_wldsd, false); /*destination[Z_AXIS] = mesh_home_z_search; - //plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE, active_extruder); + //plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], Z_LIFT_FEEDRATE, active_extruder); + plan_buffer_line_destinationXYZE(Z_LIFT_FEEDRATE); for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } st_synchronize(); */ destination[Z_AXIS] = measure_z_height; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], Z_LIFT_FEEDRATE, active_extruder); + plan_buffer_line_destinationXYZE(Z_LIFT_FEEDRATE); for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } @@ -10105,9 +10138,9 @@ void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_poi if (iy & 1) ix = (x_points_num - 1) - ix; // Zig zag float z0 = 0.f; /*destination[Z_AXIS] = mesh_home_z_search; - //plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE, active_extruder); + //plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], Z_LIFT_FEEDRATE, active_extruder); + plan_buffer_line_destinationXYZE(Z_LIFT_FEEDRATE); for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } @@ -10120,8 +10153,8 @@ void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_poi destination[X_AXIS] = ix * (x_dimension / (x_points_num - 1)) + shift_x; destination[Y_AXIS] = iy * (y_dimension / (y_points_num - 1)) + shift_y; - mesh_plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], XY_AXIS_FEEDRATE/6, active_extruder); - set_current_to_destination(); + mesh_plan_buffer_line_destinationXYZE(XY_AXIS_FEEDRATE/6); + set_current_to_destination(); st_synchronize(); // printf_P(PSTR("X = %f; Y= %f \n"), current_position[X_AXIS], current_position[Y_AXIS]); @@ -10474,7 +10507,11 @@ float temp_comp_interpolation(float inp_temperature) { if (i>0) EEPROM_read_B(EEPROM_PROBE_TEMP_SHIFT + (i-1) * 2, &shift[i]); //read shift in steps from EEPROM temp_C[i] = 50 + i * 10; //temperature in C #ifdef PINDA_THERMISTOR - temp_C[i] = 35 + i * 5; //temperature in C + constexpr int start_compensating_temp = 35; + temp_C[i] = start_compensating_temp + i * 5; //temperature in degrees C +#ifdef DETECT_SUPERPINDA + static_assert(start_compensating_temp >= PINDA_MINTEMP, "Temperature compensation start point is lower than PINDA_MINTEMP."); +#endif //DETECT_SUPERPINDA #else temp_C[i] = 50 + i * 10; //temperature in C #endif @@ -10527,7 +10564,7 @@ float temp_comp_interpolation(float inp_temperature) { #ifdef PINDA_THERMISTOR float temp_compensation_pinda_thermistor_offset(float temperature_pinda) { - if (!temp_cal_active) return 0; + if (!eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE)) return 0; if (!calibration_status_pinda()) return 0; return temp_comp_interpolation(temperature_pinda) / cs.axis_steps_per_unit[Z_AXIS]; } @@ -10544,12 +10581,12 @@ void long_pause() //long pause print //lift z current_position[Z_AXIS] += Z_PAUSE_LIFT; if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS; - plan_buffer_line_curposXYZE(15, active_extruder); + plan_buffer_line_curposXYZE(15); //Move XY to side current_position[X_AXIS] = X_PAUSE_POS; current_position[Y_AXIS] = Y_PAUSE_POS; - plan_buffer_line_curposXYZE(50, active_extruder); + plan_buffer_line_curposXYZE(50); // Turn off the print fan fanSpeed = 0; @@ -10659,7 +10696,7 @@ void uvlo_() // Retract current_position[E_AXIS] -= default_retraction; - plan_buffer_line_curposXYZE(95, active_extruder); + plan_buffer_line_curposXYZE(95); st_synchronize(); disable_e0(); @@ -10672,7 +10709,7 @@ void uvlo_() current_position[Z_AXIS] += float(1024 - z_microsteps) / (z_res * cs.axis_steps_per_unit[Z_AXIS]) + UVLO_Z_AXIS_SHIFT; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS]/60, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS]/60); st_synchronize(); poweroff_z(); @@ -10735,7 +10772,7 @@ void uvlo_() // All is set: with all the juice left, try to move extruder away to detach the nozzle completely from the print poweron_z(); current_position[X_AXIS] = (current_position[X_AXIS] < 0.5f * (X_MIN_POS + X_MAX_POS)) ? X_MIN_POS : X_MAX_POS; - plan_buffer_line_curposXYZE(500, active_extruder); + plan_buffer_line_curposXYZE(500); st_synchronize(); wdt_enable(WDTO_1S); @@ -10786,7 +10823,7 @@ void uvlo_tiny() current_position[Z_AXIS] += float(1024 - z_microsteps) / (z_res * cs.axis_steps_per_unit[Z_AXIS]) + UVLO_TINY_Z_AXIS_SHIFT; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS]/60, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS]/60); st_synchronize(); poweroff_z(); @@ -10965,7 +11002,7 @@ bool recover_machine_state_after_power_panic() // 5) Set the physical positions from the logical positions using the world2machine transformation // This is only done to inizialize Z/E axes with physical locations, since X/Y are unknown. - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); // 6) Power up the Z motors, mark their positions as known. axis_known_position[Z_AXIS] = true; @@ -11389,9 +11426,9 @@ void print_mesh_bed_leveling_table() for (int8_t y = 0; y < MESH_NUM_Y_POINTS; ++ y) for (int8_t x = 0; x < MESH_NUM_Y_POINTS; ++ x) { MYSERIAL.print(mbl.z_values[y][x], 3); - SERIAL_ECHOPGM(" "); + SERIAL_ECHO(' '); } - SERIAL_ECHOLNPGM(""); + SERIAL_ECHOLN(); } uint16_t print_time_remaining() { @@ -11439,7 +11476,7 @@ static void print_time_remaining_init() void load_filament_final_feed() { current_position[E_AXIS]+= FILAMENTCHANGE_FINALFEED; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_EFEED_FINAL, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_EFEED_FINAL); } //! @brief Wait for user to check the state @@ -11584,7 +11621,7 @@ void M600_load_filament_movements() plan_buffer_line_curposXYZE(50, active_extruder); #else current_position[E_AXIS]+= FILAMENTCHANGE_FIRSTFEED ; - plan_buffer_line_curposXYZE(FILAMENTCHANGE_EFEED_FIRST, active_extruder); + plan_buffer_line_curposXYZE(FILAMENTCHANGE_EFEED_FIRST); #endif load_filament_final_feed(); lcd_loading_filament(); @@ -11691,7 +11728,6 @@ void disable_force_z() #endif // TMC2130 } - void enable_force_z() { if(bEnableForce_z) diff --git a/Firmware/bootapp.c b/Firmware/bootapp.c index 4fd67db2b..c4585af5c 100644 --- a/Firmware/bootapp.c +++ b/Firmware/bootapp.c @@ -9,6 +9,8 @@ extern FILE _uartout; #define uartout (&_uartout) +extern void softReset(); + void bootapp_print_vars(void) { fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr); @@ -39,8 +41,7 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size) boot_src_addr = (uint32_t)rptr; boot_dst_addr = (uint32_t)fptr; bootapp_print_vars(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } void bootapp_reboot_user0(uint8_t reserved) @@ -50,6 +51,5 @@ void bootapp_reboot_user0(uint8_t reserved) boot_app_flags = BOOT_APP_FLG_USER0; boot_reserved = reserved; bootapp_print_vars(); - wdt_enable(WDTO_15MS); - while(1); + softReset(); } diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index 0e80d18ce..9d2a501dc 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -331,7 +331,7 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir) { SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL); SERIAL_PROTOCOL(subdirname); - SERIAL_PROTOCOLLNPGM("."); + SERIAL_PROTOCOLLN('.'); return; } else @@ -431,7 +431,7 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru { SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL); SERIAL_PROTOCOL(fname); - SERIAL_PROTOCOLLNPGM("."); + SERIAL_PROTOCOLLN('.'); } } else @@ -440,7 +440,7 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru { SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL); SERIAL_PROTOCOL(fname); - SERIAL_PROTOCOLLNPGM("."); + SERIAL_PROTOCOLLN('.'); } else { @@ -497,17 +497,15 @@ void CardReader::getStatus() SERIAL_PROTOCOLLNPGM("Print saved"); } else { - SERIAL_PROTOCOL(longFilename); - SERIAL_PROTOCOLPGM("\n"); + SERIAL_PROTOCOLLN(longFilename); SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE SERIAL_PROTOCOL(sdpos); - SERIAL_PROTOCOLPGM("/"); + SERIAL_PROTOCOL('/'); SERIAL_PROTOCOLLN(filesize); - uint16_t time = _millis()/60000 - starttime/60000; + uint16_t time = ( _millis() - starttime ) / 60000U; SERIAL_PROTOCOL(itostr2(time/60)); SERIAL_PROTOCOL(':'); - SERIAL_PROTOCOL(itostr2(time%60)); - SERIAL_PROTOCOLPGM("\n"); + SERIAL_PROTOCOLLN(itostr2(time%60)); } } else { diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 61e078fc0..5cb7ddb85 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -341,8 +341,9 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D9F 3487 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - bed temp | ^ | D3 Ax0d9f C1 | 0x0DA0 3488 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - PINDA temp | ^ | D3 Ax0da0 C1 | 0x0DA1 3489 | uint8 | ??? | 00h 0 | ffh 255 | ??? | ??? | D3 Ax0da1 C1 -| 0x0D48 3400 | uint8 | EEPROM_FSENSOR_PCB | ??? | ffh 255 | Filament Sensor type old vs new | ??? | D3 Ax0d48 C1 -| ^ | ^ | ^ | ??? | ^ | Filament Sensor type ??? | ^ | ^ +| 0x0D48 3400 | uint8 | EEPROM_FSENSOR_PCB | ffh 255 | ffh 255 | Filament Sensor type IR unknown | LCD Support | D3 Ax0d48 C1 +| ^ | ^ | ^ | 00h 0 | ^ | Filament Sensor type IR 0.3 or older | ^ | ^ +| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor type IR 0.4 or newer | ^ | ^ | 0x0D47 3399 | uint8 | EEPROM_FSENSOR_ACTION_NA | 00h 0 | ffh 255 | Filament Sensor action: __Continue__ | LCD menu | D3 Ax0d47 C1 | ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor action: __Pause__ | ^ | ^ | 0x0D37 3383 | float | EEPROM_UVLO_SAVED_TARGET | ??? | ff ff ff ffh | Power panic saved target all-axis | ??? | D3 Ax0d37 C16 @@ -358,6 +359,12 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | ^ | ^ | ^ | 00h 0 | ^ | LCD backlight mode: __Dim__ | ^ | ^ | 0x0D30 3376 | uint16 | EEPROM_BACKLIGHT_TIMEOUT | 01 00 - ff ff | 0a 00h 65535 | LCD backlight timeout: __10__ seconds | LCD menu | D3 Ax0d30 C2 | 0x0D2C 3372 | float | EEPROM_UVLO_LA_K | ??? | ff ff ff ffh | Power panic saved Linear Advanced K value | ??? | D3 Ax0d2c C4 +| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | ffh 255 | ffh 255 | ALTFAN override unknown state | LCD menu | D3 Ax0d2b C1 +| ^ | ^ | ^ | 00h 0 | ^ | ALTFAN override deactivated | ^ | ^ +| ^ | ^ | ^ | 01h 1 | ^ | ALTFAN override activated | ^ | ^ +| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | ffh 255 | ffh 255 | Experimental menu visibility unknown state | LCD menu | D3 Ax0d2a C1 +| ^ | ^ | ^ | 00h 0 | ^ | Experimental menu visibility hidden | ^ | ^ +| ^ | ^ | ^ | 01h 1 | ^ | Experimental menu visibility visible | ^ | ^ | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code @@ -560,8 +567,11 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float +#define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8 +#define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8 + //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_UVLO_LA_K +#define EEPROM_LAST_ITEM EEPROM_EXPERIMENTAL_VISIBILITY // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/fastio.h b/Firmware/fastio.h index e4f25ed8b..acded8cb6 100644 --- a/Firmware/fastio.h +++ b/Firmware/fastio.h @@ -58,7 +58,7 @@ #define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) /// check if pin is an timer -#define _GET_TIMER(IO) ((DIO ## IO ## _PWM) +#define _GET_TIMER(IO) (DIO ## IO ## _PWM) // why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html diff --git a/Firmware/fsensor.cpp b/Firmware/fsensor.cpp index edb2fa894..7908c5dbc 100755 --- a/Firmware/fsensor.cpp +++ b/Firmware/fsensor.cpp @@ -170,6 +170,21 @@ void fsensor_checkpoint_print(void) restore_print_from_ram_and_continue(0); } +#ifdef IR_SENSOR_ANALOG +const char* FsensorIRVersionText() +{ + switch(oFsensorPCB) + { + case ClFsensorPCB::_Old: + return _T(MSG_IR_03_OR_OLDER); + case ClFsensorPCB::_Rev04: + return _T(MSG_IR_04_OR_NEWER); + default: + return _T(MSG_IR_UNKNOWN); + } +} +#endif //IR_SENSOR_ANALOG + void fsensor_init(void) { #ifdef PAT9125 @@ -207,9 +222,9 @@ void fsensor_init(void) } printf_P(PSTR("FSensor %S"), (fsensor_enabled?PSTR("ENABLED"):PSTR("DISABLED"))); #ifdef IR_SENSOR_ANALOG - printf_P(PSTR(" (sensor board revision:%S)\n"), (oFsensorPCB==ClFsensorPCB::_Rev04) ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER)); + printf_P(PSTR(" (sensor board revision:%S)\n"), FsensorIRVersionText()); #else //IR_SENSOR_ANALOG - printf_P(PSTR("\n")); + MYSERIAL.println(); #endif //IR_SENSOR_ANALOG if (check_for_ir_sensor()){ ir_sensor_detected = true; @@ -463,22 +478,8 @@ bool fsensor_oq_result(void) } #endif //FSENSOR_QUALITY -ISR(FSENSOR_INT_PIN_VECT) +FORCE_INLINE static void fsensor_isr(int st_cnt) { - if (mmu_enabled || ir_sensor_detected) return; - if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return; - fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG; - - // prevent isr re-entry - static bool _lock = false; - if (_lock) return; - _lock = true; - - // fetch fsensor_st_cnt atomically - int st_cnt = fsensor_st_cnt; - fsensor_st_cnt = 0; - sei(); - uint8_t old_err_cnt = fsensor_err_cnt; uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y(); if (!pat9125_res) @@ -563,8 +564,28 @@ ISR(FSENSOR_INT_PIN_VECT) #endif //DEBUG_FSENSOR_LOG pat9125_y = 0; - _lock = false; - return; +} + +ISR(FSENSOR_INT_PIN_VECT) +{ + if (mmu_enabled || ir_sensor_detected) return; + if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return; + fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG; + + // prevent isr re-entry + static bool _lock = false; + if (!_lock) + { + // fetch fsensor_st_cnt atomically + int st_cnt = fsensor_st_cnt; + fsensor_st_cnt = 0; + + _lock = true; + sei(); + fsensor_isr(st_cnt); + cli(); + _lock = false; + } } void fsensor_setup_interrupt(void) @@ -611,42 +632,41 @@ void fsensor_enque_M600(){ void fsensor_update(void) { #ifdef PAT9125 - if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX)) - { - fsensor_stop_and_save_print(); + if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX)) + { + fsensor_stop_and_save_print(); KEEPALIVE_STATE(IN_HANDLER); - bool autoload_enabled_tmp = fsensor_autoload_enabled; - fsensor_autoload_enabled = false; - bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled; - fsensor_oq_meassure_enabled = true; + bool autoload_enabled_tmp = fsensor_autoload_enabled; + fsensor_autoload_enabled = false; + bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled; + fsensor_oq_meassure_enabled = true; // move the nozzle away while checking the filament current_position[Z_AXIS] += 0.8; if(current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS; - plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS], active_extruder); + plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS]); st_synchronize(); // check the filament in isolation fsensor_reset_err_cnt(); - fsensor_oq_meassure_start(0); + fsensor_oq_meassure_start(0); float e_tmp = current_position[E_AXIS]; current_position[E_AXIS] -= 3; - plan_buffer_line_curposXYZE(250/60, active_extruder); + plan_buffer_line_curposXYZE(250/60); current_position[E_AXIS] = e_tmp; - plan_buffer_line_curposXYZE(200/60, active_extruder); + plan_buffer_line_curposXYZE(200/60); st_synchronize(); - fsensor_oq_meassure_stop(); + fsensor_oq_meassure_stop(); - bool err = false; - err |= (fsensor_err_cnt > 0); // final error count is non-zero - err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit - err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit + bool err = false; + err |= (fsensor_err_cnt > 0); // final error count is non-zero + err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit + err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit fsensor_restore_print_and_continue(); fsensor_autoload_enabled = autoload_enabled_tmp; fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp; - unsigned long now = _millis(); if (!err && (now - fsensor_softfail_last) > FSENSOR_SOFTERR_DELTA) fsensor_softfail_ccnt = 0; @@ -663,70 +683,70 @@ void fsensor_update(void) fsensor_softfail_last = 0; fsensor_enque_M600(); } - } + } #else //PAT9125 - if (CHECK_FSENSOR && ir_sensor_detected) + if (CHECK_FSENSOR && ir_sensor_detected) { - if(digitalRead(IR_SENSOR_PIN)) - { // IR_SENSOR_PIN ~ H + if(digitalRead(IR_SENSOR_PIN)) + { // IR_SENSOR_PIN ~ H #ifdef IR_SENSOR_ANALOG - if(!bIRsensorStateFlag) + if(!bIRsensorStateFlag) + { + bIRsensorStateFlag=true; + nIRsensorLastTime=_millis(); + } + else + { + if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY) { - bIRsensorStateFlag=true; - nIRsensorLastTime=_millis(); - } - else - { - if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY) - { - uint8_t nMUX1,nMUX2; - uint16_t nADC; - bIRsensorStateFlag=false; - // sequence for direct data reading from AD converter - DISABLE_TEMPERATURE_INTERRUPT(); - nMUX1=ADMUX; // ADMUX saving - nMUX2=ADCSRB; - adc_setmux(VOLT_IR_PIN); - ADCSRA|=(1<4.6V - // If it does, it means a disconnected cables or faulty board - if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) ) - { - fsensor_disable(); - fsensor_not_responding = true; - printf_P(PSTR("IR sensor not responding (%d)!\n"),1); - if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause) + uint8_t nMUX1,nMUX2; + uint16_t nADC; + bIRsensorStateFlag=false; + // sequence for direct data reading from AD converter + DISABLE_TEMPERATURE_INTERRUPT(); + nMUX1=ADMUX; // ADMUX saving + nMUX2=ADCSRB; + adc_setmux(VOLT_IR_PIN); + ADCSRA|=(1<4.6V + // If it does, it means a disconnected cables or faulty board + if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) ) + { + fsensor_disable(); + fsensor_not_responding = true; + printf_P(PSTR("IR sensor not responding (%d)!\n"),1); + if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause) - // if we are printing and FS action is set to "Pause", force pause the print - if(oFsensorActionNA==ClFsensorActionNA::_Pause) - lcd_pause_print(); - } - else - { + // if we are printing and FS action is set to "Pause", force pause the print + if(oFsensorActionNA==ClFsensorActionNA::_Pause) + lcd_pause_print(); + } + else + { #endif //IR_SENSOR_ANALOG - fsensor_checkpoint_print(); - fsensor_enque_M600(); + fsensor_checkpoint_print(); + fsensor_enque_M600(); #ifdef IR_SENSOR_ANALOG - } - } + } } - } - else - { // IR_SENSOR_PIN ~ L - bIRsensorStateFlag=false; + } + } + else + { // IR_SENSOR_PIN ~ L + bIRsensorStateFlag=false; #endif //IR_SENSOR_ANALOG - } - } + } + } #endif //PAT9125 } @@ -734,24 +754,36 @@ void fsensor_update(void) /// This is called only upon start of the printer or when switching the fsensor ON in the menu /// We cannot do temporal window checks here (aka the voltage has been in some range for a period of time) bool fsensor_IR_check(){ - if( IRsensor_Lmax_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_Hmin_TRESHOLD ){ - // If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly. - // Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way, - // that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual - // and would have been considered more like a sabotage than normal printer operation - printf_P(PSTR("fsensor in forbidden range 1.5-3V - bad lever\n")); - return false; - } - - if( oFsensorPCB == ClFsensorPCB::_Rev04 ){ - // newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount - if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){ - printf_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected\n")); - return false; - } - } - - // otherwise the IR fsensor is considered working correctly - return true; + if( IRsensor_Lmax_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_Hmin_TRESHOLD ){ + /// If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly. + /// Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way, + /// that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual + /// and would have been considered more like a sabotage than normal printer operation + printf_P(PSTR("fsensor in forbidden range 1.5-3V - check sensor\n")); + return false; + } + if( oFsensorPCB == ClFsensorPCB::_Rev04 ){ + /// newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount + if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){ + printf_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected\n")); + return false; + } + /// newer IR sensor cannot normally produce 0-0.3V, this is considered a failure +#if 0 //Disabled as it has to be decided if we gonna use this or not. + if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){ + printf_P(PSTR("fsensor v0.4 in fault range 0.0-0.3V - wrong IR sensor\n")); + return false; + } +#endif + } + /// If IR sensor is "uknown state" and filament is not loaded > 1.5V return false +#if 0 + if( (oFsensorPCB == ClFsensorPCB::_Undef) && ( current_voltage_raw_IR > IRsensor_Lmax_TRESHOLD ) ){ + printf_P(PSTR("Unknown IR sensor version and no filament loaded detected.\n")); + return false; + } +#endif + // otherwise the IR fsensor is considered working correctly + return true; } #endif //IR_SENSOR_ANALOG diff --git a/Firmware/fsensor.h b/Firmware/fsensor.h index 4038d6b61..7eb09ab8b 100755 --- a/Firmware/fsensor.h +++ b/Firmware/fsensor.h @@ -83,6 +83,7 @@ extern uint8_t fsensor_log; //! @} #endif //PAT9125 +#define VOLT_DIV_REF 5 #ifdef IR_SENSOR_ANALOG #define IR_SENSOR_STEADY 10 // [ms] @@ -103,8 +104,21 @@ enum class ClFsensorActionNA:uint_least8_t extern ClFsensorPCB oFsensorPCB; extern ClFsensorActionNA oFsensorActionNA; +extern const char* FsensorIRVersionText(); extern bool fsensor_IR_check(); +constexpr uint16_t Voltage2Raw(float V){ + return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F; +} +constexpr float Raw2Voltage(uint16_t raw){ + return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) ); +} +constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982 +constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910 +constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821 +constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059 +constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368 + #endif //IR_SENSOR_ANALOG #endif //FSENSOR_H diff --git a/Firmware/heatbed_pwm.cpp b/Firmware/heatbed_pwm.cpp index 4cd0bf5e5..8121df3ee 100755 --- a/Firmware/heatbed_pwm.cpp +++ b/Firmware/heatbed_pwm.cpp @@ -59,7 +59,6 @@ enum class States : uint8_t { RISE, ///< 16 fast PWM cycles with increasing duty up to steady ON RISE_TO_ONE, ///< metastate allowing the timer change its state atomically without artefacts on the output pin ONE, ///< steady 1 (ON), no change for the whole period - ONE_TO_FALL, ///< metastate allowing the timer change its state atomically without artefacts on the output pin FALL, ///< 16 fast PWM cycles with decreasing duty down to steady OFF FALL_TO_ZERO ///< metastate allowing the timer change its state atomically without artefacts on the output pin }; @@ -155,12 +154,7 @@ ISR(TIMER0_OVF_vect) // timer compare interrupt service routine return; // want full duty for the next ONE cycle again - so keep on heating and just wait for the next timer ovf } // otherwise moving towards FALL - // @@TODO it looks like ONE_TO_FALL isn't necessary, there are no artefacts at all state = States::ONE;//_TO_FALL; -// TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz -// break; -// case States::ONE_TO_FALL: -// OCR0B = 255; // zero duty state=States::FALL; fastCounter = fastMax - 1;// we'll do 16-1 cycles of RISE TCNT0 = 255; // force overflow on the next clock cycle diff --git a/Firmware/la10compat.cpp b/Firmware/la10compat.cpp index 918659255..98522f645 100644 --- a/Firmware/la10compat.cpp +++ b/Firmware/la10compat.cpp @@ -78,10 +78,10 @@ float la10c_jerk(float j) return j; // bring low E-jerk values into equivalent LA 1.5 values by - // flattening the response in the (1-4.5) range using a piecewise + // flattening the response in the (0.3-4.5) range using a piecewise // function. Is it truly worth to preserve the difference between // 1.5/2.5 E-jerk for LA1.0? Probably not, but we try nonetheless. - j = j < 1.0? j * 3.625: + j = j < 0.3? j * 11.5: j < 4.5? j * 0.25 + 3.375: j; diff --git a/Firmware/menu.cpp b/Firmware/menu.cpp index 3995faf4c..88f929fbb 100755 --- a/Firmware/menu.cpp +++ b/Firmware/menu.cpp @@ -53,6 +53,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo { menu_menu = menu; lcd_encoder = encoder; + menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support CRITICAL_SECTION_END; if (reset_menu_state) menu_data_reset(); diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index 88cbc671a..12fca582e 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -920,7 +920,7 @@ static inline void go_xy(float x, float y, float fr) static inline void go_to_current(float fr) { - plan_buffer_line_curposXYZE(fr, active_extruder); + plan_buffer_line_curposXYZE(fr); st_synchronize(); } @@ -929,7 +929,7 @@ static inline void update_current_position_xyz() current_position[X_AXIS] = st_get_position_mm(X_AXIS); current_position[Y_AXIS] = st_get_position_mm(Y_AXIS); current_position[Z_AXIS] = st_get_position_mm(Z_AXIS); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); } static inline void update_current_position_z() diff --git a/Firmware/messages.c b/Firmware/messages.c index c97b16bbf..21dbe9397 100644 --- a/Firmware/messages.c +++ b/Firmware/messages.c @@ -140,8 +140,9 @@ const char MSG_DIM[] PROGMEM_I1 = ISTR("Dim"); ////c=6 const char MSG_AUTO[] PROGMEM_I1 = ISTR("Auto"); ////c=6 #ifdef IR_SENSOR_ANALOG // Beware - the space at the beginning is necessary since it is reused in LCD menu items which are to be with a space -const char MSG_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////c=18 -const char MSG_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////c=18 +const char MSG_IR_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////c=18 +const char MSG_IR_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////c=18 +const char MSG_IR_UNKNOWN[] PROGMEM_I1 = ISTR("unknown state");////c=18 #endif //not internationalized messages diff --git a/Firmware/messages.h b/Firmware/messages.h index 599f1d1fa..4653c869e 100644 --- a/Firmware/messages.h +++ b/Firmware/messages.h @@ -139,8 +139,9 @@ extern const char MSG_BRIGHT[]; extern const char MSG_DIM[]; extern const char MSG_AUTO[]; #ifdef IR_SENSOR_ANALOG -extern const char MSG_04_OR_NEWER[]; -extern const char MSG_03_OR_OLDER[]; +extern const char MSG_IR_04_OR_NEWER[]; +extern const char MSG_IR_03_OR_OLDER[]; +extern const char MSG_IR_UNKNOWN[]; #endif //not internationalized messages diff --git a/Firmware/mmu.cpp b/Firmware/mmu.cpp index ebf8c0131..c5981894c 100755 --- a/Firmware/mmu.cpp +++ b/Firmware/mmu.cpp @@ -540,7 +540,7 @@ void mmu_command(MmuCmd cmd) void mmu_load_step(bool synchronize) { current_position[E_AXIS] = current_position[E_AXIS] + MMU_LOAD_FEEDRATE * 0.1; - plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE); if (synchronize) st_synchronize(); } @@ -605,7 +605,7 @@ bool mmu_get_response(uint8_t move) { printf_P(PSTR("Unload 1\n")); current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001; - plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE); st_synchronize(); } } @@ -623,7 +623,7 @@ bool mmu_get_response(uint8_t move) { printf_P(PSTR("Unload 2\n")); current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001; - plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE); st_synchronize(); } } @@ -701,13 +701,13 @@ void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move) //lift z current_position[Z_AXIS] += Z_PAUSE_LIFT; if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS; - plan_buffer_line_curposXYZE(15, active_extruder); + plan_buffer_line_curposXYZE(15); st_synchronize(); //Move XY to side current_position[X_AXIS] = X_PAUSE_POS; current_position[Y_AXIS] = Y_PAUSE_POS; - plan_buffer_line_curposXYZE(50, active_extruder); + plan_buffer_line_curposXYZE(50); st_synchronize(); } if (turn_off_nozzle) { @@ -758,17 +758,17 @@ void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move) lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature...")); delay_keep_alive(3000); } - mmu_wait_for_heater_blocking(); + mmu_wait_for_heater_blocking(); } if (move_axes) { lcd_clear(); lcd_display_message_fullscreen_P(_i("MMU OK. Resuming position...")); current_position[X_AXIS] = x_position_bckp; current_position[Y_AXIS] = y_position_bckp; - plan_buffer_line_curposXYZE(50, active_extruder); + plan_buffer_line_curposXYZE(50); st_synchronize(); current_position[Z_AXIS] = z_position_bckp; - plan_buffer_line_curposXYZE(15, active_extruder); + plan_buffer_line_curposXYZE(15); st_synchronize(); } else { @@ -807,19 +807,19 @@ void mmu_load_to_nozzle() current_position[E_AXIS] += 7.2f; } float feedrate = 562; - plan_buffer_line_curposXYZE(feedrate / 60, active_extruder); + plan_buffer_line_curposXYZE(feedrate / 60); st_synchronize(); current_position[E_AXIS] += 14.4f; feedrate = 871; - plan_buffer_line_curposXYZE(feedrate / 60, active_extruder); + plan_buffer_line_curposXYZE(feedrate / 60); st_synchronize(); current_position[E_AXIS] += 36.0f; feedrate = 1393; - plan_buffer_line_curposXYZE(feedrate / 60, active_extruder); + plan_buffer_line_curposXYZE(feedrate / 60); st_synchronize(); current_position[E_AXIS] += 14.4f; feedrate = 871; - plan_buffer_line_curposXYZE(feedrate / 60, active_extruder); + plan_buffer_line_curposXYZE(feedrate / 60); st_synchronize(); if (!saved_e_relative_mode) axis_relative_modes &= ~E_AXIS_MASK; } @@ -1072,7 +1072,7 @@ void mmu_filament_ramming() for(uint8_t i = 0; i < (sizeof(ramming_sequence)/sizeof(E_step));++i) { current_position[E_AXIS] += pgm_read_float(&(ramming_sequence[i].extrude)); - plan_buffer_line_curposXYZE(pgm_read_float(&(ramming_sequence[i].feed_rate)), active_extruder); + plan_buffer_line_curposXYZE(pgm_read_float(&(ramming_sequence[i].feed_rate))); st_synchronize(); } } @@ -1446,9 +1446,9 @@ bFilamentAction=false; // NOT in "mmu_fil_eject_menu( static bool can_load() { current_position[E_AXIS] += 60; - plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE); current_position[E_AXIS] -= 52; - plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE); st_synchronize(); uint_least8_t filament_detected_count = 0; @@ -1458,7 +1458,7 @@ static bool can_load() for(uint_least8_t i = 0; i < steps; ++i) { current_position[E_AXIS] -= e_increment; - plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder); + plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE); st_synchronize(); if(0 == PIN_GET(IR_SENSOR_PIN)) { diff --git a/Firmware/optiboot_w25x20cl.cpp b/Firmware/optiboot_w25x20cl.cpp index 584c32fed..dce4074e1 100644 --- a/Firmware/optiboot_w25x20cl.cpp +++ b/Firmware/optiboot_w25x20cl.cpp @@ -99,9 +99,11 @@ struct block_t; extern struct block_t *block_buffer; //! @brief Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory. -void optiboot_w25x20cl_enter() +//! @return 1 if "start\n" was not sent. Optiboot was skipped +//! @return 0 if "start\n" was sent. Optiboot ran normally. No need to send "start\n" in setup() +uint8_t optiboot_w25x20cl_enter() { - if (boot_app_flags & BOOT_APP_FLG_USER0) return; + if (boot_app_flags & BOOT_APP_FLG_USER0) return 1; uint8_t ch; uint8_t rampz = 0; register uint16_t address = 0; @@ -120,38 +122,46 @@ void optiboot_w25x20cl_enter() unsigned long boot_timer = 0; const char *ptr = entry_magic_send; const char *end = strlen_P(entry_magic_send) + ptr; - // Initialize the serial line. - UCSR0A |= (1 << U2X0); - UBRR0L = (((float)(F_CPU))/(((float)(115200))*8.0)-1.0+0.5); - UCSR0B = (1 << RXEN0) | (1 << TXEN0); + const uint8_t selectedSerialPort_bak = selectedSerialPort; // Flush the serial line. while (RECV_READY) { watchdogReset(); // Dummy register read (discard) (void)(*(char *)UDR0); } + selectedSerialPort = 0; //switch to Serial0 + MYSERIAL.flush(); //clear RX buffer + int SerialHead = rx_buffer.head; // Send the initial magic string. while (ptr != end) putch(pgm_read_byte(ptr ++)); watchdogReset(); - // Wait for one second until a magic string (constant entry_magic) is received + // Wait for two seconds until a magic string (constant entry_magic) is received // from the serial line. ptr = entry_magic_receive; end = strlen_P(entry_magic_receive) + ptr; while (ptr != end) { - while (! RECV_READY) { + while (rx_buffer.head == SerialHead) { watchdogReset(); delayMicroseconds(1); if (++ boot_timer > boot_timeout) + { // Timeout expired, continue with the application. - return; + selectedSerialPort = selectedSerialPort_bak; //revert Serial setting + return 0; + } } - ch = UDR0; + ch = rx_buffer.buffer[SerialHead]; + SerialHead = (unsigned int)(SerialHead + 1) % RX_BUFFER_SIZE; if (pgm_read_byte(ptr ++) != ch) + { // Magic was not received correctly, continue with the application - return; + selectedSerialPort = selectedSerialPort_bak; //revert Serial setting + return 0; + } watchdogReset(); } + cbi(UCSR0B, RXCIE0); //disable the MarlinSerial0 interrupt // Send the cfm magic string. ptr = entry_magic_cfm; while (ptr != end) diff --git a/Firmware/optiboot_w25x20cl.h b/Firmware/optiboot_w25x20cl.h index dc7d4395c..95c6465f3 100644 --- a/Firmware/optiboot_w25x20cl.h +++ b/Firmware/optiboot_w25x20cl.h @@ -1,6 +1,6 @@ #ifndef OPTIBOOT_W25X20CL_H #define OPTIBOOT_W25X20CL_H -extern void optiboot_w25x20cl_enter(); +extern uint8_t optiboot_w25x20cl_enter(); #endif /* OPTIBOOT_W25X20CL_H */ diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index fcebfa58f..2615ef66e 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -226,11 +226,23 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit // Size of Plateau of Nominal Rate. uint32_t plateau_steps = 0; +#ifdef LIN_ADVANCE + uint16_t final_adv_steps = 0; + uint16_t max_adv_steps = 0; + if (block->use_advance_lead) { + final_adv_steps = final_rate * block->adv_comp; + } +#endif + // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will // have to use intersection_distance() to calculate when to abort acceleration and start braking // in order to reach the final_rate exactly at the end of this block. if (accel_decel_steps < block->step_event_count.wide) { plateau_steps = block->step_event_count.wide - accel_decel_steps; +#ifdef LIN_ADVANCE + if (block->use_advance_lead) + max_adv_steps = block->nominal_rate * block->adv_comp; +#endif } else { uint32_t acceleration_x4 = acceleration << 2; // Avoid negative numbers @@ -263,14 +275,20 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit decelerate_steps = block->step_event_count.wide; accelerate_steps = block->step_event_count.wide - decelerate_steps; } - } #ifdef LIN_ADVANCE - uint16_t final_adv_steps = 0; - if (block->use_advance_lead) { - final_adv_steps = exit_speed * block->adv_comp; - } + if (block->use_advance_lead) { + if(!accelerate_steps || !decelerate_steps) { + // accelerate_steps=0: deceleration-only ramp, max_rate is effectively unused + // decelerate_steps=0: acceleration-only ramp, max_rate _is_ final_rate + max_adv_steps = final_adv_steps; + } else { + float max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr); + max_adv_steps = max_rate * block->adv_comp; + } + } #endif + } CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section // This block locks the interrupts globally for 4.38 us, @@ -284,6 +302,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit block->final_rate = final_rate; #ifdef LIN_ADVANCE block->final_adv_steps = final_adv_steps; + block->max_adv_steps = max_adv_steps; #endif } CRITICAL_SECTION_END; @@ -671,8 +690,16 @@ void planner_abort_hard() waiting_inside_plan_buffer_line_print_aborted = true; } -void plan_buffer_line_curposXYZE(float feed_rate, uint8_t extruder) { - plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feed_rate, extruder ); +void plan_buffer_line_curposXYZE(float feed_rate) { + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feed_rate, active_extruder ); +} + +void plan_buffer_line_destinationXYZE(float feed_rate) { + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feed_rate, active_extruder); +} + +void plan_set_position_curposXYZE(){ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); } float junction_deviation = 0.1; @@ -1069,12 +1096,20 @@ Having the real displacement of the head, we can calculate the total movement le && delta_mm[E_AXIS] >= 0 && abs(delta_mm[Z_AXIS]) < 0.5; if (block->use_advance_lead) { +#ifdef LA_FLOWADJ + // M221/FLOW should change uniformly the extrusion thickness + float delta_e = (e - position_float[E_AXIS]) / extruder_multiplier[extruder]; +#else + // M221/FLOW only adjusts for an incorrect source diameter + float delta_e = (e - position_float[E_AXIS]); +#endif + float delta_D = sqrt(sq(x - position_float[X_AXIS]) + + sq(y - position_float[Y_AXIS]) + + sq(z - position_float[Z_AXIS])); + // all extrusion moves with LA require a compression which is proportional to the // extrusion_length to distance ratio (e/D) - e_D_ratio = (e - position_float[E_AXIS]) / - sqrt(sq(x - position_float[X_AXIS]) - + sq(y - position_float[Y_AXIS]) - + sq(z - position_float[Z_AXIS])); + e_D_ratio = delta_e / delta_D; // Check for unusual high e_D ratio to detect if a retract move was combined with the last // print move due to min. steps per segment. Never execute this with advance! This assumes @@ -1124,53 +1159,7 @@ Having the real displacement of the head, we can calculate the total movement le block->acceleration_st = (block->acceleration_st + (bresenham_oversample >> 1)) / bresenham_oversample; #endif - block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0))); - -#ifdef LIN_ADVANCE - if (block->use_advance_lead) { - // the nominal speed doesn't change past this point: calculate the compression ratio for the - // segment and the required advance steps - block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; - block->max_adv_steps = block->nominal_speed * block->adv_comp; - - float advance_speed; - if (e_D_ratio > 0) - advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]); - else - advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS]; - - // to save more space we avoid another copy of calc_timer and go through slow division, but we - // still need to replicate the *exact* same step grouping policy (see below) - if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY; - float advance_rate = (F_CPU / 8.0) / advance_speed; - if (advance_speed > 20000) { - block->advance_rate = advance_rate * 4; - block->advance_step_loops = 4; - } - else if (advance_speed > 10000) { - block->advance_rate = advance_rate * 2; - block->advance_step_loops = 2; - } - else - { - // never overflow the internal accumulator with very low rates - if (advance_rate < UINT16_MAX) - block->advance_rate = advance_rate; - else - block->advance_rate = UINT16_MAX; - block->advance_step_loops = 1; - } - - #ifdef LA_DEBUG - if (block->advance_step_loops > 2) - // @wavexx: we should really check for the difference between step_loops and - // advance_step_loops instead. A difference of more than 1 will lead - // to uneven speed and *should* be adjusted here by furthermore - // reducing the speed. - SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed."); - #endif - } -#endif + block->acceleration_rate = ((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0))); // Start with a safe speed. // Safe speed is the speed, from which the machine may halt to stop immediately. @@ -1297,6 +1286,53 @@ Having the real displacement of the head, we can calculate the total movement le // Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated. block->speed_factor = block->nominal_rate / block->nominal_speed; + +#ifdef LIN_ADVANCE + if (block->use_advance_lead) { + // calculate the compression ratio for the segment (the required advance steps are computed + // during trapezoid planning) + float adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; // (step/(mm/s)) + block->adv_comp = adv_comp / block->speed_factor; // step/(step/min) + + float advance_speed; + if (e_D_ratio > 0) + advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]); + else + advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS]; + + // to save more space we avoid another copy of calc_timer and go through slow division, but we + // still need to replicate the *exact* same step grouping policy (see below) + if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY; + float advance_rate = (F_CPU / 8.0) / advance_speed; + if (advance_speed > 20000) { + block->advance_rate = advance_rate * 4; + block->advance_step_loops = 4; + } + else if (advance_speed > 10000) { + block->advance_rate = advance_rate * 2; + block->advance_step_loops = 2; + } + else + { + // never overflow the internal accumulator with very low rates + if (advance_rate < UINT16_MAX) + block->advance_rate = advance_rate; + else + block->advance_rate = UINT16_MAX; + block->advance_step_loops = 1; + } + + #ifdef LA_DEBUG + if (block->advance_step_loops > 2) + // @wavexx: we should really check for the difference between step_loops and + // advance_step_loops instead. A difference of more than 1 will lead + // to uneven speed and *should* be adjusted here by furthermore + // reducing the speed. + SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed."); + #endif + } +#endif + calculate_trapezoid_for_block(block, block->entry_speed, safe_speed); if (block->step_event_count.wide <= 32767) diff --git a/Firmware/planner.h b/Firmware/planner.h index 2adcf94e7..34899cac4 100644 --- a/Firmware/planner.h +++ b/Firmware/planner.h @@ -73,12 +73,12 @@ typedef struct { // steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line(). dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis dda_usteps_t step_event_count; // The number of step events required to complete this block - long acceleration_rate; // The acceleration rate used for acceleration calculation + uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) unsigned char active_extruder; // Selects the active extruder // accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller. - long accelerate_until; // The index of the step event on which to stop acceleration - long decelerate_after; // The index of the step event on which to start decelerating + uint32_t accelerate_until; // The index of the step event on which to stop acceleration + uint32_t decelerate_after; // The index of the step event on which to start decelerating // Fields used by the motion planner to manage acceleration // float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis @@ -100,13 +100,12 @@ typedef struct { // Settings for the trapezoid generator (runs inside an interrupt handler). // Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts. - //FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway! unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec unsigned long initial_rate; // The jerk-adjusted step rate at start of block unsigned long final_rate; // The minimal rate at exit unsigned long acceleration_st; // acceleration steps/sec^2 - //FIXME does it have to be unsigned long? Probably uint8_t would be just fine. - unsigned long fan_speed; + //FIXME does it have to be int? Probably uint8_t would be just fine. Need to change in other places as well + int fan_speed; volatile char busy; @@ -154,7 +153,11 @@ vector_3 plan_get_position(); /// plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], ... /// saves almost 5KB. /// The performance penalty is negligible, since these planned lines are usually maintenance moves with the extruder. -void plan_buffer_line_curposXYZE(float feed_rate, uint8_t extruder); +void plan_buffer_line_curposXYZE(float feed_rate); + +void plan_buffer_line_destinationXYZE(float feed_rate); + +void plan_set_position_curposXYZE(); void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, uint8_t extruder, const float* gcode_target = NULL); //void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder); diff --git a/Firmware/speed_lookuptable.h b/Firmware/speed_lookuptable.h index 2748dd71a..21c6c767f 100644 --- a/Firmware/speed_lookuptable.h +++ b/Firmware/speed_lookuptable.h @@ -80,15 +80,21 @@ asm volatile ( \ #else //_NO_ASM -// NOTE: currently not implemented -void MultiU16X8toH16(unsigned short& intRes, unsigned char& charIn1, unsigned short& intIn2); -void MultiU24X24toH16(uint16_t& intRes, int32_t& longIn1, long& longIn2); +static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2) +{ + intRes = ((uint32_t)charIn1 * (uint32_t)intIn2) >> 16; +} + +static inline void MultiU24X24toH16(uint16_t& intRes, uint32_t& longIn1, uint32_t& longIn2) +{ + intRes = ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24; +} #endif //_NO_ASM FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) { - unsigned short timer; + uint16_t timer; if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times @@ -108,7 +114,7 @@ FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) if(step_rate >= (8*256)){ // higher step rate unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; unsigned char tmp_step_rate = (step_rate & 0x00ff); - unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); + uint16_t gain = (uint16_t)pgm_read_word_near(table_address+2); MultiU16X8toH16(timer, tmp_step_rate, gain); timer = (unsigned short)pgm_read_word_near(table_address) - timer; } diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index de250ec97..7c44d791b 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -71,8 +71,7 @@ static dda_isteps_t counter_z, counter_e; volatile dda_usteps_t step_events_completed; // The number of step events executed in the current block -static int32_t acceleration_time, deceleration_time; -//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; +static uint32_t acceleration_time, deceleration_time; static uint16_t acc_step_rate; // needed for deccelaration start point static uint8_t step_loops; static uint16_t OCR1A_nominal; @@ -125,7 +124,7 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; static uint16_t main_Rate; static uint16_t eISR_Rate; - static uint16_t eISR_Err; + static uint32_t eISR_Err; static uint16_t current_adv_steps; static uint16_t target_adv_steps; @@ -234,7 +233,7 @@ void invert_z_endstop(bool endstop_invert) // The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates // first block->accelerate_until step_events_completed, then keeps going at constant speed until // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. -// The slope of acceleration is calculated with the leib ramp alghorithm. +// The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far. // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. @@ -348,10 +347,7 @@ FORCE_INLINE void stepper_next_block() #ifdef LIN_ADVANCE if (current_block->use_advance_lead) { - e_step_loops = current_block->advance_step_loops; target_adv_steps = current_block->max_adv_steps; - } else { - e_step_loops = 1; } e_steps = 0; nextAdvanceISR = ADV_NEVER; @@ -736,38 +732,30 @@ FORCE_INLINE uint16_t fastdiv(uint16_t q, uint8_t d) FORCE_INLINE void advance_spread(uint16_t timer) { - if(eISR_Err > timer) + eISR_Err += timer; + + uint8_t ticks = 0; + while(eISR_Err >= current_block->advance_rate) + { + ++ticks; + eISR_Err -= current_block->advance_rate; + } + if(!ticks) { - // advance-step skipped - eISR_Err -= timer; eISR_Rate = timer; nextAdvanceISR = timer; return; } - // at least one step - uint8_t ticks = 1; - uint32_t block = current_block->advance_rate; - uint16_t max_t = timer - eISR_Err; - while (block < max_t) - { - ++ticks; - block += current_block->advance_rate; - } - if (block > timer) - eISR_Err += block - timer; - else - eISR_Err -= timer - block; - - if (ticks <= 4) - eISR_Rate = fastdiv(timer, ticks); + if (ticks <= 3) + eISR_Rate = fastdiv(timer, ticks + 1); else { // >4 ticks are still possible on slow moves - eISR_Rate = timer / ticks; + eISR_Rate = timer / (ticks + 1); } - nextAdvanceISR = eISR_Rate / 2; + nextAdvanceISR = eISR_Rate; } #endif @@ -799,7 +787,7 @@ FORCE_INLINE void isr() { // 25.12us for acceleration / deceleration. { //WRITE_NC(LOGIC_ANALYZER_CH1, true); - if (step_events_completed.wide <= (unsigned long int)current_block->accelerate_until) { + if (step_events_completed.wide <= current_block->accelerate_until) { // v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); acc_step_rate += uint16_t(current_block->initial_rate); @@ -812,19 +800,29 @@ FORCE_INLINE void isr() { acceleration_time += timer; #ifdef LIN_ADVANCE if (current_block->use_advance_lead) { - if (step_events_completed.wide <= (unsigned long int)step_loops) + if (step_events_completed.wide <= (unsigned long int)step_loops) { la_state = ADV_INIT | ADV_ACC_VARY; + if (e_extruding && current_adv_steps > target_adv_steps) + target_adv_steps = current_adv_steps; + } } #endif } - else if (step_events_completed.wide > (unsigned long int)current_block->decelerate_after) { + else if (step_events_completed.wide > current_block->decelerate_after) { uint16_t step_rate; MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - if ((step_rate & 0x8000) || step_rate < uint16_t(current_block->final_rate)) { - // Result is negative or too small. - step_rate = uint16_t(current_block->final_rate); + + if (step_rate > acc_step_rate) { // Check step_rate stays positive + step_rate = uint16_t(current_block->final_rate); } + else { + step_rate = acc_step_rate - step_rate; // Decelerate from acceleration end point. + + // lower limit + if (step_rate < current_block->final_rate) + step_rate = uint16_t(current_block->final_rate); + } + // Step_rate to timer interval. uint16_t timer = calc_timer(step_rate, step_loops); _NEXT_ISR(timer); @@ -832,9 +830,11 @@ FORCE_INLINE void isr() { #ifdef LIN_ADVANCE if (current_block->use_advance_lead) { - if (step_events_completed.wide <= (unsigned long int)current_block->decelerate_after + step_loops) { + if (step_events_completed.wide <= current_block->decelerate_after + step_loops) { target_adv_steps = current_block->final_adv_steps; la_state = ADV_INIT | ADV_ACC_VARY; + if (e_extruding && current_adv_steps < target_adv_steps) + target_adv_steps = current_adv_steps; } } #endif @@ -848,12 +848,12 @@ FORCE_INLINE void isr() { #ifdef LIN_ADVANCE if(current_block->use_advance_lead) { - if (!nextAdvanceISR) { - // Due to E-jerk, there can be discontinuities in pressure state where an - // acceleration or deceleration can be skipped or joined with the previous block. - // If LA was not previously active, re-check the pressure level - la_state = ADV_INIT; - } + // Due to E-jerk, there can be discontinuities in pressure state where an + // acceleration or deceleration can be skipped or joined with the previous block. + // If LA was not previously active, re-check the pressure level + la_state = ADV_INIT; + if (e_extruding) + target_adv_steps = current_adv_steps; } #endif } @@ -865,14 +865,21 @@ FORCE_INLINE void isr() { #ifdef LIN_ADVANCE // avoid multiple instances or function calls to advance_spread if (la_state & ADV_INIT) { + LA_phase = -1; + if (current_adv_steps == target_adv_steps) { - // nothing to be done in this phase + // nothing to be done in this phase, cancel any pending eisr la_state = 0; + nextAdvanceISR = ADV_NEVER; } else { - eISR_Err = current_block->advance_rate / 4; + // reset error and iterations per loop for this phase + eISR_Err = current_block->advance_rate; + e_step_loops = current_block->advance_step_loops; + if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) { // LA could reverse the direction of extrusion in this phase + eISR_Err += current_block->advance_rate; LA_phase = 0; } } @@ -882,11 +889,13 @@ FORCE_INLINE void isr() { advance_spread(main_Rate); if (LA_phase >= 0) { if (step_loops == e_step_loops) - LA_phase = (eISR_Rate > main_Rate); + LA_phase = (current_block->advance_rate < main_Rate); else { // avoid overflow through division. warning: we need to _guarantee_ step_loops // and e_step_loops are <= 4 due to fastdiv's limit - LA_phase = (fastdiv(eISR_Rate, step_loops) > fastdiv(main_Rate, e_step_loops)); + auto adv_rate_n = fastdiv(current_block->advance_rate, step_loops); + auto main_rate_n = fastdiv(main_Rate, e_step_loops); + LA_phase = (adv_rate_n < main_rate_n); } } } @@ -928,26 +937,34 @@ FORCE_INLINE void isr() { FORCE_INLINE void advance_isr() { if (current_adv_steps > target_adv_steps) { // decompression + if (e_step_loops != 1) { + uint16_t d_steps = current_adv_steps - target_adv_steps; + if (d_steps < e_step_loops) + e_step_loops = d_steps; + } e_steps -= e_step_loops; if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); - if(current_adv_steps > e_step_loops) - current_adv_steps -= e_step_loops; - else - current_adv_steps = 0; - nextAdvanceISR = eISR_Rate; + current_adv_steps -= e_step_loops; } else if (current_adv_steps < target_adv_steps) { // compression + if (e_step_loops != 1) { + uint16_t d_steps = target_adv_steps - current_adv_steps; + if (d_steps < e_step_loops) + e_step_loops = d_steps; + } e_steps += e_step_loops; if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR); current_adv_steps += e_step_loops; - nextAdvanceISR = eISR_Rate; } - else { + + if (current_adv_steps == target_adv_steps) { // advance steps completed nextAdvanceISR = ADV_NEVER; - LA_phase = -1; - e_step_loops = 1; + } + else { + // schedule another tick + nextAdvanceISR = eISR_Rate; } } @@ -1017,7 +1034,7 @@ FORCE_INLINE void advance_isr_scheduler() { // Schedule the next closest tick, ignoring advance if scheduled too // soon in order to avoid skewing the regular stepper acceleration - if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + TCNT1 + 40) < nextMainISR) + if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + 40) < nextMainISR) OCR1A = nextAdvanceISR; else OCR1A = nextMainISR; diff --git a/Firmware/system_timer.h b/Firmware/system_timer.h index 626e82348..9906460ae 100644 --- a/Firmware/system_timer.h +++ b/Firmware/system_timer.h @@ -8,11 +8,12 @@ #ifdef SYSTEM_TIMER_2 #include "timer02.h" +#include "tone04.h" #define _millis millis2 #define _micros micros2 #define _delay delay2 -#define _tone tone -#define _noTone noTone +#define _tone tone4 +#define _noTone noTone4 #define timer02_set_pwm0(pwm0) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index f6f8f3206..cb4fc8aee 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -143,14 +143,22 @@ static volatile bool temp_meas_ready = false; #ifdef FAN_SOFT_PWM static unsigned char soft_pwm_fan; #endif -#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1) - unsigned long extruder_autofan_last_check = _millis(); - uint8_t fanSpeedBckp = 255; - bool fan_measuring = false; -#endif +uint8_t fanSpeedBckp = 255; + +#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) + unsigned long extruder_autofan_last_check = _millis(); + + bool fan_measuring = false; + uint8_t fanState = 0; +#ifdef EXTRUDER_ALTFAN_DETECT + struct + { + uint8_t isAltfan : 1; + uint8_t altfanOverride : 1; + } altfanStatus; +#endif //EXTRUDER_ALTFAN_DETECT +#endif #if EXTRUDERS > 3 @@ -176,6 +184,12 @@ static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP; #ifdef BED_MAXTEMP static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP; #endif +#ifdef AMBIENT_MINTEMP +static int ambient_minttemp_raw = AMBIENT_RAW_LO_TEMP; +#endif +#ifdef AMBIENT_MAXTEMP +static int ambient_maxttemp_raw = AMBIENT_RAW_HI_TEMP; +#endif static void *heater_ttbl_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( (void *)HEATER_0_TEMPTABLE, (void *)HEATER_1_TEMPTABLE, (void *)HEATER_2_TEMPTABLE ); static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN ); @@ -210,6 +224,56 @@ static void temp_runaway_check(int _heater_id, float _target_temperature, float static void temp_runaway_stop(bool isPreheat, bool isBed); #endif +#ifdef EXTRUDER_ALTFAN_DETECT +ISR(INT6_vect) { + fan_edge_counter[0]++; +} + +bool extruder_altfan_detect() +{ + setExtruderAutoFanState(3); + + SET_INPUT(TACH_0); + + uint8_t overrideVal = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE); + if (overrideVal == EEPROM_EMPTY_VALUE) + { + overrideVal = (calibration_status() == CALIBRATION_STATUS_CALIBRATED) ? 1 : 0; + eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, overrideVal); + } + altfanStatus.altfanOverride = overrideVal; + + CRITICAL_SECTION_START; + EICRB &= ~(1 << ISC61); + EICRB |= (1 << ISC60); + EIMSK |= (1 << INT6); + fan_edge_counter[0] = 0; + CRITICAL_SECTION_END; + extruder_autofan_last_check = _millis(); + + _delay(1000); + + EIMSK &= ~(1 << INT6); + + countFanSpeed(); + altfanStatus.isAltfan = fan_speed[0] > 100; + setExtruderAutoFanState(1); + return altfanStatus.isAltfan; +} + +void altfanOverride_toggle() +{ + altfanStatus.altfanOverride = !altfanStatus.altfanOverride; + eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanStatus.altfanOverride); +} + +bool altfanOverride_get() +{ + return altfanStatus.altfanOverride; +} + +#endif //EXTRUDER_ALTFAN_DETECT + // return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on') bool checkAllHotends(void) { @@ -239,9 +303,7 @@ bool checkAllHotends(void) const uint8_t safety_check_cycles_count = (extruder < 0) ? 45 : 10; //10 cycles / 20s delay for extruder and 45 cycles / 90s for heatbed float temp_ambient; -#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1) +#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) unsigned long extruder_autofan_last_check = _millis(); #endif @@ -289,9 +351,7 @@ bool checkAllHotends(void) max=max(max,input); min=min(min,input); - #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1) + #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) if(_millis() - extruder_autofan_last_check > 2500) { checkExtruderAutoFans(); extruder_autofan_last_check = _millis(); @@ -447,29 +507,31 @@ int getHeaterPower(int heater) { return soft_pwm[heater]; } -#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1) +#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) #if defined(FAN_PIN) && FAN_PIN > -1 #if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN #error "You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN" #endif - #if EXTRUDER_1_AUTO_FAN_PIN == FAN_PIN - #error "You cannot set EXTRUDER_1_AUTO_FAN_PIN equal to FAN_PIN" - #endif - #if EXTRUDER_2_AUTO_FAN_PIN == FAN_PIN - #error "You cannot set EXTRUDER_2_AUTO_FAN_PIN equal to FAN_PIN" - #endif - #endif + #endif -void setExtruderAutoFanState(int pin, bool state) +void setExtruderAutoFanState(uint8_t state) { - unsigned char newFanSpeed = (state != 0) ? EXTRUDER_AUTO_FAN_SPEED : 0; - // this idiom allows both digital and PWM fan outputs (see M42 handling). - pinMode(pin, OUTPUT); - digitalWrite(pin, newFanSpeed); - //analogWrite(pin, newFanSpeed); + //If bit 1 is set (0x02), then the extruder fan speed won't be adjusted according to temperature. Useful for forcing + //the fan to either On or Off during certain tests/errors. + + fanState = state; + uint8_t newFanSpeed = 0; + if (fanState & 0x01) + { +#ifdef EXTRUDER_ALTFAN_DETECT + if (altfanStatus.isAltfan && !altfanStatus.altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT; + else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; +#else //EXTRUDER_ALTFAN_DETECT + newFanSpeed = EXTRUDER_AUTO_FAN_SPEED; +#endif //EXTRUDER_ALTFAN_DETECT + } + timer4_set_fan0(newFanSpeed); } #if (defined(FANCHECK) && (((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1))))) @@ -503,7 +565,7 @@ void checkFanSpeed() fans_check_enabled = (eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED) > 0); static unsigned char fan_speed_errors[2] = { 0,0 }; #if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 >-1)) - if ((fan_speed[0] == 0) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;} + if ((fan_speed[0] < 20) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;} else{ fan_speed_errors[0] = 0; host_keepalive(); @@ -577,47 +639,14 @@ void fanSpeedError(unsigned char _fan) { void checkExtruderAutoFans() { - uint8_t fanState = 0; - - // which fan pins need to be turned on? - #if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1 - if (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE) - fanState |= 1; - #endif - #if defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1 - if (current_temperature[1] > EXTRUDER_AUTO_FAN_TEMPERATURE) - { - if (EXTRUDER_1_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN) - fanState |= 1; - else - fanState |= 2; - } - #endif - #if defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1 - if (current_temperature[2] > EXTRUDER_AUTO_FAN_TEMPERATURE) - { - if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN) - fanState |= 1; - else if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN) - fanState |= 2; - else - fanState |= 4; - } - #endif - - // update extruder auto fan states - #if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1 - setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, (fanState & 1) != 0); - #endif - #if defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1 - if (EXTRUDER_1_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN) - setExtruderAutoFanState(EXTRUDER_1_AUTO_FAN_PIN, (fanState & 2) != 0); - #endif - #if defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1 - if (EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN - && EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN) - setExtruderAutoFanState(EXTRUDER_2_AUTO_FAN_PIN, (fanState & 4) != 0); - #endif +#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1 + if (!(fanState & 0x02)) + { + fanState &= ~1; + fanState |= current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE; + } + setExtruderAutoFanState(fanState); +#endif } #endif // any extruder auto fan pins set @@ -641,6 +670,7 @@ void manage_heater() return; // more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms) + // ADC values need to be converted before checking: converted values are later used in MINTEMP updateTemperaturesFromRawValues(); check_max_temp(); @@ -737,9 +767,7 @@ void manage_heater() #define FAN_CHECK_DURATION 100 //100ms #ifndef DEBUG_DISABLE_FANCHECK - #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \ - (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1) + #if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) #ifdef FAN_SOFT_PWM #ifdef FANCHECK @@ -1098,7 +1126,9 @@ void tp_init() timer0_init(); OCR2B = 128; - TIMSK2 |= (1< BED_MAXTEMP) { @@ -1186,6 +1214,25 @@ void tp_init() #endif } #endif //BED_MAXTEMP + +#ifdef AMBIENT_MINTEMP + while(analog2tempAmbient(ambient_minttemp_raw) < AMBIENT_MINTEMP) { +#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP + ambient_minttemp_raw += OVERSAMPLENR; +#else + ambient_minttemp_raw -= OVERSAMPLENR; +#endif + } +#endif //AMBIENT_MINTEMP +#ifdef AMBIENT_MAXTEMP + while(analog2tempAmbient(ambient_maxttemp_raw) > AMBIENT_MAXTEMP) { +#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP + ambient_maxttemp_raw -= OVERSAMPLENR; +#else + ambient_maxttemp_raw += OVERSAMPLENR; +#endif + } +#endif //AMBIENT_MAXTEMP } #if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0) @@ -1357,9 +1404,11 @@ void temp_runaway_stop(bool isPreheat, bool isBed) isBed ? LCD_ALERTMESSAGEPGM("BED PREHEAT ERROR") : LCD_ALERTMESSAGEPGM("PREHEAT ERROR"); SERIAL_ERROR_START; isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)"); - SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); +#ifdef EXTRUDER_ALTFAN_DETECT + altfanStatus.altfanOverride = 1; //full speed +#endif //EXTRUDER_ALTFAN_DETECT + setExtruderAutoFanState(3); SET_OUTPUT(FAN_PIN); - WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1); #ifdef FAN_SOFT_PWM fanSpeedSoftPwm = 255; #else //FAN_SOFT_PWM @@ -1427,26 +1476,55 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_ //! to prevent flicker and improve speed uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; + +//! update the current temperature error message +//! @param type short error abbreviation (PROGMEM) +//! @param func optional lcd update function (lcd_setalertstatus when first setting the error) +void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) = lcd_updatestatus) +{ + char msg[LCD_WIDTH]; + strcpy_P(msg, PSTR("Err: ")); + strcat_P(msg, type); + (*func)(msg); +} + +//! signal a temperature error on both the lcd and serial +//! @param type short error abbreviation (PROGMEM) +//! @param e optional extruder index for hotend errors +void temp_error_messagepgm(const char* PROGMEM type, uint8_t e = EXTRUDERS) +{ + temp_update_messagepgm(type, lcd_setalertstatus); + + SERIAL_ERROR_START; + + if(e != EXTRUDERS) { + SERIAL_ERROR((int)e); + SERIAL_ERRORPGM(": "); + } + + SERIAL_ERRORPGM("Heaters switched off. "); + SERIAL_ERRORRPGM(type); + SERIAL_ERRORLNPGM(" triggered!"); +} + + void max_temp_error(uint8_t e) { disable_heater(); if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); - LCD_ALERTMESSAGEPGM("Err: MAXTEMP"); + temp_error_messagepgm(PSTR("MAXTEMP"), e); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); - - - #endif - SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); + SET_OUTPUT(FAN_PIN); SET_OUTPUT(BEEPER); WRITE(FAN_PIN, 1); - WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1); WRITE(BEEPER, 1); +#ifdef EXTRUDER_ALTFAN_DETECT + altfanStatus.altfanOverride = 1; //full speed +#endif //EXTRUDER_ALTFAN_DETECT + setExtruderAutoFanState(3); // fanSpeed will consumed by the check_axes_activity() routine. fanSpeed=255; if (farm_mode) { prusa_statistics(93); } @@ -1456,18 +1534,15 @@ void min_temp_error(uint8_t e) { #ifdef DEBUG_DISABLE_MINTEMP return; #endif -//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; disable_heater(); - static const char err[] PROGMEM = "Err: MINTEMP"; +//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; + static const char err[] PROGMEM = "MINTEMP"; if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); - lcd_setalertstatuspgm(err); + temp_error_messagepgm(err, e); last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; } else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) // we are already stopped due to some error, only update the status message without flickering - lcd_updatestatuspgm(err); + temp_update_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE @@ -1482,37 +1557,27 @@ void min_temp_error(uint8_t e) { } void bed_max_temp_error(void) { -#if HEATER_BED_PIN > -1 - //WRITE(HEATER_BED_PIN, 0); -#endif + disable_heater(); if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !"); - LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED"); + temp_error_messagepgm(PSTR("MAXTEMP BED")); } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); #endif - } void bed_min_temp_error(void) { #ifdef DEBUG_DISABLE_MINTEMP return; #endif -//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; -#if HEATER_BED_PIN > -1 - //WRITE(HEATER_BED_PIN, 0); -#endif - static const char err[] PROGMEM = "Err: MINTEMP BED"; + disable_heater(); + static const char err[] PROGMEM = "MINTEMP BED"; if(IsStopped() == false) { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MINTEMP triggered !"); - lcd_setalertstatuspgm(err); + temp_error_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; } else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) // we are already stopped due to some error, only update the status message without flickering - lcd_updatestatuspgm(err); + temp_update_messagepgm(err); last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE @@ -1520,6 +1585,33 @@ void bed_min_temp_error(void) { #endif } + +#ifdef AMBIENT_THERMISTOR +void ambient_max_temp_error(void) { + disable_heater(); + if(IsStopped() == false) { + temp_error_messagepgm(PSTR("MAXTEMP AMB")); + } +#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE + Stop(); +#endif +} + +void ambient_min_temp_error(void) { +#ifdef DEBUG_DISABLE_MINTEMP + return; +#endif + disable_heater(); + if(IsStopped() == false) { + temp_error_messagepgm(PSTR("MINTEMP AMB")); + } +#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE + Stop(); +#endif +} +#endif + + #ifdef HEATER_0_USES_MAX6675 #define MAX6675_HEAT_INTERVAL 250 long max6675_previous_millis = MAX6675_HEAT_INTERVAL; @@ -1604,18 +1696,8 @@ void adc_ready(void) //callback from adc when sampling finished } // extern "C" -// Timer2 (originaly timer0) is shared with millies -#ifdef SYSTEM_TIMER_2 -ISR(TIMER2_COMPB_vect) -#else //SYSTEM_TIMER_2 -ISR(TIMER0_COMPB_vect) -#endif //SYSTEM_TIMER_2 +FORCE_INLINE static void temperature_isr() { - static bool _lock = false; - if (_lock) return; - _lock = true; - asm("sei"); - if (!temp_meas_ready) adc_cycle(); lcd_buttons_update(); @@ -1981,8 +2063,24 @@ ISR(TIMER0_COMPB_vect) #if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1)) check_fans(); #endif //(defined(TACH_0)) +} - _lock = false; +// Timer2 (originaly timer0) is shared with millies +#ifdef SYSTEM_TIMER_2 +ISR(TIMER2_COMPB_vect) +#else //SYSTEM_TIMER_2 +ISR(TIMER0_COMPB_vect) +#endif //SYSTEM_TIMER_2 +{ + static bool _lock = false; + if (!_lock) + { + _lock = true; + sei(); + temperature_isr(); + cli(); + _lock = false; + } } void check_max_temp() @@ -2002,11 +2100,19 @@ void check_max_temp() #else if (current_temperature_bed_raw >= bed_maxttemp_raw) { #endif - target_temperature_bed = 0; bed_max_temp_error(); } #endif - +//ambient +#if defined(AMBIENT_MAXTEMP) && (TEMP_SENSOR_AMBIENT != 0) +#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP + if (current_temperature_raw_ambient <= ambient_maxttemp_raw) { +#else + if (current_temperature_raw_ambient >= ambient_maxttemp_raw) { +#endif + ambient_max_temp_error(); + } +#endif } //! number of repeating the same state with consecutive step() calls //! used to slow down text switching @@ -2101,12 +2207,32 @@ void check_min_temp_bed() } } +#ifdef AMBIENT_MINTEMP +void check_min_temp_ambient() +{ +#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP + if (current_temperature_raw_ambient >= ambient_minttemp_raw) { +#else + if (current_temperature_raw_ambient <= ambient_minttemp_raw) { +#endif + ambient_min_temp_error(); + } +} +#endif + void check_min_temp() { static bool bCheckingOnHeater=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp) static bool bCheckingOnBed=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp) #ifdef AMBIENT_THERMISTOR -if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type, so operator is ">" ;-) +#ifdef AMBIENT_MINTEMP +check_min_temp_ambient(); +#endif +#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP +if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type +#else +if(current_temperature_raw_ambient=<(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) +#endif { // ambient temperature is low #endif //AMBIENT_THERMISTOR // *** 'common' part of code for MK2.5 & MK3 @@ -2194,4 +2320,20 @@ float unscalePID_d(float d) #endif //PIDTEMP +#ifdef PINDA_THERMISTOR +//! @brief PINDA thermistor detected +//! +//! @retval true firmware should do temperature compensation and allow calibration +//! @retval false PINDA thermistor is not detected, disable temperature compensation and calibration +//! +bool has_temperature_compensation() +{ +#ifdef DETECT_SUPERPINDA + return (current_temperature_pinda >= PINDA_MINTEMP) ? true : false; +#else + return true; +#endif +} +#endif //PINDA_THERMISTOR + diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 7b7637b11..da88a53c0 100755 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -63,6 +63,7 @@ extern float current_temperature_bed; #ifdef PINDA_THERMISTOR extern uint16_t current_temperature_raw_pinda; extern float current_temperature_pinda; +bool has_temperature_compensation(); #endif #ifdef AMBIENT_THERMISTOR @@ -245,7 +246,7 @@ FORCE_INLINE void autotempShutdown(){ void PID_autotune(float temp, int extruder, int ncycles); -void setExtruderAutoFanState(int pin, bool state); +void setExtruderAutoFanState(uint8_t state); void checkExtruderAutoFans(); @@ -270,10 +271,14 @@ void check_fans(); void check_min_temp(); void check_max_temp(); - -#endif +#ifdef EXTRUDER_ALTFAN_DETECT + extern bool extruder_altfan_detect(); + extern void altfanOverride_toggle(); + extern bool altfanOverride_get(); +#endif //EXTRUDER_ALTFAN_DETECT extern unsigned long extruder_autofan_last_check; extern uint8_t fanSpeedBckp; extern bool fan_measuring; +#endif diff --git a/Firmware/thermistortables.h b/Firmware/thermistortables.h index dc934ccfd..721c6b359 100644 --- a/Firmware/thermistortables.h +++ b/Firmware/thermistortables.h @@ -1213,6 +1213,8 @@ const short temptable_1047[][2] PROGMEM = { #endif #if (THERMISTORAMBIENT == 2000) //100k thermistor NTCG104LH104JT1 +# define AMBIENT_RAW_HI_TEMP 0 +# define AMBIENT_RAW_LO_TEMP 16383 const short temptable_2000[][2] PROGMEM = { // Source: https://product.tdk.com/info/en/catalog/datasheets/503021/tpd_ntc-thermistor_ntcg_en.pdf // Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance diff --git a/Firmware/tone04.c b/Firmware/tone04.c new file mode 100644 index 000000000..41f904a91 --- /dev/null +++ b/Firmware/tone04.c @@ -0,0 +1,126 @@ +//tone04.c +// use atmega timer4 as main tone timer instead of timer2 +// timer2 is used for System timer. + +#include "system_timer.h" +#include "Configuration_prusa.h" + +#ifdef SYSTEM_TIMER_2 + +#include +#include +#include "pins.h" + +#ifndef CRITICAL_SECTION_START + #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); + #define CRITICAL_SECTION_END SREG = _sreg; +#endif //CRITICAL_SECTION_START + + +#include "fastio.h" + +void timer4_init(void) +{ + CRITICAL_SECTION_START; + + SET_OUTPUT(BEEPER); + WRITE(BEEPER, LOW); + + SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); + + // Set timer mode 9 (PWM,Phase and Frequency Correct) + // Prescaler is CLK/1024 + // Output compare is disabled on all timer pins + // Input capture is disabled + // All interrupts are disabled + TCCR4A = (1 << WGM40); + TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40); + OCR4A = 255; + OCR4B = 255; + OCR4C = 255; + TIMSK4 = 0; + + CRITICAL_SECTION_END; +} + +#ifdef EXTRUDER_0_AUTO_FAN_PIN +void timer4_set_fan0(uint8_t duty) +{ + if (duty == 0 || duty == 255) + { + // We use digital logic if the duty cycle is 0% or 100% + TCCR4A &= ~(1 << COM4C1); + OCR4C = 0; + WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty); + } + else + { + // Use the timer for fan speed. Enable the timer compare output and set the duty cycle. + // This function also handles the impossible scenario of a fan speed change during a Tone. + // Better be safe than sorry. + CRITICAL_SECTION_START; + // Enable the PWM output on the fan pin. + TCCR4A |= (1 << COM4C1); + OCR4C = (((uint32_t)duty) * ((uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255))) / ((uint32_t)255); + CRITICAL_SECTION_END; + } +} +#endif //EXTRUDER_0_AUTO_FAN_PIN + +// Because of the timer mode change, we need two interrupts. We could also try to assume that the frequency is x2 +// and use a TOGGLE(), but this seems to work well enough so I left it as it is now. +ISR(TIMER4_COMPA_vect) +{ + WRITE(BEEPER, 1); +} + +ISR(TIMER4_OVF_vect) +{ + WRITE(BEEPER, 0); +} + +void tone4(__attribute__((unused)) uint8_t _pin, uint16_t frequency) +{ + //this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only + uint8_t prescalarbits = 0b001; + uint32_t ocr = F_CPU / frequency / 2 - 1; + + if (ocr > 0xffff) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = 0b011; + } + + CRITICAL_SECTION_START; + // Set calcualted prescaler + TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; +#ifdef EXTRUDER_0_AUTO_FAN_PIN + // Scale the fan PWM duty cycle so that it remains constant, but at the tone frequency + OCR4C = (((uint32_t)OCR4C) * ocr) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255); +#endif //EXTRUDER_0_AUTO_FAN_PIN + // Set calcualted ocr + OCR4A = ocr; + // Enable Output compare A interrupt and timer overflow interrupt + TIMSK4 |= (1 << OCIE4A) | (1 << TOIE4); + CRITICAL_SECTION_END; +} + +void noTone4(__attribute__((unused)) uint8_t _pin) +{ + CRITICAL_SECTION_START; + // Revert prescaler to CLK/1024 + TCCR4B = (TCCR4B & 0b11111000) | (1 << CS42) | (1 << CS40); +#ifdef EXTRUDER_0_AUTO_FAN_PIN + // Scale the fan OCR back to the original value. + OCR4C = (((uint32_t)OCR4C) * (uint32_t)255) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255); +#endif //EXTRUDER_0_AUTO_FAN_PIN + OCR4A = 255; + // Disable Output compare A interrupt and timer overflow interrupt + TIMSK4 &= ~((1 << OCIE4A) | (1 << TOIE4)); + CRITICAL_SECTION_END; + // Turn beeper off if it was on when noTone was called + WRITE(BEEPER, 0); +} + + +#endif //SYSTEM_TIMER_2 diff --git a/Firmware/tone04.h b/Firmware/tone04.h new file mode 100644 index 000000000..f11eeb6c6 --- /dev/null +++ b/Firmware/tone04.h @@ -0,0 +1,25 @@ +//tone04.h +// use atmega timer4 as main tone timer instead of timer2 +// timer2 is used for System timer. +#ifndef TIMER04_H +#define TIMER04_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif //defined(__cplusplus) + +extern void timer4_init(void); + +extern void timer4_set_fan0(uint8_t duty); + +extern void tone4(uint8_t _pin, uint16_t frequency); + +extern void noTone4(uint8_t _pin); + +#if defined(__cplusplus) +} +#endif //defined(__cplusplus) + +#endif //TIMER02_H diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 9f99f7a20..92dd1c363 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -818,6 +818,36 @@ void lcd_status_screen() // NOT static due to using ins } } +#ifdef ULTIPANEL_FEEDMULTIPLY + // Dead zone at 100% feedrate + if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) || + (feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100)) + { + lcd_encoder = 0; + feedmultiply = 100; + } + if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE) + { + feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE; + lcd_encoder = 0; + } + else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE) + { + feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE; + lcd_encoder = 0; + } + else if (feedmultiply != 100) + { + feedmultiply += int(lcd_encoder); + lcd_encoder = 0; + } +#endif //ULTIPANEL_FEEDMULTIPLY + + if (feedmultiply < 10) + feedmultiply = 10; + else if (feedmultiply > 999) + feedmultiply = 999; + if (lcd_status_update_delay) lcd_status_update_delay--; else @@ -894,36 +924,6 @@ void lcd_status_screen() // NOT static due to using ins menu_submenu(lcd_main_menu); lcd_refresh(); // to maybe revive the LCD if static electricity killed it. } - -#ifdef ULTIPANEL_FEEDMULTIPLY - // Dead zone at 100% feedrate - if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) || - (feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100)) - { - lcd_encoder = 0; - feedmultiply = 100; - } - if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE) - { - feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE; - lcd_encoder = 0; - } - else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE) - { - feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE; - lcd_encoder = 0; - } - else if (feedmultiply != 100) - { - feedmultiply += int(lcd_encoder); - lcd_encoder = 0; - } -#endif //ULTIPANEL_FEEDMULTIPLY - - if (feedmultiply < 10) - feedmultiply = 10; - else if (feedmultiply > 999) - feedmultiply = 999; } void lcd_commands() @@ -1943,6 +1943,7 @@ static void lcd_support_menu() sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"), _md->ip[0], _md->ip[1], _md->ip[2], _md->ip[3]); + } else if (_md->is_flash_air && _md->ip[0] == 0 && _md->ip[1] == 0 && _md->ip[2] == 0 && _md->ip[3] == 0 && @@ -1983,18 +1984,7 @@ static void lcd_support_menu() #ifdef IR_SENSOR_ANALOG MENU_ITEM_BACK_P(STR_SEPARATOR); MENU_ITEM_BACK_P(PSTR("Fil. sensor v.:")); - switch(oFsensorPCB) - { - case ClFsensorPCB::_Old: - MENU_ITEM_BACK_P(_T(MSG_03_OR_OLDER)); - break; - case ClFsensorPCB::_Rev04: - MENU_ITEM_BACK_P(_T(MSG_04_OR_NEWER)); - break; - case ClFsensorPCB::_Undef: - default: - MENU_ITEM_BACK_P(PSTR(" unknown state")); - } + MENU_ITEM_BACK_P(FsensorIRVersionText()); #endif // IR_SENSOR_ANALOG MENU_ITEM_BACK_P(STR_SEPARATOR); @@ -2038,6 +2028,7 @@ static void lcd_support_menu() MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN + #ifdef DEBUG_BUILD MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1 #endif /* DEBUG_BUILD */ @@ -2324,6 +2315,12 @@ static void mFilamentItem_ASA() mFilamentItem(ASA_PREHEAT_HOTEND_TEMP, ASA_PREHEAT_HPB_TEMP); } +static void mFilamentItem_PC() +{ + bFilamentPreheatState = false; + mFilamentItem(PC_PREHEAT_HOTEND_TEMP, PC_PREHEAT_HPB_TEMP); +} + static void mFilamentItem_ABS() { bFilamentPreheatState = false; @@ -2383,6 +2380,7 @@ void lcd_generic_preheat_menu() MENU_ITEM_SUBMENU_P(PSTR("PLA - " STRINGIFY(PLA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PLA_PREHEAT_HPB_TEMP)),mFilamentItem_PLA); MENU_ITEM_SUBMENU_P(PSTR("PET - " STRINGIFY(PET_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PET_PREHEAT_HPB_TEMP)),mFilamentItem_PET); MENU_ITEM_SUBMENU_P(PSTR("ASA - " STRINGIFY(ASA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ASA_PREHEAT_HPB_TEMP)),mFilamentItem_ASA); + MENU_ITEM_SUBMENU_P(PSTR("PC - " STRINGIFY(PC_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PC_PREHEAT_HPB_TEMP)),mFilamentItem_PC); MENU_ITEM_SUBMENU_P(PSTR("ABS - " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)),mFilamentItem_ABS); MENU_ITEM_SUBMENU_P(PSTR("HIPS - " STRINGIFY(HIPS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(HIPS_PREHEAT_HPB_TEMP)),mFilamentItem_HIPS); MENU_ITEM_SUBMENU_P(PSTR("PP - " STRINGIFY(PP_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PP_PREHEAT_HPB_TEMP)),mFilamentItem_PP); @@ -2736,7 +2734,7 @@ static void _lcd_move(const char *name, int axis, int min, int max) if (max_software_endstops && current_position[axis] > max) current_position[axis] = max; lcd_encoder = 0; world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - plan_buffer_line_curposXYZE(manual_feedrate[axis] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[axis] / 60); lcd_draw_update = 1; } } @@ -2761,7 +2759,7 @@ static void lcd_move_e() { current_position[E_AXIS] += float((int)lcd_encoder) * move_menu_scale; lcd_encoder = 0; - plan_buffer_line_curposXYZE(manual_feedrate[E_AXIS] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[E_AXIS] / 60); lcd_draw_update = 1; } } @@ -3279,7 +3277,7 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z) { // Don't know where we are. Let's claim we are Z=0, so the soft end stops will not be triggered when moving up. current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); // Until confirmed by the confirmation dialog. for (;;) { @@ -3301,7 +3299,7 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z) // Only move up, whatever direction the user rotates the encoder. current_position[Z_AXIS] += fabs(lcd_encoder); lcd_encoder = 0; - plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60); } } if (lcd_clicked()) { @@ -3337,7 +3335,7 @@ calibrated: else { current_position[Z_AXIS] = Z_MAX_POS+4.f; } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); return true; canceled: @@ -3741,14 +3739,12 @@ void lcd_temp_cal_show_result(bool result) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 1); SERIAL_ECHOLNPGM("Temperature calibration done. Continue with pressing the knob."); lcd_show_fullscreen_message_and_wait_P(_T(MSG_TEMP_CALIBRATION_DONE)); - temp_cal_active = true; eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, 1); } else { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0); SERIAL_ECHOLNPGM("Temperature calibration failed. Continue with pressing the knob."); lcd_show_fullscreen_message_and_wait_P(_i("Temperature calibration failed"));////MSG_TEMP_CAL_FAILED c=20 r=8 - temp_cal_active = false; eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, 0); } lcd_update_enable(true); @@ -3855,7 +3851,7 @@ void prusa_statistics_err(char c){ } static void prusa_statistics_case0(uint8_t statnr){ - SERIAL_ECHO("{"); + SERIAL_ECHO('{'); prusa_stat_printerstatus(statnr); prusa_stat_farm_number(); prusa_stat_printinfo(); @@ -3883,7 +3879,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) { } else { - SERIAL_ECHO("{"); + SERIAL_ECHO('{'); prusa_stat_printerstatus(1); prusa_stat_farm_number(); prusa_stat_diameter(); @@ -4449,9 +4445,9 @@ void lcd_pinda_calibration_menu() } void lcd_temp_calibration_set() { + bool temp_cal_active = eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE); temp_cal_active = !temp_cal_active; eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, temp_cal_active); - st_current_init(); } #ifdef HAS_SECOND_SERIAL_PORT @@ -4709,7 +4705,7 @@ void lcd_language() static void wait_preheat() { current_position[Z_AXIS] = 100; //move in z axis to make space for loading filament - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60, active_extruder); + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); delay_keep_alive(2000); lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING)); lcd_set_custom_characters(); @@ -5416,6 +5412,7 @@ do\ }\ while (0) +#if 0 // temporarily unused static void lcd_check_gcode_set(void) { switch(oCheckGcode) @@ -5434,6 +5431,7 @@ switch(oCheckGcode) } eeprom_update_byte((uint8_t*)EEPROM_CHECK_GCODE,(uint8_t)oCheckGcode); } +#endif #define SETTINGS_GCODE \ do\ @@ -5526,6 +5524,25 @@ static void sheets_menu() void lcd_hw_setup_menu(void) // can not be "static" { + typedef struct + {// 2bytes total + int8_t status; + uint8_t experimental_menu_visibility; + } _menu_data_t; + static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); + _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); + + if (_md->status == 0 || lcd_draw_update) + { + _md->experimental_menu_visibility = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY); + if (_md->experimental_menu_visibility == EEPROM_EMPTY_VALUE) + { + _md->experimental_menu_visibility = 0; + eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, _md->experimental_menu_visibility); + } + } + + MENU_BEGIN(); MENU_ITEM_BACK_P(_T(bSettings?MSG_SETTINGS:MSG_BACK)); // i.e. default menu-item / menu-item after checking mismatch @@ -5535,8 +5552,16 @@ void lcd_hw_setup_menu(void) // can not be "static" #ifdef IR_SENSOR_ANALOG FSENSOR_ACTION_NA; - MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor); + //! Fsensor Detection isn't ready for mmu yet it is temporarily disabled. + //! @todo Don't forget to remove this as soon Fsensor Detection works with mmu + if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor); #endif //IR_SENSOR_ANALOG + + if (_md->experimental_menu_visibility) + { + MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu);////MSG_MENU_EXPERIMENTAL c=18 + } + MENU_END(); } @@ -5575,8 +5600,10 @@ static void lcd_settings_menu() #if defined (TMC2130) && defined (LINEARITY_CORRECTION) MENU_ITEM_SUBMENU_P(_i("Lin. correction"), lcd_settings_linearity_correction_menu); #endif //LINEARITY_CORRECTION && TMC2130 - - MENU_ITEM_TOGGLE_P(_T(MSG_TEMP_CALIBRATION), temp_cal_active ? _T(MSG_ON) : _T(MSG_OFF), lcd_temp_calibration_set); + if(has_temperature_compensation()) + { + MENU_ITEM_TOGGLE_P(_T(MSG_TEMP_CALIBRATION), eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE) ? _T(MSG_ON) : _T(MSG_OFF), lcd_temp_calibration_set); + } #ifdef HAS_SECOND_SERIAL_PORT MENU_ITEM_TOGGLE_P(_T(MSG_RPI_PORT), (selectedSerialPort == 0) ? _T(MSG_OFF) : _T(MSG_ON), lcd_second_serial_set); @@ -5680,7 +5707,10 @@ static void lcd_calibration_menu() //MENU_ITEM_FUNCTION_P(MSG_RESET_CALIBRATE_E, lcd_extr_cal_reset); #endif #ifndef MK1BP - MENU_ITEM_SUBMENU_P(_i("Temp. calibration"), lcd_pinda_calibration_menu);////MSG_CALIBRATION_PINDA_MENU c=17 r=1 + if(has_temperature_compensation()) + { + MENU_ITEM_SUBMENU_P(_i("Temp. calibration"), lcd_pinda_calibration_menu);////MSG_CALIBRATION_PINDA_MENU c=17 r=1 + } #endif //MK1BP } @@ -6197,13 +6227,13 @@ void unload_filament() // extr_unload2(); current_position[E_AXIS] -= 45; - plan_buffer_line_curposXYZE(5200 / 60, active_extruder); + plan_buffer_line_curposXYZE(5200 / 60); st_synchronize(); current_position[E_AXIS] -= 15; - plan_buffer_line_curposXYZE(1000 / 60, active_extruder); + plan_buffer_line_curposXYZE(1000 / 60); st_synchronize(); current_position[E_AXIS] -= 20; - plan_buffer_line_curposXYZE(1000 / 60, active_extruder); + plan_buffer_line_curposXYZE(1000 / 60); st_synchronize(); lcd_display_message_fullscreen_P(_T(MSG_PULL_OUT_FILAMENT)); @@ -6483,7 +6513,7 @@ static bool fan_error_selftest() fanSpeedSoftPwm = 255; #endif //FAN_SOFT_PWM manage_heater(); //enables print fan - setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, 1); //force enables the extruder fan untill the first manage_heater() call. + setExtruderAutoFanState(3); //force enables the extruder fan #ifdef FAN_SOFT_PWM extruder_autofan_last_check = _millis(); fan_measuring = true; @@ -6491,6 +6521,7 @@ static bool fan_error_selftest() _delay(1000); //delay_keep_alive would turn off extruder fan, because temerature is too low (maybe) manage_heater(); fanSpeed = 0; + setExtruderAutoFanState(1); //releases lock on the extruder fan #ifdef FAN_SOFT_PWM fanSpeedSoftPwm = 0; #endif //FAN_SOFT_PWM @@ -7171,13 +7202,13 @@ void lcd_print_stop() cancel_heatup = true; //unroll temperature wait loop stack. current_position[Z_AXIS] += 10; //lift Z. - plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60); if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) //if axis are homed, move to parked position. { current_position[X_AXIS] = X_CANCEL_POS; current_position[Y_AXIS] = Y_CANCEL_POS; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); } st_synchronize(); @@ -7399,8 +7430,8 @@ void lcd_belttest() #ifdef IR_SENSOR_ANALOG // called also from marlin_main.cpp -void printf_IRSensorAnalogBoardChange(bool bPCBrev04){ - printf_P(PSTR("Filament sensor board change detected: revision%S\n"), bPCBrev04 ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER)); +void printf_IRSensorAnalogBoardChange(){ + printf_P(PSTR("Filament sensor board change detected: revision%S\n"), FsensorIRVersionText()); } static bool lcd_selftest_IRsensor(bool bStandalone) @@ -7425,8 +7456,8 @@ static bool lcd_selftest_IRsensor(bool bStandalone) return(false); } if((bPCBrev04 ? 1 : 0) != (uint8_t)oFsensorPCB){ // safer then "(uint8_t)bPCBrev04" - printf_IRSensorAnalogBoardChange(bPCBrev04); oFsensorPCB=bPCBrev04 ? ClFsensorPCB::_Rev04 : ClFsensorPCB::_Old; + printf_IRSensorAnalogBoardChange(); eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB); } return(true); @@ -7434,22 +7465,26 @@ static bool lcd_selftest_IRsensor(bool bStandalone) static void lcd_detect_IRsensor(){ bool bAction; - + bool loaded; bMenuFSDetect = true; // inhibits some code inside "manage_inactivity()" - bAction = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament loaded?"), false, false); - if(bAction){ - lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action."));////c=20 r=4 + /// Check if filament is loaded. If it is loaded stop detection. + /// @todo Add autodetection with MMU2s + loaded = ! READ(IR_SENSOR_PIN); + if(loaded ){ + lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action.")); return; + } else { + lcd_show_fullscreen_message_and_wait_P(_i("Please check the IR sensor connections and filament is unloaded.")); + bAction = lcd_selftest_IRsensor(true); } - bAction = lcd_selftest_IRsensor(true); - if(bAction){ + if(bAction){ lcd_show_fullscreen_message_and_wait_P(_i("Sensor verified, remove the filament now."));////c=20 r=3 - // the fsensor board has been successfully identified, any previous "not responding" may be cleared now - fsensor_not_responding = false; + // the fsensor board has been successfully identified, any previous "not responding" may be cleared now + fsensor_not_responding = false; } else { lcd_show_fullscreen_message_and_wait_P(_i("Verification failed, remove the filament and try again."));////c=20 r=5 - // here it is unclear what to to with the fsensor_not_responding flag - } + // here it is unclear what to to with the fsensor_not_responding flag + } bMenuFSDetect=false; // de-inhibits some code inside "manage_inactivity()" } #endif //IR_SENSOR_ANALOG @@ -7465,9 +7500,17 @@ bool lcd_selftest() bool _result = true; bool _swapped_fan = false; #ifdef IR_SENSOR_ANALOG - //! Check if IR sensor is in unknown state, set it temporarily to 0.3 or older - //! @todo This has to be improved - if( oFsensorPCB == ClFsensorPCB::_Undef) eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,0); + //! Check if IR sensor is in unknown state, if so run Fsensor Detection + //! As the Fsensor Detection isn't yet ready for the mmu2s we set temporarily the IR sensor 0.3 or older for mmu2s + //! @todo Don't forget to remove this as soon Fsensor Detection works with mmu + if( oFsensorPCB == ClFsensorPCB::_Undef) { + if (!mmu_enabled) { + lcd_detect_IRsensor(); + } + else { + eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,0); + } + } #endif //IR_SENSOR_ANALOG lcd_wait_for_cool_down(); lcd_clear(); @@ -7605,7 +7648,7 @@ bool lcd_selftest() current_position[Y_AXIS] += 4; #endif //TMC2130 current_position[Z_AXIS] = current_position[Z_AXIS] + 10; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); set_destination_to_current(); _progress = lcd_selftest_screen(TestScreen::AxisZ, _progress, 3, true, 1500); @@ -7617,7 +7660,7 @@ bool lcd_selftest() //raise Z to not damage the bed during and hotend testing current_position[Z_AXIS] += 20; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); } @@ -7625,7 +7668,7 @@ bool lcd_selftest() if (_result) { current_position[Z_AXIS] = current_position[Z_AXIS] + 10; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); _progress = lcd_selftest_screen(TestScreen::Home, 0, 2, true, 0); bool bres = tmc2130_home_calibrate(X_AXIS); @@ -7675,10 +7718,12 @@ bool lcd_selftest() _progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK } #endif //PAT9125 -//#ifdef IR_SENSOR_ANALOG -#if (0) +#if 0 + // Intentionally disabled - that's why we moved the detection to runtime by just checking the two voltages. + // The idea is not to force the user to remove and insert the filament on an assembled printer. +//def IR_SENSOR_ANALOG _progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filament sensor - _result = lcd_selftest_IRsensor(); + _result = lcd_selftest_IRsensor(); if (_result) { _progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //filament sensor OK @@ -7721,7 +7766,7 @@ bool lcd_selftest() static void reset_crash_det(unsigned char axis) { current_position[axis] += 10; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_DET)) tmc2130_sg_stop_on_crash = true; } @@ -7750,7 +7795,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) { // first axis length measurement begin current_position[axis] -= (axis_length + margin); - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); @@ -7760,11 +7805,11 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) { current_position_init = st_get_position_mm(axis); current_position[axis] += 2 * margin; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); current_position[axis] += axis_length; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); @@ -7780,11 +7825,11 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) { current_position[axis] -= margin; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); current_position[axis] -= (axis_length + margin); - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); @@ -7809,7 +7854,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) { lcd_selftest_error(TestError::Axis, _error_1, ""); current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); reset_crash_det(axis); enable_endstops(true); endstops_hit_on_purpose(); @@ -7829,13 +7874,13 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) { lcd_selftest_error(TestError::Pulley, _error_1, ""); current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); reset_crash_det(axis); endstops_hit_on_purpose(); return false; } current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); reset_crash_det(axis); endstops_hit_on_purpose(); return true; @@ -7857,13 +7902,13 @@ static bool lcd_selfcheck_axis(int _axis, int _travel) if (_axis == X_AXIS) { current_position[Z_AXIS] += 17; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); } do { current_position[_axis] = current_position[_axis] - 1; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); #ifdef TMC2130 if ((READ(Z_MIN_PIN) ^ (bool)Z_MIN_ENDSTOP_INVERTING)) @@ -7943,7 +7988,7 @@ static bool lcd_selfcheck_axis(int _axis, int _travel) } } current_position[_axis] = 0; //simulate axis home to avoid negative numbers for axis position, especially Z. - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position_curposXYZE(); return _stepresult; } @@ -7966,17 +8011,17 @@ static bool lcd_selfcheck_pulleys(int axis) current_position_init = current_position[axis]; current_position[axis] += 2; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); for (i = 0; i < 5; i++) { refresh_cmd_timeout(); current_position[axis] = current_position[axis] + move; st_current_set(0, 850); //set motor current higher - plan_buffer_line_curposXYZE(200, active_extruder); + plan_buffer_line_curposXYZE(200); st_synchronize(); if (SilentModeMenu != SILENT_MODE_OFF) st_current_set(0, tmp_motor[0]); //set back to normal operation currents else st_current_set(0, tmp_motor_loud[0]); //set motor current back current_position[axis] = current_position[axis] - move; - plan_buffer_line_curposXYZE(50, active_extruder); + plan_buffer_line_curposXYZE(50); st_synchronize(); if (((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING) == 1) || ((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING) == 1)) { @@ -7993,7 +8038,7 @@ static bool lcd_selfcheck_pulleys(int axis) endstop_triggered = true; if (current_position_init - 1 <= current_position[axis] && current_position_init + 1 >= current_position[axis]) { current_position[axis] += 10; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); return(true); } @@ -8004,7 +8049,7 @@ static bool lcd_selfcheck_pulleys(int axis) } else { current_position[axis] -= 1; - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); if (_millis() > timeout_counter) { lcd_selftest_error(TestError::Pulley, (axis == 0) ? "X" : "Y", ""); @@ -8034,7 +8079,7 @@ static bool lcd_selfcheck_endstops() #endif //!TMC2130 if ((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING) == 1) current_position[2] += 10; } - plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder); + plan_buffer_line_curposXYZE(manual_feedrate[0] / 60); st_synchronize(); if ( @@ -8360,8 +8405,7 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite, lcd_set_cursor(0, 1); if(check_opposite == true) lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN)); else lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN)); - SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); - WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1); + setExtruderAutoFanState(3); break; case 1: // object cooling fan @@ -8390,23 +8434,6 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite, lcd_button_pressed = false; do { - switch (_fan) - { - case 0: - // extruder cooling fan - SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); - WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1); - break; - case 1: - // object cooling fan - SET_OUTPUT(FAN_PIN); -#ifdef FAN_SOFT_PWM - fanSpeedSoftPwm = 255; -#else //FAN_SOFT_PWM - analogWrite(FAN_PIN, 255); -#endif //FAN_SOFT_PWM - break; - } if (abs((enc_dif - lcd_encoder_diff)) > 2) { if (enc_dif > lcd_encoder_diff) { _result = !check_opposite; @@ -8433,8 +8460,7 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite, } while (!lcd_clicked()); KEEPALIVE_STATE(IN_HANDLER); - SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); - WRITE(EXTRUDER_0_AUTO_FAN_PIN, 0); + setExtruderAutoFanState(0); SET_OUTPUT(FAN_PIN); #ifdef FAN_SOFT_PWM fanSpeedSoftPwm = 0; @@ -8454,20 +8480,20 @@ static FanCheck lcd_selftest_fan_auto(int _fan) case 0: fanSpeed = 0; manage_heater(); //turn off fan - setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, 1); //extruder fan + setExtruderAutoFanState(3); //extruder fan #ifdef FAN_SOFT_PWM extruder_autofan_last_check = _millis(); fan_measuring = true; #endif //FAN_SOFT_PWM - _delay(2000); //delay_keep_alive would turn off extruder fan, because temerature is too low - + _delay(2000); + setExtruderAutoFanState(0); //extruder fan manage_heater(); //count average fan speed from 2s delay and turn off fans printf_P(PSTR("Test 1:\n")); printf_P(PSTR("Print fan speed: %d \n"), fan_speed[1]); printf_P(PSTR("Extr fan speed: %d \n"), fan_speed[0]); - if (!fan_speed[0]) { + if (fan_speed[0] < 20) { // < 1200 RPM would mean either a faulty Noctua or Altfan return FanCheck::ExtruderFan; } #ifdef FAN_SOFT_PWM @@ -8545,7 +8571,7 @@ static FanCheck lcd_selftest_fan_auto(int _fan) static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay) { - lcd_update_enable(false); + lcd_update_enable(false); const char *_indicator = (_progress >= _progress_scale) ? "-" : "|"; @@ -8593,7 +8619,7 @@ static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_s { //SERIAL_ECHOLNPGM("Other tests"); - TestScreen _step_block = TestScreen::AxisX; + TestScreen _step_block = TestScreen::AxisX; lcd_selftest_screen_step(2, 2, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "X", _indicator); _step_block = TestScreen::AxisY; @@ -8605,8 +8631,8 @@ static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_s _step_block = TestScreen::Bed; lcd_selftest_screen_step(3, 0, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Bed", _indicator); - _step_block = TestScreen::Hotend; - lcd_selftest_screen_step(3, 9, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Hotend", _indicator); + _step_block = TestScreen::Hotend; + lcd_selftest_screen_step(3, 9, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Hotend", _indicator); } if (_delay > 0) delay_keep_alive(_delay); @@ -8843,13 +8869,14 @@ void lcd_finishstatus() { lcd_draw_update = 2; } + void lcd_setstatus(const char* message) { if (lcd_status_message_level > 0) return; - strncpy(lcd_status_message, message, LCD_WIDTH); - lcd_finishstatus(); + lcd_updatestatus(message); } + void lcd_updatestatuspgm(const char *message){ strncpy_P(lcd_status_message, message, LCD_WIDTH); lcd_status_message[LCD_WIDTH] = 0; @@ -8864,12 +8891,29 @@ void lcd_setstatuspgm(const char* message) return; lcd_updatestatuspgm(message); } + +void lcd_updatestatus(const char *message){ + strncpy(lcd_status_message, message, LCD_WIDTH); + lcd_status_message[LCD_WIDTH] = 0; + lcd_finishstatus(); + // hack lcd_draw_update to 1, i.e. without clear + lcd_draw_update = 1; +} + void lcd_setalertstatuspgm(const char* message) { lcd_setstatuspgm(message); lcd_status_message_level = 1; lcd_return_to_status(); } + +void lcd_setalertstatus(const char* message) +{ + lcd_setstatus(message); + lcd_status_message_level = 1; + lcd_return_to_status(); +} + void lcd_reset_alert_level() { lcd_status_message_level = 0; @@ -8889,6 +8933,13 @@ void menu_lcd_longpress_func(void) lcd_quick_feedback(); return; } + if (menu_menu == lcd_hw_setup_menu) + { + // only toggle the experimental menu visibility flag + lcd_quick_feedback(); + lcd_experimental_toggle(); + return; + } // explicitely listed menus which are allowed to rise the move-z or live-adj-z functions // The lists are not the same for both functions, so first decide which function is to be performed @@ -9052,3 +9103,25 @@ void lcd_crash_detect_disable() eeprom_update_byte((uint8_t*)EEPROM_CRASH_DET, 0x00); } #endif + +void lcd_experimental_toggle() +{ + uint8_t oldVal = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY); + if (oldVal == EEPROM_EMPTY_VALUE) + oldVal = 0; + else + oldVal = !oldVal; + eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, oldVal); +} + +void lcd_experimental_menu() +{ + MENU_BEGIN(); + MENU_ITEM_BACK_P(_T(MSG_BACK)); + +#ifdef EXTRUDER_ALTFAN_DETECT + MENU_ITEM_TOGGLE_P(_N("ALTFAN det."), altfanOverride_get()?_T(MSG_OFF):_T(MSG_ON), altfanOverride_toggle);////MSG_MENU_ALTFAN c=18 +#endif //EXTRUDER_ALTFAN_DETECT + + MENU_END(); +} diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 50db77b08..2b54b3c2e 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -23,9 +23,11 @@ void lcd_setstatuspgm(const char* message); //! - always returns the display to the main status screen //! - always makes lcd_reset (which is slow and causes flicker) //! - does not update the message if there is already one (i.e. lcd_status_message_level > 0) +void lcd_setalertstatus(const char* message); void lcd_setalertstatuspgm(const char* message); //! only update the alert message on the main status screen //! has no sideeffects, may be called multiple times +void lcd_updatestatus(const char *message); void lcd_updatestatuspgm(const char *message); void lcd_reset_alert_level(); @@ -142,7 +144,7 @@ extern uint8_t farm_status; #ifdef IR_SENSOR_ANALOG extern bool bMenuFSDetect; -void printf_IRSensorAnalogBoardChange(bool bPCBrev04); +void printf_IRSensorAnalogBoardChange(); #endif //IR_SENSOR_ANALOG extern int8_t SilentModeMenu; @@ -256,21 +258,7 @@ enum class WizState : uint8_t void lcd_wizard(WizState state); -#define VOLT_DIV_REF 5 -#ifdef IR_SENSOR_ANALOG -constexpr uint16_t Voltage2Raw(float V){ - return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F; -} -constexpr float Raw2Voltage(uint16_t raw){ - return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) ); -} -constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821 -constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910 -constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059 -constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982 -constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368 - - -#endif //IR_SENSOR_ANALOG +extern void lcd_experimental_toggle(); +extern void lcd_experimental_menu(); #endif //ULTRALCD_H diff --git a/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h index 45b88c7ba..887a90a6f 100644 --- a/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h @@ -330,6 +330,10 @@ PREHEAT SETTINGS #define ASA_PREHEAT_HPB_TEMP 105 #define ASA_PREHEAT_FAN_SPEED 0 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_FAN_SPEED 0 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 #define ABS_PREHEAT_FAN_SPEED 0 diff --git a/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h index 7b3e24458..c9c4ed6cd 100644 --- a/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h @@ -326,6 +326,9 @@ PREHEAT SETTINGS #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 105 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index 36a9b5214..f2ef69e99 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -384,6 +384,9 @@ #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 105 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index ff13a7c61..7eaba3d6c 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -385,6 +385,9 @@ #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 105 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index 71a23a1a6..ee245bd4b 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -384,6 +384,9 @@ #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 105 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index 8d22a6cc9..6bf30f192 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -385,6 +385,9 @@ #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 105 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index b80217ee3..04b4c5266 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -294,6 +294,9 @@ #if BED_MINTEMP_DELAY>USHRT_MAX #error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)" #endif +#define DETECT_SUPERPINDA +#define PINDA_MINTEMP BED_MINTEMP +#define AMBIENT_MINTEMP -30 // Maxtemps #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) @@ -304,6 +307,7 @@ #define HEATER_1_MAXTEMP 305 #define HEATER_2_MAXTEMP 305 #define BED_MAXTEMP 125 +#define AMBIENT_MAXTEMP 100 #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) // Define PID constants for extruder with PT100 @@ -496,6 +500,9 @@ #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 110 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index ad714c235..c869ec517 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -296,6 +296,9 @@ #if BED_MINTEMP_DELAY>USHRT_MAX #error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)" #endif +#define DETECT_SUPERPINDA +#define PINDA_MINTEMP BED_MINTEMP +#define AMBIENT_MINTEMP -30 // Maxtemps #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) @@ -306,6 +309,7 @@ #define HEATER_1_MAXTEMP 305 #define HEATER_2_MAXTEMP 305 #define BED_MAXTEMP 125 +#define AMBIENT_MAXTEMP 100 #if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP) // Define PID constants for extruder with PT100 @@ -331,6 +335,8 @@ #define EXTRUDER_2_AUTO_FAN_PIN -1 #define EXTRUDER_AUTO_FAN_TEMPERATURE 50 #define EXTRUDER_AUTO_FAN_SPEED 255 // == full speed +#define EXTRUDER_ALTFAN_DETECT +#define EXTRUDER_ALTFAN_SPEED_SILENT 128 @@ -498,6 +504,9 @@ #define ASA_PREHEAT_HOTEND_TEMP 260 #define ASA_PREHEAT_HPB_TEMP 105 +#define PC_PREHEAT_HOTEND_TEMP 275 +#define PC_PREHEAT_HPB_TEMP 110 + #define ABS_PREHEAT_HOTEND_TEMP 255 #define ABS_PREHEAT_HPB_TEMP 100 diff --git a/README.md b/README.md index fb1c79689..1562552bc 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,28 @@ The firmware for the Original Prusa i3 printers is proudly based on [Marlin 1.0. 1. Clone this repository and checkout the correct branch for your desired release version. -2. Set your printer model. +1. Set your printer model. - For MK3 --> skip to step 3. - If you have a different printer model, follow step [2.b](#2b) from Windows build +1. Install GNU AWK `sudo apt-get install gawk` +If you use mawk instead of gawk you get strange errors when multi language support is generated like: +`awk: line 2: function strtonum never defined +sed: couldn't write 4 items to stdout: Broken pipe +./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined +sed: couldn't write 4 items to stdout: Broken pipe +tr: write error: Broken pipe +./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined +sed: couldn't write 4 items to stdout: Broken pipe +tr: write error: Broken pipe +tr: write error +cut: write error: Broken pipeNG! - some texts not found in lang_en.txt! updating binary: + primary language ids...awk: line 2: function strtonum never defined +sed: couldn't flush stdout: Broken pipe` -3. Run `./build.sh` +1. Run `./build.sh` - Output hex file is at `"PrusaFirmware/lang/firmware.hex"` . In the same folder you can hex files for other languages as well. -4. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE. +1. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE. - If you wish to flash from Arduino, follow step [2.c](#2c) from Windows build first. @@ -182,7 +196,7 @@ Example: `ninja` -## Runing +## Running `./tests` # 4. Documentation