Fixed a non-C++ implementation of the PRUSA specific G-Codes.

Yet another improvements of the bed skew calibration.
This commit is contained in:
bubnikv 2016-07-06 16:12:04 +02:00
parent 1394e7efc6
commit a88c0a30e7
9 changed files with 405 additions and 562 deletions

View file

@ -1223,6 +1223,7 @@ void get_command()
// Return True if a character was found
static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
static inline bool code_seen(const char *code) { return (strchr_pointer = strstr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
static inline float code_value() { return strtod(strchr_pointer+1, NULL); }
static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); }
static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); };
@ -1590,19 +1591,18 @@ void process_commands()
// PRUSA GCODES
/*
if(code_seen('PRUSA')){
if(code_seen('Fir')){
if(code_seen("PRUSA")){
if(code_seen("Fir")){
SERIAL_PROTOCOLLN(FW_version);
} else if(code_seen('Rev')){
} else if(code_seen("Rev")){
SERIAL_PROTOCOLLN(FILAMENT_SIZE "-" ELECTRONICS "-" NOZZLE_TYPE );
} else if(code_seen('Lang')) {
} else if(code_seen("Lang")) {
lcd_force_language_selection();
} else if(code_seen('Lz')) {
} else if(code_seen("Lz")) {
EEPROM_save_B(EEPROM_BABYSTEP_Z,0);
}
//else if (code_seen('Cal')) {
@ -1611,7 +1611,6 @@ void process_commands()
}
else
*/
if(code_seen('G'))
{
switch((int)code_value())
@ -2798,6 +2797,7 @@ void process_commands()
verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short();
}
BedSkewOffsetDetectionResultType result = find_bed_offset_and_skew(verbosity_level);
uint8_t point_too_far_mask = 0;
clean_up_after_endstop_move();
// Print head up.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
@ -2811,27 +2811,14 @@ void process_commands()
// Home in the XY plane.
setup_for_endstop_move();
home_xy();
result = improve_bed_offset_and_skew(1, verbosity_level);
result = improve_bed_offset_and_skew(1, verbosity_level, point_too_far_mask);
clean_up_after_endstop_move();
// Print head up.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder);
st_synchronize();
}
if (result >= BED_SKEW_OFFSET_DETECTION_FAILED) {
lcd_bed_calibration_show_result(result);
} else {
lcd_bed_calibration_show_result(BED_SKEW_OFFSET_DETECTION_FAILED);
lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType(- int8_t(result)));
}
/*
if (result != BED_SKEW_OFFSET_DETECTION_FAILED) {
// Mesh bed leveling.
// Push the commands to the front of the message queue in the reverse order!
// There shall be always enough space reserved for these commands.
enquecommand_front_P((PSTR("G80")));
}
*/
lcd_bed_calibration_show_result(result, point_too_far_mask);
lcd_update_enable(true);
lcd_implementation_clear();
// lcd_return_to_status();
@ -2840,46 +2827,6 @@ void process_commands()
break;
}
case 46: // M46: bed skew and offset with manual Z up
{
// Disable the default update procedure of the display. We will do a modal dialog.
lcd_update_enable(false);
// Let the planner use the uncorrected coordinates.
mbl.reset();
world2machine_reset();
// Move the print head close to the bed.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder);
st_synchronize();
// Home in the XY plane.
set_destination_to_current();
setup_for_endstop_move();
home_xy();
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();
}
bool success = improve_bed_offset_and_skew(1, verbosity_level);
clean_up_after_endstop_move();
// Print head up.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder);
st_synchronize();
if (success) {
// Mesh bed leveling.
// Push the commands to the front of the message queue in the reverse order!
// There shall be always enough space reserved for these commands.
enquecommand_front_P((PSTR("G80")));
}
lcd_update_enable(true);
lcd_implementation_clear();
// lcd_return_to_status();
lcd_update();
break;
}
#if 1
case 48: // M48: scan the bed induction sensor points, print the sensor trigger coordinates to the serial line for visualization on the PC.
{

View file

@ -278,60 +278,60 @@ const char * const MSG_BED_LEVELING_FAILED_POINT_LOW_LANG_TABLE[LANG_NUM] PROGME
MSG_BED_LEVELING_FAILED_POINT_LOW_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_EN[] PROGMEM = "X/Y calibration failed. Please consult manual.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_CZ[] PROGMEM = "Kalibrace X/Y selhala. Nahlednete do manualu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_IT[] PROGMEM = "X/Y calibration failed. Please consult manual.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_ES[] PROGMEM = "X/Y calibration failed. Please consult manual.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_PL[] PROGMEM = "X/Y calibration failed. Please consult manual.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_PL
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_EN[] PROGMEM = "X/Y calibration failed. Front calibration points not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_CZ[] PROGMEM = "Kalibrace X/Y selhala. Predni kalibracni body moc vpredu. Srovnejte tiskarnu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_IT[] PROGMEM = "X/Y calibration failed. Front calibration points not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_ES[] PROGMEM = "X/Y calibration failed. Front calibration points not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_PL[] PROGMEM = "X/Y calibration failed. Front calibration points not reachable.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_EN[] PROGMEM = "X/Y calibration bad. Front calibration points not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_CZ[] PROGMEM = "Kalibrace selhala. Predni kalibracni body moc vpredu. Srovnejte tiskarnu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_IT[] PROGMEM = "X/Y calibration bad. Front calibration points not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_ES[] PROGMEM = "X/Y calibration bad. Front calibration points not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_PL[] PROGMEM = "X/Y calibration bad. Front calibration points not reachable. Fix the printer.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_PL
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_EN[] PROGMEM = "X/Y calibration failed. Left front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_CZ[] PROGMEM = "Kalibrace X/Y selhala. Levy predni bod moc vpredu. Srovnejte tiskarnu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_IT[] PROGMEM = "X/Y calibration failed. Left front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_ES[] PROGMEM = "X/Y calibration failed. Left front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_PL[] PROGMEM = "X/Y calibration failed. Left front calibration point not reachable.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_EN[] PROGMEM = "X/Y calibration bad. Left front calibration point not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_CZ[] PROGMEM = "Kalibrace selhala. Levy predni bod moc vpredu. Srovnejte tiskarnu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_IT[] PROGMEM = "X/Y calibration bad. Left front calibration point not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_ES[] PROGMEM = "X/Y calibration bad. Left front calibration point not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_PL[] PROGMEM = "X/Y calibration bad. Left front calibration point not reachable. Fix the printer.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_PL
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_EN[] PROGMEM = "X/Y calibration failed. Right front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_CZ[] PROGMEM = "Kalibrace X/Y selhala. Pravy predni bod moc vpredu. Srovnejte tiskarnu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_IT[] PROGMEM = "X/Y calibration failed. Right front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_ES[] PROGMEM = "X/Y calibration failed. Right front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_PL[] PROGMEM = "X/Y calibration failed. Right front calibration point not reachable.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_EN[] PROGMEM = "X/Y calibration bad. Right front calibration point not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_CZ[] PROGMEM = "Kalibrace selhala. Pravy predni bod moc vpredu. Srovnejte tiskarnu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_IT[] PROGMEM = "X/Y calibration bad. Right front calibration point not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_ES[] PROGMEM = "X/Y calibration bad. Right front calibration point not reachable. Fix the printer.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_PL[] PROGMEM = "X/Y calibration bad. Right front calibration point not reachable. Fix the printer.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_PL
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_EN[] PROGMEM = "X/Y calibration failed. Please consult the manual.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_CZ[] PROGMEM = "Kalibrace X/Y selhala. Nahlednete do manualu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_IT[] PROGMEM = "X/Y calibration failed. Please consult the manual.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_ES[] PROGMEM = "X/Y calibration failed. Please consult the manual.";
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_PL[] PROGMEM = "X/Y calibration failed. Please consult the manual.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_EN,
MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_IT,
MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_ES,
MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_EN[] PROGMEM = "X/Y calibration ok. X/Y axes are perpendicular.";
const char MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_CZ[] PROGMEM = "Kalibrace X/Y perfektni. X/Y osy jsou kolme.";
const char MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_CZ[] PROGMEM = "X/Y calibration ok. X/Y axes are perpendicular.";
const char MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_IT[] PROGMEM = "X/Y calibration ok. X/Y axes are perpendicular.";
const char MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_ES[] PROGMEM = "X/Y calibration ok. X/Y axes are perpendicular.";
const char MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_PL[] PROGMEM = "X/Y calibration ok. X/Y axes are perpendicular.";
@ -343,6 +343,19 @@ const char * const MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_LANG_TABLE[LANG_NUM] PR
MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_EN[] PROGMEM = "X/Y calibration failed. Bed calibration point was not found.";
const char MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_CZ[] PROGMEM = "Kalibrace X/Y selhala. Kalibracni bod podlozky nenalezen.";
const char MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_IT[] PROGMEM = "X/Y calibration failed. Bed calibration point was not found.";
const char MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_ES[] PROGMEM = "X/Y calibration failed. Bed calibration point was not found.";
const char MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_PL[] PROGMEM = "X/Y calibration failed. Bed calibration point was not found.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_EN,
MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_IT,
MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_ES,
MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME_EN[] PROGMEM = "X/Y skewed severly. Skew will be corrected automatically.";
const char MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME_CZ[] PROGMEM = "X/Y osy jsou silne zkosene. Zkoseni bude automaticky vyrovnano pri tisku.";
const char MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME_IT[] PROGMEM = "X/Y skewed severly. Skew will be corrected automatically.";
@ -369,6 +382,45 @@ const char * const MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD_LANG_TABLE[LANG_NUM]
MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_EN[] PROGMEM = "X/Y calibration compromised. Front calibration points not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_CZ[] PROGMEM = "Kalibrace X/Y nepresna. Predni kalibracni body moc vpredu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_IT[] PROGMEM = "X/Y calibration compromised. Front calibration points not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_ES[] PROGMEM = "X/Y calibration compromised. Front calibration points not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_PL[] PROGMEM = "X/Y calibration compromised. Front calibration points not reachable.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_EN[] PROGMEM = "X/Y calibration compromised. Left front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_CZ[] PROGMEM = "Kalibrace X/Y nepresna. Levy predni bod moc vpredu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_IT[] PROGMEM = "X/Y calibration compromised. Left front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_ES[] PROGMEM = "X/Y calibration compromised. Left front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_PL[] PROGMEM = "X/Y calibration compromised. Left front calibration point not reachable.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_PL
};
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_EN[] PROGMEM = "X/Y calibration compromised. Right front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_CZ[] PROGMEM = "Kalibrace X/Y nepresna. Pravy predni bod moc vpredu.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_IT[] PROGMEM = "X/Y calibration compromised. Right front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_ES[] PROGMEM = "X/Y calibration compromised. Right front calibration point not reachable.";
const char MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_PL[] PROGMEM = "X/Y calibration compromised. Right front calibration point not reachable.";
const char * const MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_LANG_TABLE[LANG_NUM] PROGMEM = {
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_EN,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_CZ,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_IT,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_ES,
MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_PL
};
const char MSG_BEGIN_FILE_LIST_EN[] PROGMEM = "Begin file list";
const char MSG_BEGIN_FILE_LIST_CZ[] PROGMEM = "Begin file list";
const char MSG_BEGIN_FILE_LIST_IT[] PROGMEM = "Begin file list";

View file

@ -50,20 +50,28 @@ extern const char* const MSG_BED_LEVELING_FAILED_POINT_HIGH_LANG_TABLE[LANG_NUM]
#define MSG_BED_LEVELING_FAILED_POINT_HIGH LANG_TABLE_SELECT(MSG_BED_LEVELING_FAILED_POINT_HIGH_LANG_TABLE)
extern const char* const MSG_BED_LEVELING_FAILED_POINT_LOW_LANG_TABLE[LANG_NUM];
#define MSG_BED_LEVELING_FAILED_POINT_LOW LANG_TABLE_SELECT(MSG_BED_LEVELING_FAILED_POINT_LOW_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FAILED_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_PERFECT_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR_LANG_TABLE)
extern const char* const MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_LANG_TABLE[LANG_NUM];
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR LANG_TABLE_SELECT(MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR_LANG_TABLE)
extern const char* const MSG_BEGIN_FILE_LIST_LANG_TABLE[LANG_NUM];
#define MSG_BEGIN_FILE_LIST LANG_TABLE_SELECT(MSG_BEGIN_FILE_LIST_LANG_TABLE)
extern const char* const MSG_BROWNOUT_RESET_LANG_TABLE[LANG_NUM];

View file

@ -297,13 +297,17 @@
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 "kalibracniho bodu"
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3 " z 9"
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED "Kalibrace X/Y selhala. Nahlednete do manualu."
#define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT "Kalibrace X/Y perfektni. X/Y osy jsou kolme."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD "Kalibrace X/Y v poradku. X/Y osy mirne zkosene."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME "X/Y osy jsou silne zkosene. Zkoseni bude automaticky vyrovnano pri tisku."
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR "Kalibrace selhala. Levy predni bod moc vpredu. Srovnejte tiskarnu."
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR "Kalibrace selhala. Pravy predni bod moc vpredu. Srovnejte tiskarnu."
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR "Kalibrace selhala. Predni kalibracni body moc vpredu. Srovnejte tiskarnu."
#define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND "Kalibrace X/Y selhala. Kalibracni bod podlozky nenalezen."
#define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED "Kalibrace X/Y selhala. Nahlednete do manualu."
#define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT "X/Y calibration ok. X/Y axes are perpendicular."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD "Kalibrace X/Y v poradku. X/Y osy mirne zkosene."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME "X/Y osy jsou silne zkosene. Zkoseni bude automaticky vyrovnano pri tisku."
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR "Kalibrace X/Y selhala. Levy predni bod moc vpredu. Srovnejte tiskarnu."
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR "Kalibrace X/Y selhala. Pravy predni bod moc vpredu. Srovnejte tiskarnu."
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR "Kalibrace X/Y selhala. Predni kalibracni body moc vpredu. Srovnejte tiskarnu."
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR "Kalibrace X/Y nepresna. Levy predni bod moc vpredu."
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR "Kalibrace X/Y nepresna. Pravy predni bod moc vpredu."
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR "Kalibrace X/Y nepresna. Predni kalibracni body moc vpredu."
#define MSG_BED_LEVELING_FAILED_POINT_LOW "Kalibrace Z selhala. Sensor nesepnul. Znecistena tryska? Cekam na reset."
#define MSG_BED_LEVELING_FAILED_POINT_HIGH "Kalibrace Z selhala. Sensor sepnul prilis vysoko. Cekam na reset."

View file

@ -290,15 +290,19 @@
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 "calibration point"
#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3 " of 9"
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED "X/Y calibration failed. Please consult manual."
#define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT "X/Y calibration ok. X/Y axes are perpendicular."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD "X/Y calibration all right. X/Y axes are slightly skewed."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME "X/Y skewed severly. Skew will be corrected automatically."
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR "X/Y calibration bad. Left front calibration point not reachable. Fix the printer."
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR "X/Y calibration bad. Right front calibration point not reachable. Fix the printer."
#define MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR "X/Y calibration bad. Front calibration points not reachable. Fix the printer."
#define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND "X/Y calibration failed. Bed calibration point was not found."
#define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED "X/Y calibration failed. Please consult the manual."
#define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT "X/Y calibration ok. X/Y axes are perpendicular."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD "X/Y calibration all right. X/Y axes are slightly skewed."
#define MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME "X/Y skewed severly. Skew will be corrected automatically."
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR "X/Y calibration failed. Left front calibration point not reachable."
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR "X/Y calibration failed. Right front calibration point not reachable."
#define MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR "X/Y calibration failed. Front calibration points not reachable."
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR "X/Y calibration compromised. Left front calibration point not reachable."
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR "X/Y calibration compromised. Right front calibration point not reachable."
#define MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR "X/Y calibration compromised. Front calibration points not reachable."
#define MSG_BED_LEVELING_FAILED_POINT_LOW "Bed leveling failed. Sensor didnt trigger. Debris on nozzle? Waiting for reset."
#define MSG_BED_LEVELING_FAILED_POINT_HIGH "Bed leveling failed. Sensor triggered too high. Waiting for reset."
#define MSG_BED_LEVELING_FAILED_POINT_LOW "Bed leveling failed. Sensor didnt trigger. Debris on nozzle? Waiting for reset."
#define MSG_BED_LEVELING_FAILED_POINT_HIGH "Bed leveling failed. Sensor triggered too high. Waiting for reset."
#endif // LANGUAGE_EN_H

View file

@ -5,7 +5,6 @@
#include "mesh_bed_leveling.h"
#include "stepper.h"
#include "ultralcd.h"
// #include "qr_solve.h"
uint8_t world2machine_correction_mode;
float world2machine_rotation_and_skew[2][2];
@ -14,7 +13,10 @@ float world2machine_shift[2];
// Weight of the Y coordinate for the least squares fitting of the bed induction sensor targets.
// Only used for the first row of the points, which may not befully in reach of the sensor.
#define WEIGHT_FIRST_ROW (0.2f)
#define WEIGHT_FIRST_ROW_X_HIGH (1.f)
#define WEIGHT_FIRST_ROW_X_LOW (0.35f)
#define WEIGHT_FIRST_ROW_Y_HIGH (0.3f)
#define WEIGHT_FIRST_ROW_Y_LOW (0.0f)
#define BED_ZERO_REF_X (- 22.f + X_PROBE_OFFSET_FROM_EXTRUDER)
#define BED_ZERO_REF_Y (- 0.6f + Y_PROBE_OFFSET_FROM_EXTRUDER)
@ -37,6 +39,14 @@ float world2machine_shift[2];
#define MIN_BED_SENSOR_POINT_RESPONSE_DMR (2.0f)
//#define Y_MIN_POS_FOR_BED_CALIBRATION (MANUAL_Y_HOME_POS-0.2f)
#define Y_MIN_POS_FOR_BED_CALIBRATION (Y_MIN_POS)
// Distances toward the print bed edge may not be accurate.
#define Y_MIN_POS_CALIBRATION_POINT_ACCURATE (Y_MIN_POS + 3.f)
// When the measured point center is out of reach of the sensor, Y coordinate will be ignored
// by the Least Squares fitting and the X coordinate will be weighted low.
#define Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH (Y_MIN_POS - 0.5f)
// Positions of the bed reference points in the machine coordinates, referenced to the P.I.N.D.A sensor.
// The points are ordered in a zig-zag fashion to speed up the calibration.
const float bed_ref_points[] PROGMEM = {
@ -62,314 +72,48 @@ const float bed_ref_points_4[] PROGMEM = {
13.f - BED_ZERO_REF_X, 104.4f - BED_ZERO_REF_Y
};
//#define Y_MIN_POS_FOR_BED_CALIBRATION (MANUAL_Y_HOME_POS-0.2f)
#define Y_MIN_POS_FOR_BED_CALIBRATION (Y_MIN_POS)
static inline float sqr(float x) { return x * x; }
#if 0
// Linear Least Squares fitting of the bed to the measured induction points.
// This method will not maintain a unity length of the machine axes.
// This may be all right if the sensor points are measured precisely,
// but it will stretch or shorten the machine axes if the measured data is not precise enough.
bool calculate_machine_skew_and_offset_LS(
// Matrix of maximum 9 2D points (18 floats)
const float *measured_pts,
uint8_t npts,
const float *true_pts,
// Resulting correction matrix.
float *vec_x,
float *vec_y,
float *cntr,
// Temporary values, 49-18-(2*3)=25 floats
// , float *temp
int8_t verbosity_level
)
{
if (verbosity_level >= 10) {
// Show the initial state, before the fitting.
SERIAL_ECHOPGM("X vector, initial: ");
MYSERIAL.print(vec_x[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_x[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("Y vector, initial: ");
MYSERIAL.print(vec_y[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_y[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("center, initial: ");
MYSERIAL.print(cntr[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(cntr[1], 5);
SERIAL_ECHOLNPGM("");
for (uint8_t i = 0; i < npts; ++ i) {
SERIAL_ECHOPGM("point #");
MYSERIAL.print(int(i));
SERIAL_ECHOPGM(" measured: (");
MYSERIAL.print(measured_pts[i*2], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(measured_pts[i*2+1], 5);
SERIAL_ECHOPGM("); target: (");
MYSERIAL.print(pgm_read_float(true_pts+i*2 ), 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(pgm_read_float(true_pts+i*2+1), 5);
SERIAL_ECHOPGM("), error: ");
MYSERIAL.print(sqrt(
sqr(pgm_read_float(true_pts+i*2 ) - measured_pts[i*2 ]) +
sqr(pgm_read_float(true_pts+i*2+1) - measured_pts[i*2+1])), 5);
SERIAL_ECHOLNPGM("");
}
delay_keep_alive(100);
}
{
// Create covariance matrix for A, collect the right hand side b.
float A[3][3] = { 0.f };
float b[3] = { 0.f };
float acc;
for (uint8_t r = 0; r < 3; ++ r) {
for (uint8_t c = 0; c < 3; ++ c) {
acc = 0;
for (uint8_t i = 0; i < npts; ++ i) {
float a = (r == 2) ? 1.f : measured_pts[2 * i + r];
float b = (c == 2) ? 1.f : measured_pts[2 * i + c];
acc += a * b;
}
A[r][c] = acc;
}
acc = 0.f;
for (uint8_t i = 0; i < npts; ++ i) {
float a = (r == 2) ? 1.f : measured_pts[2 * i + r];
float b = pgm_read_float(true_pts+i*2);
acc += a * b;
}
b[r] = acc;
}
// Solve the linear equation for ax, bx, cx.
float x[3] = { 0.f };
for (uint8_t iter = 0; iter < 100; ++ iter) {
x[0] = (b[0] - A[0][1] * x[1] - A[0][2] * x[2]) / A[0][0];
x[1] = (b[1] - A[1][0] * x[0] - A[1][2] * x[2]) / A[1][1];
x[2] = (b[2] - A[2][0] * x[0] - A[2][1] * x[1]) / A[2][2];
}
// Store the result to the output variables.
vec_x[0] = x[0];
vec_y[0] = x[1];
cntr[0] = x[2];
// Recalculate A and b for the y values.
// Note the weighting of the first row of values.
for (uint8_t r = 0; r < 3; ++ r) {
for (uint8_t c = 0; c < 3; ++ c) {
acc = 0;
for (uint8_t i = 0; i < npts; ++ i) {
float w = (i < 3) ? WEIGHT_FIRST_ROW : 1.f;
float a = (r == 2) ? 1.f : measured_pts[2 * i + r];
float b = (c == 2) ? 1.f : measured_pts[2 * i + c];
acc += a * b * w;
}
A[r][c] = acc;
}
acc = 0.f;
for (uint8_t i = 0; i < npts; ++ i) {
float w = (i < 3) ? WEIGHT_FIRST_ROW : 1.f;
float a = (r == 2) ? 1.f : measured_pts[2 * i + r];
float b = pgm_read_float(true_pts+i*2+1);
acc += w * a * b;
}
b[r] = acc;
}
// Solve the linear equation for ay, by, cy.
x[0] = 0.f, x[1] = 0.f; x[2] = 0.f;
for (uint8_t iter = 0; iter < 100; ++ iter) {
x[0] = (b[0] - A[0][1] * x[1] - A[0][2] * x[2]) / A[0][0];
x[1] = (b[1] - A[1][0] * x[0] - A[1][2] * x[2]) / A[1][1];
x[2] = (b[2] - A[2][0] * x[0] - A[2][1] * x[1]) / A[2][2];
}
// Store the result to the output variables.
vec_x[1] = x[0];
vec_y[1] = x[1];
cntr[1] = x[2];
}
if (verbosity_level >= 10) {
// Show the adjusted state, before the fitting.
SERIAL_ECHOPGM("X vector new, inverted: ");
MYSERIAL.print(vec_x[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_x[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("Y vector new, inverted: ");
MYSERIAL.print(vec_y[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_y[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("center new, inverted: ");
MYSERIAL.print(cntr[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(cntr[1], 5);
SERIAL_ECHOLNPGM("");
delay_keep_alive(100);
SERIAL_ECHOLNPGM("Error after correction: ");
for (uint8_t i = 0; i < npts; ++ i) {
float x = vec_x[0] * measured_pts[i*2] + vec_y[0] * measured_pts[i*2+1] + cntr[0];
float y = vec_x[1] * measured_pts[i*2] + vec_y[1] * measured_pts[i*2+1] + cntr[1];
SERIAL_ECHOPGM("point #");
MYSERIAL.print(int(i));
SERIAL_ECHOPGM(" measured: (");
MYSERIAL.print(measured_pts[i*2], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(measured_pts[i*2+1], 5);
SERIAL_ECHOPGM("); corrected: (");
MYSERIAL.print(x, 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(y, 5);
SERIAL_ECHOPGM("); target: (");
MYSERIAL.print(pgm_read_float(true_pts+i*2 ), 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(pgm_read_float(true_pts+i*2+1), 5);
SERIAL_ECHOPGM("), error: ");
MYSERIAL.print(sqrt(sqr(pgm_read_float(true_pts+i*2)-x)+sqr(pgm_read_float(true_pts+i*2+1)-y)));
SERIAL_ECHOLNPGM("");
}
}
#if 0
// Normalize the vectors. We expect, that the machine axes may be skewed a bit, but the distances are correct.
// l shall be very close to 1 already.
float l = sqrt(vec_x[0]*vec_x[0] + vec_x[1] * vec_x[1]);
vec_x[0] /= l;
vec_x[1] /= l;
SERIAL_ECHOPGM("Length of the X vector: ");
MYSERIAL.print(l, 5);
SERIAL_ECHOLNPGM("");
l = sqrt(vec_y[0]*vec_y[0] + vec_y[1] * vec_y[1]);
vec_y[0] /= l;
vec_y[1] /= l;
SERIAL_ECHOPGM("Length of the Y vector: ");
MYSERIAL.print(l, 5);
SERIAL_ECHOLNPGM("");
// Recalculate the center using the adjusted vec_x/vec_y
{
cntr[0] = 0.f;
cntr[1] = 0.f;
for (uint8_t i = 0; i < npts; ++ i) {
cntr[0] += measured_pts[2 * i ] - pgm_read_float(true_pts+i*2) * vec_x[0] - pgm_read_float(true_pts+i*2+1) * vec_y[0];
cntr[1] += measured_pts[2 * i + 1] - pgm_read_float(true_pts+i*2) * vec_x[1] - pgm_read_float(true_pts+i*2+1) * vec_y[1];
}
cntr[0] /= float(npts);
cntr[1] /= float(npts);
}
SERIAL_ECHOPGM("X vector new, inverted, normalized: ");
MYSERIAL.print(vec_x[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_x[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("Y vector new, inverted, normalized: ");
MYSERIAL.print(vec_y[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_y[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("center new, inverted, normalized: ");
MYSERIAL.print(cntr[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(cntr[1], 5);
SERIAL_ECHOLNPGM("");
#endif
// Invert the transformation matrix made of vec_x, vec_y and cntr.
{
float d = vec_x[0] * vec_y[1] - vec_x[1] * vec_y[0];
float Ainv[2][2] = {
{ vec_y[1] / d, - vec_y[0] / d },
{ - vec_x[1] / d, vec_x[0] / d }
};
float cntrInv[2] = {
- Ainv[0][0] * cntr[0] - Ainv[0][1] * cntr[1],
- Ainv[1][0] * cntr[0] - Ainv[1][1] * cntr[1]
};
vec_x[0] = Ainv[0][0];
vec_x[1] = Ainv[1][0];
vec_y[0] = Ainv[0][1];
vec_y[1] = Ainv[1][1];
cntr[0] = cntrInv[0];
cntr[1] = cntrInv[1];
}
if (verbosity_level >= 1) {
// Show the adjusted state, before the fitting.
SERIAL_ECHOPGM("X vector, adjusted: ");
MYSERIAL.print(vec_x[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_x[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("Y vector, adjusted: ");
MYSERIAL.print(vec_y[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(vec_y[1], 5);
SERIAL_ECHOLNPGM("");
SERIAL_ECHOPGM("center, adjusted: ");
MYSERIAL.print(cntr[0], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(cntr[1], 5);
SERIAL_ECHOLNPGM("");
delay_keep_alive(100);
}
if (verbosity_level >= 2) {
SERIAL_ECHOLNPGM("Difference after correction: ");
for (uint8_t i = 0; i < npts; ++ i) {
float x = vec_x[0] * pgm_read_float(true_pts+i*2) + vec_y[0] * pgm_read_float(true_pts+i*2+1) + cntr[0];
float y = vec_x[1] * pgm_read_float(true_pts+i*2) + vec_y[1] * pgm_read_float(true_pts+i*2+1) + cntr[1];
SERIAL_ECHOPGM("point #");
MYSERIAL.print(int(i));
SERIAL_ECHOPGM("measured: (");
MYSERIAL.print(measured_pts[i*2], 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(measured_pts[i*2+1], 5);
SERIAL_ECHOPGM("); measured-corrected: (");
MYSERIAL.print(x, 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(y, 5);
SERIAL_ECHOPGM("); target: (");
MYSERIAL.print(pgm_read_float(true_pts+i*2 ), 5);
SERIAL_ECHOPGM(", ");
MYSERIAL.print(pgm_read_float(true_pts+i*2+1), 5);
SERIAL_ECHOPGM("), error: ");
MYSERIAL.print(sqrt(sqr(measured_pts[i*2]-x)+sqr(measured_pts[i*2+1]-y)));
SERIAL_ECHOLNPGM("");
}
delay_keep_alive(100);
}
return true;
}
#else
static inline float point_weight_y(uint8_t i, BedSkewOffsetDetectionResultType measured_points_status)
// Weight of a point coordinate in a least squares optimization.
// The first row of points may not be fully reachable
// and the y values may be shortened a bit by the bed carriage
// pulling the belt up.
static inline float point_weight_x(const uint8_t i, const float &y)
{
float w = 1.f;
if (i < 3) {
w = WEIGHT_FIRST_ROW;
if ((i == 0 && (measured_points_status & BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR)) ||
(i == 1 && (measured_points_status & BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR)) ||
(i == 2 && (measured_points_status & BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR)))
w = 0.f;
if (y >= Y_MIN_POS_CALIBRATION_POINT_ACCURATE) {
w = WEIGHT_FIRST_ROW_X_HIGH;
} else if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) {
// If the point is fully outside, give it some weight.
w = WEIGHT_FIRST_ROW_X_LOW;
} else {
// Linearly interpolate the weight from 1 to WEIGHT_FIRST_ROW_X.
float t = (y - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) / (Y_MIN_POS_CALIBRATION_POINT_ACCURATE - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH);
w = (1.f - t) * WEIGHT_FIRST_ROW_X_LOW + t * WEIGHT_FIRST_ROW_X_HIGH;
}
}
return w;
}
// Weight of a point coordinate in a least squares optimization.
// The first row of points may not be fully reachable
// and the y values may be shortened a bit by the bed carriage
// pulling the belt up.
static inline float point_weight_y(const uint8_t i, const float &y)
{
float w = 1.f;
if (i < 3) {
if (y >= Y_MIN_POS_CALIBRATION_POINT_ACCURATE) {
w = WEIGHT_FIRST_ROW_Y_HIGH;
} else if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) {
// If the point is fully outside, give it some weight.
w = WEIGHT_FIRST_ROW_Y_LOW;
} else {
// Linearly interpolate the weight from 1 to WEIGHT_FIRST_ROW_X.
float t = (y - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH) / (Y_MIN_POS_CALIBRATION_POINT_ACCURATE - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH);
w = (1.f - t) * WEIGHT_FIRST_ROW_Y_LOW + t * WEIGHT_FIRST_ROW_Y_HIGH;
}
}
return w;
}
@ -382,7 +126,6 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
// Matrix of maximum 9 2D points (18 floats)
const float *measured_pts,
uint8_t npts,
BedSkewOffsetDetectionResultType measured_points_status,
const float *true_pts,
// Resulting correction matrix.
float *vec_x,
@ -466,7 +209,8 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
(c == 0) ? 1.f :
((c == 2) ? (-s1 * measured_pts[2 * i]) :
(-c2 * measured_pts[2 * i + 1]));
acc += a * b;
float w = point_weight_x(i, measured_pts[2 * i + 1]);
acc += a * b * w;
}
// Second for the residuum in the y axis.
// The first row of the points have a low weight, because their position may not be known
@ -480,7 +224,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
(c == 1) ? 1.f :
((c == 2) ? ( c1 * measured_pts[2 * i]) :
(-s2 * measured_pts[2 * i + 1]));
float w = point_weight_y(i, measured_points_status);
float w = point_weight_y(i, measured_pts[2 * i + 1]);
acc += a * b * w;
}
}
@ -496,7 +240,8 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
((r == 2) ? (-s1 * measured_pts[2 * i]) :
(-c2 * measured_pts[2 * i + 1])));
float fx = c1 * measured_pts[2 * i] - s2 * measured_pts[2 * i + 1] + cntr[0] - pgm_read_float(true_pts + i * 2);
acc += j * fx;
float w = point_weight_x(i, measured_pts[2 * i + 1]);
acc += j * fx * w;
}
{
float j =
@ -505,7 +250,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
((r == 2) ? ( c1 * measured_pts[2 * i]) :
(-s2 * measured_pts[2 * i + 1])));
float fy = s1 * measured_pts[2 * i] + c2 * measured_pts[2 * i + 1] + cntr[1] - pgm_read_float(true_pts + i * 2 + 1);
float w = point_weight_y(i, measured_points_status);
float w = point_weight_y(i, measured_pts[2 * i + 1]);
acc += j * fy * w;
}
}
@ -612,13 +357,13 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
float errY = sqr(pgm_read_float(true_pts + i * 2 + 1) - y);
float err = sqrt(errX + errY);
if (i < 3) {
float w = point_weight_y(i, measured_points_status);
float w = point_weight_y(i, measured_pts[2 * i + 1]);
if (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X ||
(w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y))
result = (measured_points_status == BED_SKEW_OFFSET_DETECTION_PERFECT) ? BED_SKEW_OFFSET_DETECTION_FAILED : BedSkewOffsetDetectionResultType(- int8_t(measured_points_status));
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
} else {
if (err > BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN)
result = (measured_points_status == BED_SKEW_OFFSET_DETECTION_PERFECT) ? BED_SKEW_OFFSET_DETECTION_FAILED : BedSkewOffsetDetectionResultType(- int8_t(measured_points_status));
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
}
if (verbosity_level >= 10) {
SERIAL_ECHOPGM("point #");
@ -664,16 +409,19 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
// Refresh the offset.
cntr[0] = 0.f;
cntr[1] = 0.f;
float wx = 0.f;
float wy = 0.f;
for (int8_t i = 0; i < 9; ++ i) {
float x = vec_x[0] * measured_pts[i * 2] + vec_y[0] * measured_pts[i * 2 + 1];
float y = vec_x[1] * measured_pts[i * 2] + vec_y[1] * measured_pts[i * 2 + 1];
float w = (i < 3) ? WEIGHT_FIRST_ROW : 1.f;
cntr[0] += pgm_read_float(true_pts + i * 2) - x;
float w = point_weight_x(i, y);
cntr[0] += w * (pgm_read_float(true_pts + i * 2) - x);
wx += w;
w = point_weight_y(i, y);
cntr[1] += w * (pgm_read_float(true_pts + i * 2 + 1) - y);
wy += w;
}
cntr[0] /= 9.f;
cntr[0] /= wx;
cntr[1] /= wy;
}
#endif
@ -745,14 +493,9 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
delay_keep_alive(100);
}
if (result >= 0 && measured_points_status > 0)
// Maintain the "left / right / both points out of reach" status.
result = measured_points_status;
return result;
}
#endif
void reset_bed_offset_and_skew()
{
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+0), 0x0FFFFFFFF);
@ -1312,6 +1055,11 @@ inline bool improve_bed_induction_sensor_point2(bool lift_z_on_min_y, int8_t ver
}
b = current_position[X_AXIS];
if (b - a < MIN_BED_SENSOR_POINT_RESPONSE_DMR) {
if (verbosity_level >= 5) {
SERIAL_ECHOPGM("Point width too small: ");
SERIAL_ECHO(b - a);
SERIAL_ECHOLNPGM("");
}
// We force the calibration routine to move the Z axis slightly down to make the response more pronounced.
current_position[X_AXIS] = center_old_x;
goto canceled;
@ -1372,8 +1120,13 @@ inline bool improve_bed_induction_sensor_point2(bool lift_z_on_min_y, int8_t ver
b = current_position[Y_AXIS];
if (b - a < MIN_BED_SENSOR_POINT_RESPONSE_DMR) {
// We force the calibration routine to move the Z axis slightly down to make the response more pronounced.
if (verbosity_level >= 5) {
SERIAL_ECHOPGM("Point height too small: ");
SERIAL_ECHO(b - a);
SERIAL_ECHOLNPGM("");
}
current_position[Y_AXIS] = center_old_y;
goto canceled;
goto canceled;
}
if (verbosity_level >= 5) {
debug_output_point(PSTR("top" ), current_position[X_AXIS], a, current_position[Z_AXIS]);
@ -1399,20 +1152,18 @@ canceled:
// Searching in a zig-zag movement in a plane for the maximum width of the response.
#define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_RADIUS (4.f)
#define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_STEP_FINE_Y (0.1f)
enum InductionSensorPointStatusType
{
INDUCTION_SENSOR_POINT_FAILED = -1,
INDUCTION_SENSOR_POINT_OK = 0,
INDUCTION_SENSOR_POINT_FAR = 1,
};
inline InductionSensorPointStatusType improve_bed_induction_sensor_point3(int verbosity_level)
inline bool improve_bed_induction_sensor_point3(int verbosity_level)
{
if (current_position[Y_AXIS] < Y_MIN_POS_FOR_BED_CALIBRATION)
current_position[Y_AXIS] = Y_MIN_POS_FOR_BED_CALIBRATION;
float center_old_x = current_position[X_AXIS];
float center_old_y = current_position[Y_AXIS];
float a, b;
bool result = true;
// Was the sensor point detected too far in the minus Y axis?
// If yes, the center of the induction point cannot be reached by the machine.
bool y_too_far = false;
{
float x0 = center_old_x - IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_RADIUS;
float x1 = center_old_x + IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_RADIUS;
@ -1438,6 +1189,7 @@ inline InductionSensorPointStatusType improve_bed_induction_sensor_point3(int ve
}
// Search in the positive Y direction, until a maximum diameter is found.
// (the next diameter is smaller than the current one.)
float dmax = 0.f;
float xmax1 = 0.f;
float xmax2 = 0.f;
@ -1482,14 +1234,37 @@ inline InductionSensorPointStatusType improve_bed_induction_sensor_point3(int ve
if (dmax == 0.) {
if (verbosity_level > 0)
SERIAL_PROTOCOLPGM("failed - not found\n");
current_position[X_AXIS] = center_old_x;
current_position[Y_AXIS] = center_old_y;
goto canceled;
}
{
// Find the positive Y hit. This gives the extreme Y value for the search of the maximum diameter in the -Y direction.
enable_z_endstop(false);
go_xy(xmax1, y0 + IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS, homing_feedrate[X_AXIS] / 60.f);
enable_z_endstop(true);
go_xy(xmax1, max(y0 - IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS, Y_MIN_POS_FOR_BED_CALIBRATION), homing_feedrate[X_AXIS] / 60.f);
update_current_position_xyz();
if (! endstop_z_hit_on_purpose()) {
current_position[Y_AXIS] = center_old_y;
goto canceled;
}
if (verbosity_level >= 5)
debug_output_point(PSTR("top" ), current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS]);
y1 = current_position[Y_AXIS];
}
if (y1 <= y0) {
// Either the induction sensor is too high, or the induction sensor target is out of reach.
current_position[Y_AXIS] = center_old_y;
goto canceled;
}
// SERIAL_PROTOCOLPGM("ok 1\n");
// Search in the negative Y direction, until a maximum diameter is found.
dmax = 0.f;
if (y0 + 1.f < y1)
y1 = y0 + 1.f;
// if (y0 + 1.f < y1)
// y1 = y0 + 1.f;
for (y = y1; y >= y0; y -= IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_STEP_FINE_Y) {
enable_z_endstop(false);
go_xy(x0, y, homing_feedrate[X_AXIS] / 60.f);
@ -1585,7 +1360,7 @@ inline InductionSensorPointStatusType improve_bed_induction_sensor_point3(int ve
{
// Compare the distance in the Y+ direction with the diameter in the X direction.
// Find the positive Y hit.
// Find the positive Y hit once again, this time along the Y axis going through the X point with the highest diameter.
enable_z_endstop(false);
go_xy(xmax, ymax + IMPROVE_BED_INDUCTION_SENSOR_SEARCH_RADIUS, homing_feedrate[X_AXIS] / 60.f);
enable_z_endstop(true);
@ -1597,19 +1372,45 @@ inline InductionSensorPointStatusType improve_bed_induction_sensor_point3(int ve
}
if (verbosity_level >= 5)
debug_output_point(PSTR("top" ), current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS]);
if (current_position[Y_AXIS] - y0 < 0.5f * dmax) {
// Probably not even a half circle was detected. The induction point is too far in the minus Y direction.
if (current_position[Y_AXIS] - 0.5f * dmax < Y_MIN_POS_FOR_BED_CALIBRATION - 0.6f) {
ymax = current_position[Y_AXIS] - 0.5f * dmax;
// ymax = Y_MIN_POS_FOR_BED_CALIBRATION;
y_too_far = true;
if (current_position[Y_AXIS] - Y_MIN_POS_FOR_BED_CALIBRATION < 0.5f * dmax) {
// Probably not even a half circle was detected. The induction point is likely too far in the minus Y direction.
// First verify, if the measurement has been done at a sufficient height. If no, lower the Z axis a bit.
if (current_position[Y_AXIS] < ymax || dmax < 0.5f * MIN_BED_SENSOR_POINT_RESPONSE_DMR) {
if (verbosity_level >= 5) {
SERIAL_ECHOPGM("Partial point diameter too small: ");
SERIAL_ECHO(dmax);
SERIAL_ECHOLNPGM("");
}
result = false;
} else {
ymax = current_position[Y_AXIS] - 0.5f * dmax;
// Estimate the circle radius from the maximum diameter and height:
float h = current_position[Y_AXIS] - ymax;
float r = dmax * dmax / (8.f * h) + 0.5f * h;
if (r < 0.8f * MIN_BED_SENSOR_POINT_RESPONSE_DMR) {
if (verbosity_level >= 5) {
SERIAL_ECHOPGM("Partial point estimated radius too small: ");
SERIAL_ECHO(r);
SERIAL_ECHOPGM(", dmax:");
SERIAL_ECHO(dmax);
SERIAL_ECHOPGM(", h:");
SERIAL_ECHO(h);
SERIAL_ECHOLNPGM("");
}
result = false;
} else {
// The point may end up outside of the machine working space.
// That is all right as it helps to improve the accuracy of the measurement point
// due to averaging.
// For the y correction, use an average of dmax/2 and the estimated radius.
r = 0.5f * (0.5f * dmax + r);
ymax = current_position[Y_AXIS] - r;
}
}
//FIXME
if (ymax < Y_MIN_POS_FOR_BED_CALIBRATION)
ymax = Y_MIN_POS_FOR_BED_CALIBRATION;
} else {
// If the diameter of the detected spot was smaller than a minimum allowed,
// the induction sensor is probably too high. Returning false will force
// the sensor to be lowered a tiny bit.
result = xmax >= MIN_BED_SENSOR_POINT_RESPONSE_DMR;
ymax = 0.5f * (y0 + y1);
}
}
@ -1629,13 +1430,13 @@ inline InductionSensorPointStatusType improve_bed_induction_sensor_point3(int ve
// delay_keep_alive(3000);
}
return y_too_far ? INDUCTION_SENSOR_POINT_FAR : INDUCTION_SENSOR_POINT_OK;
return result;
canceled:
// Go back to the center.
enable_z_endstop(false);
go_xy(current_position[X_AXIS], current_position[Y_AXIS], homing_feedrate[X_AXIS] / 60.f);
return INDUCTION_SENSOR_POINT_FAILED;
return false;
}
// Scan the mesh bed induction points one by one by a left-right zig-zag movement,
@ -1738,17 +1539,17 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
if (verbosity_level >= 10)
delay_keep_alive(3000);
if (! find_bed_induction_sensor_point_xy())
return BED_SKEW_OFFSET_DETECTION_FAILED;
find_bed_induction_sensor_point_z();
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
#if 1
if (k == 0) {
// Improve the position of the 1st row sensor points by a zig-zag movement.
find_bed_induction_sensor_point_z();
int8_t i = 4;
for (;;) {
if (improve_bed_induction_sensor_point3(verbosity_level) != INDUCTION_SENSOR_POINT_FAILED)
if (improve_bed_induction_sensor_point3(verbosity_level))
break;
if (-- i == 0)
return BED_SKEW_OFFSET_DETECTION_FAILED;
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
// Try to move the Z axis down a bit to increase a chance of the sensor to trigger.
current_position[Z_AXIS] -= 0.025f;
enable_endstops(false);
@ -1757,7 +1558,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
}
if (i == 0)
// not found
return BED_SKEW_OFFSET_DETECTION_FAILED;
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
}
#endif
if (verbosity_level >= 10)
@ -1791,44 +1592,49 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
}
}
calculate_machine_skew_and_offset_LS(pts, 4, BED_SKEW_OFFSET_DETECTION_PERFECT, bed_ref_points_4, vec_x, vec_y, cntr, verbosity_level);
world2machine_update(vec_x, vec_y, cntr);
#if 1
// Fearlessly store the calibration values into the eeprom.
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0), cntr [0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4), cntr [1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +0), vec_x[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +4), vec_x[1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +0), vec_y[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +4), vec_y[1]);
#endif
BedSkewOffsetDetectionResultType result = calculate_machine_skew_and_offset_LS(pts, 4, bed_ref_points_4, vec_x, vec_y, cntr, verbosity_level);
if (result >= 0) {
world2machine_update(vec_x, vec_y, cntr);
#if 1
// Fearlessly store the calibration values into the eeprom.
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0), cntr [0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4), cntr [1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +0), vec_x[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +4), vec_x[1]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +0), vec_y[0]);
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +4), vec_y[1]);
#endif
// Correct the current_position to match the transformed coordinate system after world2machine_rotation_and_skew and world2machine_shift were set.
world2machine_update_current();
// Correct the current_position to match the transformed coordinate system after world2machine_rotation_and_skew and world2machine_shift were set.
world2machine_update_current();
if (verbosity_level >= 20) {
// Test the positions. Are the positions reproducible? Now the calibration is active in the planner.
delay_keep_alive(3000);
for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) {
// Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout();
// Go to the measurement point.
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
current_position[X_AXIS] = pgm_read_float(bed_ref_points+mesh_point*2);
current_position[Y_AXIS] = pgm_read_float(bed_ref_points+mesh_point*2+1);
go_to_current(homing_feedrate[X_AXIS]/60);
if (verbosity_level >= 20) {
// Test the positions. Are the positions reproducible? Now the calibration is active in the planner.
delay_keep_alive(3000);
for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) {
// Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout();
// Go to the measurement point.
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
current_position[X_AXIS] = pgm_read_float(bed_ref_points+mesh_point*2);
current_position[Y_AXIS] = pgm_read_float(bed_ref_points+mesh_point*2+1);
go_to_current(homing_feedrate[X_AXIS]/60);
delay_keep_alive(3000);
}
}
}
return BED_SKEW_OFFSET_DETECTION_PERFECT;
return result;
}
BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level)
BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask)
{
// Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout();
// Mask of the first three points. Are they too far?
too_far_mask = 0;
// Reusing the z_values memory for the measurement cache.
// 7x7=49 floats, good for 16 (x,y,z) vectors.
float *pts = &mbl.z_values[0][0];
@ -1857,9 +1663,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
// Collect a matrix of 9x9 points.
bool leftFrontTooFar = false;
bool rightFrontTooFar = false;
int8_t result = BED_SKEW_OFFSET_DETECTION_PERFECT;
BedSkewOffsetDetectionResultType result = BED_SKEW_OFFSET_DETECTION_PERFECT;
for (int8_t mesh_point = 0; mesh_point < 9; ++ mesh_point) {
// Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout();
@ -1900,6 +1704,8 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
find_bed_induction_sensor_point_z();
if (verbosity_level >= 10)
delay_keep_alive(3000);
// Try to move the Z axis down a bit to increase a chance of the sensor to trigger.
current_position[Z_AXIS] -= 0.025f;
// Improve the point position by searching its center in a current plane.
int8_t n_errors = 3;
for (int8_t iter = 0; iter < 8; ) {
@ -1918,18 +1724,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
// of the sensor points, the y position cannot be measured
// by a cross center method.
// Use a zig-zag search for the first row of the points.
InductionSensorPointStatusType status = improve_bed_induction_sensor_point3(verbosity_level);
if (status == INDUCTION_SENSOR_POINT_FAILED) {
found = false;
} else {
found = true;
if (iter == 7 && INDUCTION_SENSOR_POINT_FAR)
// Remember, which side of the bed is shifted too far in the minus y direction.
result |=
(mesh_point == 1) ? BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR :
((mesh_point == 0) ? BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR :
BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR);
}
found = improve_bed_induction_sensor_point3(verbosity_level);
} else {
switch (method) {
case 0: found = improve_bed_induction_sensor_point(); break;
@ -1946,6 +1741,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
++ iter;
} else if (n_errors -- == 0) {
// Give up.
result = BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
goto canceled;
} else {
// Try to move the Z axis down a bit to increase a chance of the sensor to trigger.
@ -2001,11 +1797,21 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
}
{
result = calculate_machine_skew_and_offset_LS(pts, 9, BedSkewOffsetDetectionResultType(result), bed_ref_points, vec_x, vec_y, cntr, verbosity_level);
// First fill in the too_far_mask from the measured points.
for (uint8_t mesh_point = 0; mesh_point < 3; ++ mesh_point)
if (pts[mesh_point * 2 + 1] < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH)
too_far_mask |= 1 << mesh_point;
result = calculate_machine_skew_and_offset_LS(pts, 9, bed_ref_points, vec_x, vec_y, cntr, verbosity_level);
if (result < 0) {
SERIAL_ECHOLNPGM("Calculation of the machine skew and offset failed.");
goto canceled;
}
// In case of success, update the too_far_mask from the calculated points.
for (uint8_t mesh_point = 0; mesh_point < 3; ++ mesh_point) {
float y = vec_x[1] * pgm_read_float(bed_ref_points+mesh_point*2) + vec_y[1] * pgm_read_float(bed_ref_points+mesh_point*2+1) + cntr[1];
if (y < Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH)
too_far_mask |= 1 << mesh_point;
}
}
world2machine_update(vec_x, vec_y, cntr);
@ -2150,7 +1956,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
enable_z_endstop(endstop_z_enabled);
// Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout();
return BedSkewOffsetDetectionResultType(result);
return result;
canceled:
// Don't let the manage_inactivity() function remove power from the motors.
@ -2162,7 +1968,7 @@ canceled:
reset_bed_offset_and_skew();
enable_endstops(endstops_enabled);
enable_z_endstop(endstop_z_enabled);
return (result == BED_SKEW_OFFSET_DETECTION_PERFECT) ? BED_SKEW_OFFSET_DETECTION_FAILED : BedSkewOffsetDetectionResultType(- int8_t(result));
return result;
}
bool scan_bed_induction_points(int8_t verbosity_level)

View file

@ -145,21 +145,17 @@ extern bool find_bed_induction_sensor_point_xy();
// Negative: failed
enum BedSkewOffsetDetectionResultType {
// Detection failed, some point was not found.
BED_SKEW_OFFSET_DETECTION_FAILED = -1,
BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND = -1,
BED_SKEW_OFFSET_DETECTION_FITTING_FAILED = -2,
// Detection finished with success.
BED_SKEW_OFFSET_DETECTION_PERFECT = 0,
BED_SKEW_OFFSET_DETECTION_SKEW_MILD = 1,
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2,
// Detection finished with success, but it is recommended to fix the printer mechanically.
BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR = 4,
BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR = 8,
BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR = BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR | BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR,
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2
};
extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level);
extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level);
extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask);
extern void reset_bed_offset_and_skew();
extern bool is_bed_z_jitter_data_valid();

View file

@ -1353,34 +1353,8 @@ void lcd_display_message_fullscreen_P(const char *msg)
}
}
void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result)
static void lcd_show_fullscreen_message_and_wait_P(const char *msg)
{
const char *msg = NULL;
switch (result) {
case BED_SKEW_OFFSET_DETECTION_FAILED:
default:
msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED;
break;
case BED_SKEW_OFFSET_DETECTION_PERFECT:
msg = MSG_BED_SKEW_OFFSET_DETECTION_PERFECT;
break;
case BED_SKEW_OFFSET_DETECTION_SKEW_MILD:
msg = MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD;
break;
case BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME:
msg = MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME;
break;
case BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR:
msg = MSG_BED_SKEW_OFFSET_DETECTION_FRONT_LEFT_FAR;
break;
case BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR:
msg = MSG_BED_SKEW_OFFSET_DETECTION_FRONT_RIGHT_FAR;
break;
case BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR:
msg = MSG_BED_SKEW_OFFSET_DETECTION_FRONT_BOTH_FAR;
break;
}
lcd_display_message_fullscreen_P(msg);
// Until confirmed by a button click.
@ -1395,6 +1369,58 @@ void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result)
}
}
void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask)
{
const char *msg = NULL;
if (result == BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND) {
lcd_show_fullscreen_message_and_wait_P(MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND);
} else if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED) {
if (point_too_far_mask == 0)
msg = MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
else if (point_too_far_mask == 2 || point_too_far_mask == 7)
// Only the center point or all the three front points.
msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_BOTH_FAR;
else if (point_too_far_mask & 1 == 0)
// The right and maybe the center point out of reach.
msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_RIGHT_FAR;
else
// The left and maybe the center point out of reach.
msg = MSG_BED_SKEW_OFFSET_DETECTION_FAILED_FRONT_LEFT_FAR;
lcd_show_fullscreen_message_and_wait_P(msg);
} else {
if (point_too_far_mask != 0) {
if (point_too_far_mask == 2 || point_too_far_mask == 7)
// Only the center point or all the three front points.
msg = MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_BOTH_FAR;
else if (point_too_far_mask & 1 == 0)
// The right and maybe the center point out of reach.
msg = MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_RIGHT_FAR;
else
// The left and maybe the center point out of reach.
msg = MSG_BED_SKEW_OFFSET_DETECTION_WARNING_FRONT_LEFT_FAR;
lcd_show_fullscreen_message_and_wait_P(msg);
}
if (point_too_far_mask == 0 || result > 0) {
switch (result) {
default:
// should not happen
msg = MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
break;
case BED_SKEW_OFFSET_DETECTION_PERFECT:
msg = MSG_BED_SKEW_OFFSET_DETECTION_PERFECT;
break;
case BED_SKEW_OFFSET_DETECTION_SKEW_MILD:
msg = MSG_BED_SKEW_OFFSET_DETECTION_SKEW_MILD;
break;
case BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME:
msg = MSG_BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME;
break;
}
lcd_show_fullscreen_message_and_wait_P(msg);
}
}
}
static void lcd_show_end_stops() {
lcd.setCursor(0, 0);
lcd_printPGM((PSTR("End stops diag")));

View file

@ -44,7 +44,7 @@
// the user confirm that it has been done.
extern bool lcd_calibrate_z_end_stop_manual();
// Show the result of the calibration process on the LCD screen.
extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result);
extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask);
extern void lcd_diag_show_end_stops();