diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index ebaf3f140..1a9d33a02 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -219,7 +219,7 @@ unsigned int heating_status; unsigned int heating_status_counter; bool loading_flag = false; - +#define XY_NO_RESTORE_FLAG (mesh_bed_leveling_flag || homing_flag) char snmm_filaments_used = 0; @@ -305,7 +305,12 @@ bool no_response = false; uint8_t important_status; uint8_t saved_filament_type; -#define SAVED_TARGET_UNSET (X_MIN_POS-1) +// Define some coordinates outside the clamp limits (making them invalid past the parsing stage) so +// that they can be used later for various logical checks +#define X_COORD_INVALID (X_MIN_POS-1) +#define Y_COORD_INVALID (Y_MIN_POS-1) + +#define SAVED_TARGET_UNSET X_COORD_INVALID float saved_target[NUM_AXIS] = {SAVED_TARGET_UNSET, 0, 0, 0}; // save/restore printing in case that mmu was not responding @@ -375,7 +380,7 @@ boolean chdkActive = false; bool saved_printing = false; //!< Print is paused and saved in RAM static uint32_t saved_sdpos = 0; //!< SD card position, or line number in case of USB printing uint8_t saved_printing_type = PRINTING_TYPE_SD; -static float saved_pos[4] = { 0, 0, 0, 0 }; +static float saved_pos[4] = { X_COORD_INVALID, 0, 0, 0 }; static uint16_t saved_feedrate2 = 0; //!< Default feedrate (truncated from float) static int saved_feedmultiply2 = 0; static uint8_t saved_active_extruder = 0; @@ -588,19 +593,6 @@ void crashdet_restore_print_and_continue() // babystep_apply(); } - -void crashdet_stop_and_save_print2() -{ - cli(); - planner_abort_hard(); //abort printing - cmdqueue_reset(); //empty cmdqueue - card.sdprinting = false; - card.closefile(); - // Reset and re-enable the stepper timer just before the global interrupts are enabled. - st_reset_timer(); - sei(); -} - void crashdet_detected(uint8_t mask) { st_synchronize(); @@ -2954,6 +2946,416 @@ static void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis) #endif //TMC2130 } + +// G80 - Automatic mesh bed leveling +static void gcode_G80() +{ + mesh_bed_leveling_flag = true; +#ifndef PINDA_THERMISTOR + static bool run = false; // thermistor-less PINDA temperature compensation is running +#endif // ndef PINDA_THERMISTOR + +#ifdef SUPPORT_VERBOSITY + int8_t verbosity_level = 0; + if (code_seen('V')) { + // Just 'V' without a number counts as V1. + char c = strchr_pointer[1]; + verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short(); + } +#endif //SUPPORT_VERBOSITY + // Firstly check if we know where we are + 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 G80 with all its parameters + enquecommand_front_P(G28W0); + return; + } + + uint8_t nMeasPoints = MESH_MEAS_NUM_X_POINTS; + if (code_seen('N')) { + nMeasPoints = code_value_uint8(); + if (nMeasPoints != 7) { + nMeasPoints = 3; + } + } + else { + nMeasPoints = eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); + } + + uint8_t nProbeRetry = 3; + if (code_seen('R')) { + nProbeRetry = code_value_uint8(); + if (nProbeRetry > 10) { + nProbeRetry = 10; + } + } + else { + nProbeRetry = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); + } + bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); + +#ifndef PINDA_THERMISTOR + if (run == false && temp_cal_active == true && calibration_status_pinda() == true && target_temperature_bed >= 50) + { + temp_compensation_start(); + run = true; + repeatcommand_front(); // repeat G80 with all its parameters + enquecommand_front_P(G28W0); + break; + } + run = false; +#endif //PINDA_THERMISTOR + // Save custom message state, set a new custom message state to display: Calibrating point 9. + CustomMsg custom_message_type_old = custom_message_type; + unsigned int custom_message_state_old = custom_message_state; + custom_message_type = CustomMsg::MeshBedLeveling; + custom_message_state = (nMeasPoints * nMeasPoints) + 10; + lcd_update(1); + + mbl.reset(); //reset mesh bed leveling + + // Reset baby stepping to zero, if the babystepping has already been loaded before. + babystep_undo(); + + // 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); + // The move to the first calibration point. + current_position[X_AXIS] = BED_X0; + current_position[Y_AXIS] = BED_Y0; + +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) + { + bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); + clamped ? SERIAL_PROTOCOLPGM("First calibration point clamped.\n") : SERIAL_PROTOCOLPGM("No clamping for first calibration point.\n"); + } +#else //SUPPORT_VERBOSITY + world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); +#endif //SUPPORT_VERBOSITY + + int XY_AXIS_FEEDRATE = homing_feedrate[X_AXIS] / 20; + plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); + // Wait until the move is finished. + st_synchronize(); + if (waiting_inside_plan_buffer_line_print_aborted) + { + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + return; + } + + uint8_t mesh_point = 0; //index number of calibration point + int Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 40; + bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + has_z ? SERIAL_PROTOCOLPGM("Z jitter data from Z cal. valid.\n") : SERIAL_PROTOCOLPGM("Z jitter data from Z cal. not valid.\n"); + } +#endif // SUPPORT_VERBOSITY + int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 + 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 + uint8_t iy = mesh_point / nMeasPoints; + /*if (!mbl_point_measurement_valid(ix, iy, nMeasPoints, true)) { + printf_P(PSTR("Skipping point [%d;%d] \n"), ix, iy); + custom_message_state--; + mesh_point++; + continue; //skip + }*/ + if (iy & 1) ix = (nMeasPoints - 1) - ix; // Zig zag + if (nMeasPoints == 7) //if we have 7x7 mesh, compare with Z-calibration for points which are in 3x3 mesh + { + has_z = ((ix % 3 == 0) && (iy % 3 == 0)) && is_bed_z_jitter_data_valid(); + } + float z0 = 0.f; + if (has_z && (mesh_point > 0)) { + uint16_t z_offset_u = 0; + if (nMeasPoints == 7) { + z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); + } + else { + z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * (ix + iy * 3 - 1))); + } + z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + printf_P(PSTR("Bed leveling, point: %d, calibration Z stored in eeprom: %d, calibration z: %f \n"), mesh_point, z_offset_u, z0); + } +#endif // SUPPORT_VERBOSITY + } + + // Move Z up to MESH_HOME_Z_SEARCH. + 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); + st_synchronize(); + + // Move to XY position of the sensor point. + current_position[X_AXIS] = BED_X(ix, nMeasPoints); + current_position[Y_AXIS] = BED_Y(iy, nMeasPoints); + + //printf_P(PSTR("[%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); + + +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); + SERIAL_PROTOCOL(mesh_point); + clamped ? SERIAL_PROTOCOLPGM(": xy clamped.\n") : SERIAL_PROTOCOLPGM(": no xy clamping\n"); + } +#else //SUPPORT_VERBOSITY + world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); +#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); + st_synchronize(); + if (waiting_inside_plan_buffer_line_print_aborted) + { + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + return; + } + + // Go down until endstop is hit + const float Z_CALIBRATION_THRESHOLD = 1.f; + 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 + printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); + break; + } + 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); + 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 + printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); + break; + } + if (MESH_HOME_Z_SEARCH - current_position[Z_AXIS] < 0.1f) { + puts_P(PSTR("Bed leveling failed. Sensor disconnected or cable broken.")); + break; + } + } + if (has_z && fabs(z0 - current_position[Z_AXIS]) > Z_CALIBRATION_THRESHOLD) { //if we have data from z calibration, max. allowed difference is 1mm for each point + puts_P(PSTR("Bed leveling failed. Sensor triggered too high.")); + break; + } +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 10) { + SERIAL_ECHOPGM("X: "); + MYSERIAL.print(current_position[X_AXIS], 5); + SERIAL_ECHOLNPGM(""); + SERIAL_ECHOPGM("Y: "); + MYSERIAL.print(current_position[Y_AXIS], 5); + SERIAL_PROTOCOLPGM("\n"); + } +#endif // SUPPORT_VERBOSITY + float offset_z = 0; + +#ifdef PINDA_THERMISTOR + offset_z = temp_compensation_pinda_thermistor_offset(current_temperature_pinda); +#endif //PINDA_THERMISTOR + // #ifdef SUPPORT_VERBOSITY + /* if (verbosity_level >= 1) + { + SERIAL_ECHOPGM("mesh bed leveling: "); + MYSERIAL.print(current_position[Z_AXIS], 5); + SERIAL_ECHOPGM(" offset: "); + MYSERIAL.print(offset_z, 5); + SERIAL_ECHOLNPGM(""); + }*/ + // #endif // SUPPORT_VERBOSITY + mbl.set_z(ix, iy, current_position[Z_AXIS] - offset_z); //store measured z values z_values[iy][ix] = z - offset_z; + + custom_message_state--; + mesh_point++; + lcd_update(1); + } + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 20) { + SERIAL_ECHOLNPGM("Mesh bed leveling while loop finished."); + SERIAL_ECHOLNPGM("MESH_HOME_Z_SEARCH: "); + MYSERIAL.print(current_position[Z_AXIS], 5); + } +#endif // SUPPORT_VERBOSITY + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); + st_synchronize(); + if (mesh_point != nMeasPoints * nMeasPoints) { + Sound_MakeSound(e_SOUND_TYPE_StandardAlert); + bool bState; + do { // repeat until Z-leveling o.k. + lcd_display_message_fullscreen_P(_i("Some problem encountered, Z-leveling enforced ...")); +#ifdef TMC2130 + lcd_wait_for_click_delay(MSG_BED_LEVELING_FAILED_TIMEOUT); + calibrate_z_auto(); // Z-leveling (X-assembly stay up!!!) +#else // TMC2130 + lcd_wait_for_click_delay(0); // ~ no timeout + lcd_calibrate_z_end_stop_manual(true); // Z-leveling (X-assembly stay up!!!) +#endif // TMC2130 + // ~ 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); + 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); + st_synchronize(); +#ifdef TMC2130 + tmc2130_home_exit(); +#endif // TMC2130 + enable_z_endstop(bState); + } while (st_get_position_mm(Z_AXIS) > MESH_HOME_Z_SEARCH); // i.e. Z-leveling not o.k. + // plan_set_z_position(MESH_HOME_Z_SEARCH); // is not necessary ('do-while' loop always ends at the expected Z-position) + + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + lcd_update_enable(true); // display / status-line recovery + gcode_G28(true, true, true); // X & Y & Z-homing (must be after individual Z-homing (problem with spool-holder)!) + repeatcommand_front(); // re-run (i.e. of "G80") + return; + } + clean_up_after_endstop_move(l_feedmultiply); + // SERIAL_ECHOLNPGM("clean up finished "); + +#ifndef PINDA_THERMISTOR + if(temp_cal_active == true && calibration_status_pinda() == true) temp_compensation_apply(); //apply PINDA temperature compensation +#endif + babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. + // SERIAL_ECHOLNPGM("babystep applied"); + bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + eeprom_bed_correction_valid ? SERIAL_PROTOCOLPGM("Bed correction data valid\n") : SERIAL_PROTOCOLPGM("Bed correction data not valid\n"); + } +#endif // SUPPORT_VERBOSITY + + for (uint8_t i = 0; i < 4; ++i) { + unsigned char codes[4] = { 'L', 'R', 'F', 'B' }; + long correction = 0; + if (code_seen(codes[i])) + correction = code_value_long(); + else if (eeprom_bed_correction_valid) { + unsigned char *addr = (i < 2) ? + ((i == 0) ? (unsigned char*)EEPROM_BED_CORRECTION_LEFT : (unsigned char*)EEPROM_BED_CORRECTION_RIGHT) : + ((i == 2) ? (unsigned char*)EEPROM_BED_CORRECTION_FRONT : (unsigned char*)EEPROM_BED_CORRECTION_REAR); + correction = eeprom_read_int8(addr); + } + if (correction == 0) + continue; + + if (labs(correction) > BED_ADJUSTMENT_UM_MAX) { + SERIAL_ERROR_START; + SERIAL_ECHOPGM("Excessive bed leveling correction: "); + SERIAL_ECHO(correction); + SERIAL_ECHOLNPGM(" microns"); + } + else { + float offset = float(correction) * 0.001f; + switch (i) { + case 0: + for (uint8_t row = 0; row < nMeasPoints; ++row) { + for (uint8_t col = 0; col < nMeasPoints - 1; ++col) { + mbl.z_values[row][col] += offset * (nMeasPoints - 1 - col) / (nMeasPoints - 1); + } + } + break; + case 1: + for (uint8_t row = 0; row < nMeasPoints; ++row) { + for (uint8_t col = 1; col < nMeasPoints; ++col) { + mbl.z_values[row][col] += offset * col / (nMeasPoints - 1); + } + } + break; + case 2: + for (uint8_t col = 0; col < nMeasPoints; ++col) { + for (uint8_t row = 0; row < nMeasPoints; ++row) { + mbl.z_values[row][col] += offset * (nMeasPoints - 1 - row) / (nMeasPoints - 1); + } + } + break; + case 3: + for (uint8_t col = 0; col < nMeasPoints; ++col) { + for (uint8_t row = 1; row < nMeasPoints; ++row) { + mbl.z_values[row][col] += offset * row / (nMeasPoints - 1); + } + } + break; + } + } + } + // SERIAL_ECHOLNPGM("Bed leveling correction finished"); + if (nMeasPoints == 3) { + mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) + } + /* + SERIAL_PROTOCOLPGM("Num X,Y: "); + SERIAL_PROTOCOL(MESH_NUM_X_POINTS); + SERIAL_PROTOCOLPGM(","); + SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); + SERIAL_PROTOCOLPGM("\nZ search height: "); + SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); + SERIAL_PROTOCOLLNPGM("\nMeasured points:"); + for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { + for (int x = 0; x < MESH_NUM_X_POINTS; x++) { + SERIAL_PROTOCOLPGM(" "); + SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); + } + SERIAL_PROTOCOLPGM("\n"); + } + */ + if (nMeasPoints == 7 && magnet_elimination) { + mbl_interpolation(nMeasPoints); + } + /* + SERIAL_PROTOCOLPGM("Num X,Y: "); + SERIAL_PROTOCOL(MESH_NUM_X_POINTS); + SERIAL_PROTOCOLPGM(","); + SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); + SERIAL_PROTOCOLPGM("\nZ search height: "); + SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); + SERIAL_PROTOCOLLNPGM("\nMeasured points:"); + for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { + for (int x = 0; x < MESH_NUM_X_POINTS; x++) { + SERIAL_PROTOCOLPGM(" "); + SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); + } + SERIAL_PROTOCOLPGM("\n"); + } + */ + // SERIAL_ECHOLNPGM("Upsample finished"); + mbl.active = 1; //activate mesh bed leveling + // SERIAL_ECHOLNPGM("Mesh bed leveling activated"); + go_home_with_z_lift(); + // SERIAL_ECHOLNPGM("Go home finished"); + //unretract (after PINDA preheat retraction) + 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); + } + KEEPALIVE_STATE(NOT_BUSY); + // Restore custom message state + lcd_setstatuspgm(_T(WELCOME_MSG)); + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + mesh_bed_leveling_flag = false; + mesh_bed_run_from_menu = false; + lcd_update(2); +} + + void adjust_bed_reset() { eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1); @@ -4530,9 +4932,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) gcode_G28(home_x, home_x_value, home_y, home_y_value, home_z, home_z_value, without_mbl); #endif //TMC2130 if ((home_x || home_y || without_mbl || home_z) == false) { - // Push the commands to the front of the message queue in the reverse order! - // There shall be always enough space reserved for these commands. - goto case_G80; + gcode_G80(); } break; } @@ -5084,404 +5484,11 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) * v Y-axis */ - case 80: - + case 80: { #ifdef MK1BP break; #endif //MK1BP - case_G80: - { - mesh_bed_leveling_flag = true; -#ifndef PINDA_THERMISTOR - static bool run = false; // thermistor-less PINDA temperature compensation is running -#endif // ndef PINDA_THERMISTOR - -#ifdef SUPPORT_VERBOSITY - int8_t verbosity_level = 0; - if (code_seen('V')) { - // Just 'V' without a number counts as V1. - char c = strchr_pointer[1]; - verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short(); - } -#endif //SUPPORT_VERBOSITY - // Firstly check if we know where we are - 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 G80 with all its parameters - enquecommand_front_P(G28W0); - break; - } - - uint8_t nMeasPoints = MESH_MEAS_NUM_X_POINTS; - if (code_seen('N')) { - nMeasPoints = code_value_uint8(); - if (nMeasPoints != 7) { - nMeasPoints = 3; - } - } - else { - nMeasPoints = eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); - } - - uint8_t nProbeRetry = 3; - if (code_seen('R')) { - nProbeRetry = code_value_uint8(); - if (nProbeRetry > 10) { - nProbeRetry = 10; - } - } - else { - nProbeRetry = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); - } - bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); - -#ifndef PINDA_THERMISTOR - if (run == false && temp_cal_active == true && calibration_status_pinda() == true && target_temperature_bed >= 50) - { - temp_compensation_start(); - run = true; - repeatcommand_front(); // repeat G80 with all its parameters - enquecommand_front_P(G28W0); - break; - } - run = false; -#endif //PINDA_THERMISTOR - // Save custom message state, set a new custom message state to display: Calibrating point 9. - CustomMsg custom_message_type_old = custom_message_type; - unsigned int custom_message_state_old = custom_message_state; - custom_message_type = CustomMsg::MeshBedLeveling; - custom_message_state = (nMeasPoints * nMeasPoints) + 10; - lcd_update(1); - - mbl.reset(); //reset mesh bed leveling - - // Reset baby stepping to zero, if the babystepping has already been loaded before. - babystep_undo(); - - // 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); - // The move to the first calibration point. - current_position[X_AXIS] = BED_X0; - current_position[Y_AXIS] = BED_Y0; - - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) - { - bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - clamped ? SERIAL_PROTOCOLPGM("First calibration point clamped.\n") : SERIAL_PROTOCOLPGM("No clamping for first calibration point.\n"); - } - #else //SUPPORT_VERBOSITY - world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - #endif //SUPPORT_VERBOSITY - - plan_buffer_line_curposXYZE(homing_feedrate[X_AXIS] / 30); - // Wait until the move is finished. - st_synchronize(); - - uint8_t mesh_point = 0; //index number of calibration point - - int XY_AXIS_FEEDRATE = homing_feedrate[X_AXIS] / 20; - int Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 40; - bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - has_z ? SERIAL_PROTOCOLPGM("Z jitter data from Z cal. valid.\n") : SERIAL_PROTOCOLPGM("Z jitter data from Z cal. not valid.\n"); - } - #endif // SUPPORT_VERBOSITY - int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 - 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 - uint8_t iy = mesh_point / nMeasPoints; - /*if (!mbl_point_measurement_valid(ix, iy, nMeasPoints, true)) { - printf_P(PSTR("Skipping point [%d;%d] \n"), ix, iy); - custom_message_state--; - mesh_point++; - continue; //skip - }*/ - if (iy & 1) ix = (nMeasPoints - 1) - ix; // Zig zag - if (nMeasPoints == 7) //if we have 7x7 mesh, compare with Z-calibration for points which are in 3x3 mesh - { - has_z = ((ix % 3 == 0) && (iy % 3 == 0)) && is_bed_z_jitter_data_valid(); - } - float z0 = 0.f; - if (has_z && (mesh_point > 0)) { - uint16_t z_offset_u = 0; - if (nMeasPoints == 7) { - z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); - } - else { - z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * (ix + iy * 3 - 1))); - } - z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - printf_P(PSTR("Bed leveling, point: %d, calibration Z stored in eeprom: %d, calibration z: %f \n"), mesh_point, z_offset_u, z0); - } - #endif // SUPPORT_VERBOSITY - } - - // Move Z up to MESH_HOME_Z_SEARCH. - 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); - st_synchronize(); - - // Move to XY position of the sensor point. - current_position[X_AXIS] = BED_X(ix, nMeasPoints); - current_position[Y_AXIS] = BED_Y(iy, nMeasPoints); - - //printf_P(PSTR("[%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); - - - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - SERIAL_PROTOCOL(mesh_point); - clamped ? SERIAL_PROTOCOLPGM(": xy clamped.\n") : SERIAL_PROTOCOLPGM(": no xy clamping\n"); - } - #else //SUPPORT_VERBOSITY - world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - #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); - st_synchronize(); - - // Go down until endstop is hit - const float Z_CALIBRATION_THRESHOLD = 1.f; - 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 - printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); - break; - } - 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); - 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 - printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); - break; - } - if (MESH_HOME_Z_SEARCH - current_position[Z_AXIS] < 0.1f) { - puts_P(PSTR("Bed leveling failed. Sensor disconnected or cable broken.")); - break; - } - } - if (has_z && fabs(z0 - current_position[Z_AXIS]) > Z_CALIBRATION_THRESHOLD) { //if we have data from z calibration, max. allowed difference is 1mm for each point - puts_P(PSTR("Bed leveling failed. Sensor triggered too high.")); - break; - } - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 10) { - SERIAL_ECHOPGM("X: "); - MYSERIAL.print(current_position[X_AXIS], 5); - SERIAL_ECHOLNPGM(""); - SERIAL_ECHOPGM("Y: "); - MYSERIAL.print(current_position[Y_AXIS], 5); - SERIAL_PROTOCOLPGM("\n"); - } - #endif // SUPPORT_VERBOSITY - float offset_z = 0; - -#ifdef PINDA_THERMISTOR - offset_z = temp_compensation_pinda_thermistor_offset(current_temperature_pinda); -#endif //PINDA_THERMISTOR -// #ifdef SUPPORT_VERBOSITY -/* if (verbosity_level >= 1) - { - SERIAL_ECHOPGM("mesh bed leveling: "); - MYSERIAL.print(current_position[Z_AXIS], 5); - SERIAL_ECHOPGM(" offset: "); - MYSERIAL.print(offset_z, 5); - SERIAL_ECHOLNPGM(""); - }*/ -// #endif // SUPPORT_VERBOSITY - mbl.set_z(ix, iy, current_position[Z_AXIS] - offset_z); //store measured z values z_values[iy][ix] = z - offset_z; - - custom_message_state--; - mesh_point++; - lcd_update(1); - } - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 20) { - SERIAL_ECHOLNPGM("Mesh bed leveling while loop finished."); - SERIAL_ECHOLNPGM("MESH_HOME_Z_SEARCH: "); - MYSERIAL.print(current_position[Z_AXIS], 5); - } - #endif // SUPPORT_VERBOSITY - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - st_synchronize(); - if (mesh_point != nMeasPoints * nMeasPoints) { - Sound_MakeSound(e_SOUND_TYPE_StandardAlert); - bool bState; - do { // repeat until Z-leveling o.k. - lcd_display_message_fullscreen_P(_i("Some problem encountered, Z-leveling enforced ...")); -#ifdef TMC2130 - lcd_wait_for_click_delay(MSG_BED_LEVELING_FAILED_TIMEOUT); - calibrate_z_auto(); // Z-leveling (X-assembly stay up!!!) -#else // TMC2130 - lcd_wait_for_click_delay(0); // ~ no timeout - lcd_calibrate_z_end_stop_manual(true); // Z-leveling (X-assembly stay up!!!) -#endif // TMC2130 - // ~ 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); - 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); - st_synchronize(); -#ifdef TMC2130 - tmc2130_home_exit(); -#endif // TMC2130 - enable_z_endstop(bState); - } while (st_get_position_mm(Z_AXIS) > MESH_HOME_Z_SEARCH); // i.e. Z-leveling not o.k. -// plan_set_z_position(MESH_HOME_Z_SEARCH); // is not necessary ('do-while' loop always ends at the expected Z-position) - custom_message_type=CustomMsg::Status; // display / status-line recovery - lcd_update_enable(true); // display / status-line recovery - gcode_G28(true, true, true); // X & Y & Z-homing (must be after individual Z-homing (problem with spool-holder)!) - repeatcommand_front(); // re-run (i.e. of "G80") - break; - } - clean_up_after_endstop_move(l_feedmultiply); -// SERIAL_ECHOLNPGM("clean up finished "); - -#ifndef PINDA_THERMISTOR - if(temp_cal_active == true && calibration_status_pinda() == true) temp_compensation_apply(); //apply PINDA temperature compensation -#endif - babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. -// SERIAL_ECHOLNPGM("babystep applied"); - bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - eeprom_bed_correction_valid ? SERIAL_PROTOCOLPGM("Bed correction data valid\n") : SERIAL_PROTOCOLPGM("Bed correction data not valid\n"); - } - #endif // SUPPORT_VERBOSITY - - for (uint8_t i = 0; i < 4; ++i) { - unsigned char codes[4] = { 'L', 'R', 'F', 'B' }; - long correction = 0; - if (code_seen(codes[i])) - correction = code_value_long(); - else if (eeprom_bed_correction_valid) { - unsigned char *addr = (i < 2) ? - ((i == 0) ? (unsigned char*)EEPROM_BED_CORRECTION_LEFT : (unsigned char*)EEPROM_BED_CORRECTION_RIGHT) : - ((i == 2) ? (unsigned char*)EEPROM_BED_CORRECTION_FRONT : (unsigned char*)EEPROM_BED_CORRECTION_REAR); - correction = eeprom_read_int8(addr); - } - if (correction == 0) - continue; - - if (labs(correction) > BED_ADJUSTMENT_UM_MAX) { - SERIAL_ERROR_START; - SERIAL_ECHOPGM("Excessive bed leveling correction: "); - SERIAL_ECHO(correction); - SERIAL_ECHOLNPGM(" microns"); - } - else { - float offset = float(correction) * 0.001f; - switch (i) { - case 0: - for (uint8_t row = 0; row < nMeasPoints; ++row) { - for (uint8_t col = 0; col < nMeasPoints - 1; ++col) { - mbl.z_values[row][col] += offset * (nMeasPoints - 1 - col) / (nMeasPoints - 1); - } - } - break; - case 1: - for (uint8_t row = 0; row < nMeasPoints; ++row) { - for (uint8_t col = 1; col < nMeasPoints; ++col) { - mbl.z_values[row][col] += offset * col / (nMeasPoints - 1); - } - } - break; - case 2: - for (uint8_t col = 0; col < nMeasPoints; ++col) { - for (uint8_t row = 0; row < nMeasPoints; ++row) { - mbl.z_values[row][col] += offset * (nMeasPoints - 1 - row) / (nMeasPoints - 1); - } - } - break; - case 3: - for (uint8_t col = 0; col < nMeasPoints; ++col) { - for (uint8_t row = 1; row < nMeasPoints; ++row) { - mbl.z_values[row][col] += offset * row / (nMeasPoints - 1); - } - } - break; - } - } - } -// SERIAL_ECHOLNPGM("Bed leveling correction finished"); - if (nMeasPoints == 3) { - mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) - } -/* - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLPGM("\n"); - } -*/ - if (nMeasPoints == 7 && magnet_elimination) { - mbl_interpolation(nMeasPoints); - } -/* - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLPGM("\n"); - } -*/ -// SERIAL_ECHOLNPGM("Upsample finished"); - mbl.active = 1; //activate mesh bed leveling -// SERIAL_ECHOLNPGM("Mesh bed leveling activated"); - go_home_with_z_lift(); -// SERIAL_ECHOLNPGM("Go home finished"); - //unretract (after PINDA preheat retraction) - 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); - } - KEEPALIVE_STATE(NOT_BUSY); - // Restore custom message state - lcd_setstatuspgm(_T(WELCOME_MSG)); - custom_message_type = custom_message_type_old; - custom_message_state = custom_message_state_old; - mesh_bed_leveling_flag = false; - mesh_bed_run_from_menu = false; - lcd_update(2); - + gcode_G80(); } break; @@ -10851,8 +10858,9 @@ void uvlo_() } // save the global state at planning time + bool pos_invalid = XY_NO_RESTORE_FLAG; uint16_t feedrate_bckp; - if (current_block) + if (current_block && !pos_invalid) { memcpy(saved_target, current_block->gcode_target, sizeof(saved_target)); feedrate_bckp = current_block->gcode_feedrate; @@ -10930,8 +10938,13 @@ void uvlo_() eeprom_update_word((uint16_t*)(EEPROM_UVLO_Z_MICROSTEPS), z_microsteps); // Store the current position. - eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), current_position[X_AXIS]); - eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4), current_position[Y_AXIS]); + if (pos_invalid) + eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), X_COORD_INVALID); + else + { + eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), current_position[X_AXIS]); + eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4), current_position[Y_AXIS]); + } // Store the current feed rate, temperatures, fan speed and extruder multipliers (flow rates) eeprom_update_word((uint16_t*)EEPROM_UVLO_FEEDRATE, feedrate_bckp); @@ -11189,11 +11202,6 @@ bool recover_machine_state_after_power_panic() // Recover last E axis position current_position[E_AXIS] = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_E)); - memcpy(destination, current_position, sizeof(destination)); - - SERIAL_ECHOPGM("recover_machine_state_after_power_panic, initial "); - print_world_coordinates(); - // 3) Initialize the logical to physical coordinate system transformation. world2machine_initialize(); // SERIAL_ECHOPGM("recover_machine_state_after_power_panic, initial "); @@ -11205,7 +11213,11 @@ 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. + clamp_to_software_endstops(current_position); + memcpy(destination, current_position, sizeof(destination)); plan_set_position_curposXYZE(); + SERIAL_ECHOPGM("recover_machine_state_after_power_panic, initial "); + print_world_coordinates(); // 6) Power up the Z motors, mark their positions as known. axis_known_position[Z_AXIS] = true; @@ -11242,7 +11254,7 @@ void restore_print_from_eeprom(bool mbl_was_active) { int feedrate_rec; int feedmultiply_rec; uint8_t fan_speed_rec; - char cmd[30]; + char cmd[48]; char filename[13]; uint8_t depth = 0; char dir_name[9]; @@ -11283,10 +11295,13 @@ void restore_print_from_eeprom(bool mbl_was_active) { // Move to the XY print position in logical coordinates, where the print has been killed, but // without shifting Z along the way. This requires performing the move without mbl. - sprintf_P(cmd, PSTR("G1 X%f Y%f F3000"), - eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0)), - eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4))); - enquecommand(cmd); + float pos_x = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0)); + float pos_y = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4)); + if (pos_x != X_COORD_INVALID) + { + sprintf_P(cmd, PSTR("G1 X%f Y%f F3000"), pos_x, pos_y); + enquecommand(cmd); + } // Enable MBL and switch to logical positioning if (mbl_was_active) @@ -11466,7 +11481,8 @@ void stop_and_save_print_to_ram(float z_move, float e_move) #endif // save the global state at planning time - if (current_block) + bool pos_invalid = XY_NO_RESTORE_FLAG; + if (current_block && !pos_invalid) { memcpy(saved_target, current_block->gcode_target, sizeof(saved_target)); saved_feedrate2 = current_block->gcode_feedrate; @@ -11478,7 +11494,10 @@ void stop_and_save_print_to_ram(float z_move, float e_move) } planner_abort_hard(); //abort printing + memcpy(saved_pos, current_position, sizeof(saved_pos)); + if (pos_invalid) saved_pos[X_AXIS] = X_COORD_INVALID; + saved_feedmultiply2 = feedmultiply; //save feedmultiply saved_active_extruder = active_extruder; //save active_extruder saved_extruder_temperature = degTargetHotend(active_extruder); @@ -11572,6 +11591,13 @@ void restore_print_from_ram_and_continue(float e_move) fans_check_enabled = false; #endif + // do not restore XY for commands that do not require that + if (saved_pos[X_AXIS] == X_COORD_INVALID) + { + saved_pos[X_AXIS] = current_position[X_AXIS]; + saved_pos[Y_AXIS] = current_position[Y_AXIS]; + } + //first move print head in XY to the saved position: plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], current_position[Z_AXIS], saved_pos[E_AXIS] - e_move, homing_feedrate[Z_AXIS]/13, active_extruder); //then move Z diff --git a/Firmware/tmc2130.cpp b/Firmware/tmc2130.cpp index 3f6826908..480efb2ba 100755 --- a/Firmware/tmc2130.cpp +++ b/Firmware/tmc2130.cpp @@ -68,8 +68,9 @@ uint8_t tmc2130_sg_diag_mask = 0x00; uint8_t tmc2130_sg_crash = 0; uint16_t tmc2130_sg_err[4] = {0, 0, 0, 0}; uint16_t tmc2130_sg_cnt[4] = {0, 0, 0, 0}; +#ifdef DEBUG_CRASHDET_COUNTERS bool tmc2130_sg_change = false; - +#endif bool skip_debug_msg = false; @@ -255,7 +256,9 @@ void tmc2130_st_isr() if (tmc2130_sg_cnt[axis] < tmc2130_sg_err[axis]) { tmc2130_sg_cnt[axis] = tmc2130_sg_err[axis]; +#ifdef DEBUG_CRASHDET_COUNTERS tmc2130_sg_change = true; +#endif uint8_t sg_thr = 64; // if (axis == Y_AXIS) sg_thr = 64; if (tmc2130_sg_err[axis] >= sg_thr) @@ -409,7 +412,9 @@ void tmc2130_check_overtemp() } checktime = _millis(); +#ifdef DEBUG_CRASHDET_COUNTERS tmc2130_sg_change = true; +#endif } #ifdef DEBUG_CRASHDET_COUNTERS if (tmc2130_sg_change)