@ -65,8 +65,7 @@
unified_bed_leveling : : g29_phase_value ,
unified_bed_leveling : : g29_repetition_cnt ,
unified_bed_leveling : : g29_storage_slot = 0 ,
unified_bed_leveling : : g29_map_type ,
unified_bed_leveling : : g29_grid_size ;
unified_bed_leveling : : g29_map_type ;
bool unified_bed_leveling : : g29_c_flag ,
unified_bed_leveling : : g29_x_flag ,
unified_bed_leveling : : g29_y_flag ;
@ -75,6 +74,10 @@
unified_bed_leveling : : g29_card_thickness = 0.0 ,
unified_bed_leveling : : g29_constant = 0.0 ;
# if HAS_BED_PROBE
int unified_bed_leveling : : g29_grid_size ;
# endif
/**
* G29 : Unified Bed Leveling by Roxy
*
@ -310,6 +313,8 @@
return ;
}
if ( g29_parameter_parsing ( ) ) return ; // abort if parsing the simple parameters causes a problem,
// Check for commands that require the printer to be homed
if ( axis_unhomed_error ( ) ) {
const int8_t p_val = parser . intval ( ' P ' , - 1 ) ;
@ -317,8 +322,6 @@
gcode . home_all_axes ( ) ;
}
if ( g29_parameter_parsing ( ) ) return ; // abort if parsing the simple parameters causes a problem,
// Invalidate Mesh Points. This command is a little bit asymmetrical because
// it directly specifies the repetition count and does not use the 'R' parameter.
if ( parser . seen ( ' I ' ) ) {
@ -381,40 +384,44 @@
}
}
if ( parser . seen ( ' J ' ) ) {
if ( g29_grid_size ) { // if not 0 it is a normal n x n grid being probed
save_ubl_active_state_and_disable ( ) ;
tilt_mesh_based_on_probed_grid ( parser . seen ( ' T ' ) ) ;
restore_ubl_active_state_and_leave ( ) ;
}
else { // grid_size == 0 : A 3-Point leveling has been requested
float z3 , z2 , z1 = probe_pt ( LOGICAL_X_POSITION ( UBL_PROBE_PT_1_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_1_Y ) , false , g29_verbose_level ) ;
if ( ! isnan ( z1 ) ) {
z2 = probe_pt ( LOGICAL_X_POSITION ( UBL_PROBE_PT_2_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_2_Y ) , false , g29_verbose_level ) ;
if ( ! isnan ( z2 ) )
z3 = probe_pt ( LOGICAL_X_POSITION ( UBL_PROBE_PT_3_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_3_Y ) , true , g29_verbose_level ) ;
}
# if HAS_BED_PROBE
if ( isnan ( z1 ) | | isnan ( z2 ) | | isnan ( z3 ) ) { // probe_pt will return NAN if unreachable
SERIAL_ERROR_START ( ) ;
SERIAL_ERRORLNPGM ( " Attempt to probe off the bed. " ) ;
goto LEAVE ;
if ( parser . seen ( ' J ' ) ) {
if ( g29_grid_size ) { // if not 0 it is a normal n x n grid being probed
save_ubl_active_state_and_disable ( ) ;
tilt_mesh_based_on_probed_grid ( parser . seen ( ' T ' ) ) ;
restore_ubl_active_state_and_leave ( ) ;
}
else { // grid_size == 0 : A 3-Point leveling has been requested
float z3 , z2 , z1 = probe_pt ( LOGICAL_X_POSITION ( UBL_PROBE_PT_1_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_1_Y ) , false , g29_verbose_level ) ;
if ( ! isnan ( z1 ) ) {
z2 = probe_pt ( LOGICAL_X_POSITION ( UBL_PROBE_PT_2_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_2_Y ) , false , g29_verbose_level ) ;
if ( ! isnan ( z2 ) )
z3 = probe_pt ( LOGICAL_X_POSITION ( UBL_PROBE_PT_3_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_3_Y ) , true , g29_verbose_level ) ;
}
// Adjust z1, z2, z3 by the Mesh Height at these points. Just because they're non-zero
// doesn't mean the Mesh is tilted! (Compensate each probe point by what the Mesh says
// its height is.)
if ( isnan ( z1 ) | | isnan ( z2 ) | | isnan ( z3 ) ) { // probe_pt will return NAN if unreachable
SERIAL_ERROR_START ( ) ;
SERIAL_ERRORLNPGM ( " Attempt to probe off the bed. " ) ;
goto LEAVE ;
}
save_ubl_active_state_and_disable ( ) ;
z1 - = get_z_correction ( LOGICAL_X_POSITION ( UBL_PROBE_PT_1_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_1_Y ) ) /* + zprobe_zoffset */ ;
z2 - = get_z_correction ( LOGICAL_X_POSITION ( UBL_PROBE_PT_2_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_2_Y ) ) /* + zprobe_zoffset */ ;
z3 - = get_z_correction ( LOGICAL_X_POSITION ( UBL_PROBE_PT_3_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_3_Y ) ) /* + zprobe_zoffset */ ;
// Adjust z1, z2, z3 by the Mesh Height at these points. Just because they're non-zero
// doesn't mean the Mesh is tilted! (Compensate each probe point by what the Mesh says
// its height is.)
do_blocking_move_to_xy ( 0.5 * ( UBL_MESH_MAX_X - ( UBL_MESH_MIN_X ) ) , 0.5 * ( UBL_MESH_MAX_Y - ( UBL_MESH_MIN_Y ) ) ) ;
tilt_mesh_based_on_3pts ( z1 , z2 , z3 ) ;
restore_ubl_active_state_and_leave ( ) ;
save_ubl_active_state_and_disable ( ) ;
z1 - = get_z_correction ( LOGICAL_X_POSITION ( UBL_PROBE_PT_1_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_1_Y ) ) /* + zprobe_zoffset */ ;
z2 - = get_z_correction ( LOGICAL_X_POSITION ( UBL_PROBE_PT_2_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_2_Y ) ) /* + zprobe_zoffset */ ;
z3 - = get_z_correction ( LOGICAL_X_POSITION ( UBL_PROBE_PT_3_X ) , LOGICAL_Y_POSITION ( UBL_PROBE_PT_3_Y ) ) /* + zprobe_zoffset */ ;
do_blocking_move_to_xy ( 0.5 * ( UBL_MESH_MAX_X - ( UBL_MESH_MIN_X ) ) , 0.5 * ( UBL_MESH_MAX_Y - ( UBL_MESH_MIN_Y ) ) ) ;
tilt_mesh_based_on_3pts ( z1 , z2 , z3 ) ;
restore_ubl_active_state_and_leave ( ) ;
}
}
}
# endif // HAS_BED_PROBE
if ( parser . seen ( ' P ' ) ) {
if ( WITHIN ( g29_phase_value , 0 , 1 ) & & state . storage_slot = = - 1 ) {
@ -431,23 +438,27 @@
SERIAL_PROTOCOLLNPGM ( " Mesh zeroed. " ) ;
break ;
case 1 :
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if ( ! parser . seen ( ' C ' ) ) {
invalidate ( ) ;
SERIAL_PROTOCOLLNPGM ( " Mesh invalidated. Probing mesh. " ) ;
}
if ( g29_verbose_level > 1 ) {
SERIAL_PROTOCOLPAIR ( " Probing Mesh Points Closest to ( " , g29_x_pos ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL ( g29_y_pos ) ;
SERIAL_PROTOCOLLNPGM ( " ). \n " ) ;
}
probe_entire_mesh ( g29_x_pos + X_PROBE_OFFSET_FROM_EXTRUDER , g29_y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER ,
parser . seen ( ' T ' ) , parser . seen ( ' E ' ) , parser . seen ( ' U ' ) ) ;
break ;
# if HAS_BED_PROBE
case 1 :
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if ( ! parser . seen ( ' C ' ) ) {
invalidate ( ) ;
SERIAL_PROTOCOLLNPGM ( " Mesh invalidated. Probing mesh. " ) ;
}
if ( g29_verbose_level > 1 ) {
SERIAL_PROTOCOLPAIR ( " Probing Mesh Points Closest to ( " , g29_x_pos ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL ( g29_y_pos ) ;
SERIAL_PROTOCOLLNPGM ( " ). \n " ) ;
}
probe_entire_mesh ( g29_x_pos + X_PROBE_OFFSET_FROM_EXTRUDER , g29_y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER ,
parser . seen ( ' T ' ) , parser . seen ( ' E ' ) , parser . seen ( ' U ' ) ) ;
break ;
# endif
case 2 : {
# if ENABLED(NEWPANEL)
@ -776,161 +787,166 @@
z_values [ x ] [ y ] + = g29_constant ;
}
/**
* Probe all invalidated locations of the mesh that can be reached by the probe .
* This attempts to fill in locations closest to the nozzle ' s start location first .
*/
void unified_bed_leveling : : probe_entire_mesh ( const float & lx , const float & ly , const bool do_ubl_mesh_map , const bool stow_probe , bool close_or_far ) {
mesh_index_pair location ;
has_control_of_lcd_panel = true ;
save_ubl_active_state_and_disable ( ) ; // we don't do bed level correction because we want the raw data when we probe
DEPLOY_PROBE ( ) ;
uint16_t max_iterations = GRID_MAX_POINTS ;
# if HAS_BED_PROBE
do {
# if ENABLED(NEWPANEL)
if ( ubl_lcd_clicked ( ) ) {
SERIAL_PROTOCOLLNPGM ( " \n Mesh only partially populated. \n " ) ;
lcd_quick_feedback ( ) ;
STOW_PROBE ( ) ;
while ( ubl_lcd_clicked ( ) ) idle ( ) ;
has_control_of_lcd_panel = false ;
restore_ubl_active_state_and_leave ( ) ;
safe_delay ( 50 ) ; // Debounce the Encoder wheel
return ;
}
# endif
location = find_closest_mesh_point_of_type ( INVALID , lx , ly , USE_PROBE_AS_REFERENCE , NULL , close_or_far ) ;
if ( location . x_index > = 0 ) { // mesh point found and is reachable by probe
const float rawx = mesh_index_to_xpos ( location . x_index ) ,
rawy = mesh_index_to_ypos ( location . y_index ) ;
/**
* Probe all invalidated locations of the mesh that can be reached by the probe .
* This attempts to fill in locations closest to the nozzle ' s start location first .
*/
void unified_bed_leveling : : probe_entire_mesh ( const float & lx , const float & ly , const bool do_ubl_mesh_map , const bool stow_probe , bool close_or_far ) {
mesh_index_pair location ;
const float measured_z = probe_pt ( LOGICAL_X_POSITION ( rawx ) , LOGICAL_Y_POSITION ( rawy ) , stow_probe , g29_verbose_level ) ; // TODO: Needs error handling
z_values [ location . x_index ] [ location . y_index ] = measured_z ;
}
has_control_of_lcd_panel = true ;
save_ubl_active_state_and_disable ( ) ; // we don't do bed level correction because we want the raw data when we probe
DEPLOY_PROBE ( ) ;
if ( do_ubl_mesh_map ) display_map ( g29_map_type ) ;
uint16_t max_iterations = GRID_MAX_POINTS ;
} while ( location . x_index > = 0 & & - - max_iterations ) ;
do {
# if ENABLED(NEWPANEL)
if ( ubl_lcd_clicked ( ) ) {
SERIAL_PROTOCOLLNPGM ( " \n Mesh only partially populated. \n " ) ;
lcd_quick_feedback ( ) ;
STOW_PROBE ( ) ;
while ( ubl_lcd_clicked ( ) ) idle ( ) ;
has_control_of_lcd_panel = false ;
restore_ubl_active_state_and_leave ( ) ;
safe_delay ( 50 ) ; // Debounce the Encoder wheel
return ;
}
# endif
STOW_PROBE ( ) ;
restore_ubl_active_state_and_leave ( ) ;
location = find_closest_mesh_point_of_type ( INVALID , lx , ly , USE_PROBE_AS_REFERENCE , NULL , close_or_far ) ;
do_blocking_move_to_xy (
constrain ( lx - ( X_PROBE_OFFSET_FROM_EXTRUDER ) , UBL_MESH_MIN_X , UBL_MESH_MAX_X ) ,
constrain ( ly - ( Y_PROBE_OFFSET_FROM_EXTRUDER ) , UBL_MESH_MIN_Y , UBL_MESH_MAX_Y )
) ;
}
if ( location . x_index > = 0 ) { // mesh point found and is reachable by probe
const float rawx = mesh_index_to_xpos ( location . x_index ) ,
rawy = mesh_index_to_ypos ( location . y_index ) ;
void unified_bed_leveling : : tilt_mesh_based_on_3pts ( const float & z1 , const float & z2 , const float & z3 ) {
matrix_3x3 rotation ;
vector_3 v1 = vector_3 ( ( UBL_PROBE_PT_1_X - UBL_PROBE_PT_2_X ) ,
( UBL_PROBE_PT_1_Y - UBL_PROBE_PT_2_Y ) ,
( z1 - z2 ) ) ,
const float measured_z = probe_pt ( LOGICAL_X_POSITION ( rawx ) , LOGICAL_Y_POSITION ( rawy ) , stow_probe , g29_verbose_level ) ; // TODO: Needs error handling
z_values [ location . x_index ] [ location . y_index ] = measured_z ;
}
v2 = vector_3 ( ( UBL_PROBE_PT_3_X - UBL_PROBE_PT_2_X ) ,
( UBL_PROBE_PT_3_Y - UBL_PROBE_PT_2_Y ) ,
( z3 - z2 ) ) ,
if ( do_ubl_mesh_map ) display_map ( g29_map_type ) ;
normal = vector_3 : : cross ( v1 , v2 ) ;
} while ( location . x_index > = 0 & & - - max_iterations ) ;
normal = normal . get_normal ( ) ;
STOW_PROBE ( ) ;
restore_ubl_active_state_and_leave ( ) ;
/**
* This vector is normal to the tilted plane .
* However , we don ' t know its direction . We need it to point up . So if
* Z is negative , we need to invert the sign of all components of the vector
*/
if ( normal . z < 0.0 ) {
normal . x = - normal . x ;
normal . y = - normal . y ;
normal . z = - normal . z ;
do_blocking_move_to_xy (
constrain ( lx - ( X_PROBE_OFFSET_FROM_EXTRUDER ) , UBL_MESH_MIN_X , UBL_MESH_MAX_X ) ,
constrain ( ly - ( Y_PROBE_OFFSET_FROM_EXTRUDER ) , UBL_MESH_MIN_Y , UBL_MESH_MAX_Y )
) ;
}
rotation = matrix_3x3 : : create_look_at ( vector_3 ( normal . x , normal . y , 1 ) ) ;
if ( g29_verbose_level > 2 ) {
SERIAL_ECHOPGM ( " bed plane normal = [ " ) ;
SERIAL_PROTOCOL_F ( normal . x , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . y , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . z , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
rotation . debug ( PSTR ( " rotation matrix: " ) ) ;
}
void unified_bed_leveling : : tilt_mesh_based_on_3pts ( const float & z1 , const float & z2 , const float & z3 ) {
matrix_3x3 rotation ;
vector_3 v1 = vector_3 ( ( UBL_PROBE_PT_1_X - UBL_PROBE_PT_2_X ) ,
( UBL_PROBE_PT_1_Y - UBL_PROBE_PT_2_Y ) ,
( z1 - z2 ) ) ,
v2 = vector_3 ( ( UBL_PROBE_PT_3_X - UBL_PROBE_PT_2_X ) ,
( UBL_PROBE_PT_3_Y - UBL_PROBE_PT_2_Y ) ,
( z3 - z2 ) ) ,
normal = vector_3 : : cross ( v1 , v2 ) ;
normal = normal . get_normal ( ) ;
/**
* This vector is normal to the tilted plane .
* However , we don ' t know its direction . We need it to point up . So if
* Z is negative , we need to invert the sign of all components of the vector
*/
if ( normal . z < 0.0 ) {
normal . x = - normal . x ;
normal . y = - normal . y ;
normal . z = - normal . z ;
}
//
// All of 3 of these points should give us the same d constant
//
rotation = matrix_3x3 : : create_look_at ( vector_3 ( normal . x , normal . y , 1 ) ) ;
float t = normal . x * ( UBL_PROBE_PT_1_X ) + normal . y * ( UBL_PROBE_PT_1_Y ) ,
d = t + normal . z * z1 ;
if ( g29_verbose_level > 2 ) {
SERIAL_ECHOPGM ( " bed plane normal = [ " ) ;
SERIAL_PROTOCOL_F ( normal . x , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . y , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . z , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
rotation . debug ( PSTR ( " rotation matrix: " ) ) ;
}
if ( g29_verbose_level > 2 ) {
SERIAL_ECHOPGM ( " D constant: " ) ;
SERIAL_PROTOCOL_F ( d , 7 ) ;
SERIAL_ECHOLNPGM ( " " ) ;
}
//
// All of 3 of these points should give us the same d constant
//
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " d from 1st point: " ) ;
SERIAL_ECHO_F ( d , 6 ) ;
SERIAL_EOL ( ) ;
t = normal . x * ( UBL_PROBE_PT_2_X ) + normal . y * ( UBL_PROBE_PT_2_Y ) ;
d = t + normal . z * z2 ;
SERIAL_ECHOPGM ( " d from 2nd point: " ) ;
SERIAL_ECHO_F ( d , 6 ) ;
SERIAL_EOL ( ) ;
t = normal . x * ( UBL_PROBE_PT_3_X ) + normal . y * ( UBL_PROBE_PT_3_Y ) ;
d = t + normal . z * z3 ;
SERIAL_ECHOPGM ( " d from 3rd point: " ) ;
SERIAL_ECHO_F ( d , 6 ) ;
SERIAL_EOL ( ) ;
float t = normal . x * ( UBL_PROBE_PT_1_X ) + normal . y * ( UBL_PROBE_PT_1_Y ) ,
d = t + normal . z * z1 ;
if ( g29_verbose_level > 2 ) {
SERIAL_ECHOPGM ( " D constant: " ) ;
SERIAL_PROTOCOL_F ( d , 7 ) ;
SERIAL_ECHOLNPGM ( " " ) ;
}
# endif
for ( uint8_t i = 0 ; i < GRID_MAX_POINTS_X ; i + + ) {
for ( uint8_t j = 0 ; j < GRID_MAX_POINTS_Y ; j + + ) {
float x_tmp = mesh_index_to_xpos ( i ) ,
y_tmp = mesh_index_to_ypos ( j ) ,
z_tmp = z_values [ i ] [ j ] ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " before rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOPGM ( " ] ---> " ) ;
safe_delay ( 20 ) ;
}
# endif
apply_rotation_xyz ( rotation , x_tmp , y_tmp , z_tmp ) ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " after rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
safe_delay ( 55 ) ;
}
# endif
z_values [ i ] [ j ] + = z_tmp - d ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " d from 1st point: " ) ;
SERIAL_ECHO_F ( d , 6 ) ;
SERIAL_EOL ( ) ;
t = normal . x * ( UBL_PROBE_PT_2_X ) + normal . y * ( UBL_PROBE_PT_2_Y ) ;
d = t + normal . z * z2 ;
SERIAL_ECHOPGM ( " d from 2nd point: " ) ;
SERIAL_ECHO_F ( d , 6 ) ;
SERIAL_EOL ( ) ;
t = normal . x * ( UBL_PROBE_PT_3_X ) + normal . y * ( UBL_PROBE_PT_3_Y ) ;
d = t + normal . z * z3 ;
SERIAL_ECHOPGM ( " d from 3rd point: " ) ;
SERIAL_ECHO_F ( d , 6 ) ;
SERIAL_EOL ( ) ;
}
# endif
for ( uint8_t i = 0 ; i < GRID_MAX_POINTS_X ; i + + ) {
for ( uint8_t j = 0 ; j < GRID_MAX_POINTS_Y ; j + + ) {
float x_tmp = mesh_index_to_xpos ( i ) ,
y_tmp = mesh_index_to_ypos ( j ) ,
z_tmp = z_values [ i ] [ j ] ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " before rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOPGM ( " ] ---> " ) ;
safe_delay ( 20 ) ;
}
# endif
apply_rotation_xyz ( rotation , x_tmp , y_tmp , z_tmp ) ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " after rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
safe_delay ( 55 ) ;
}
# endif
z_values [ i ] [ j ] + = z_tmp - d ;
}
}
}
}
# endif // HAS_BED_PROBE
# if ENABLED(NEWPANEL)
float unified_bed_leveling : : measure_point_with_encoder ( ) {
while ( ubl_lcd_clicked ( ) ) delay ( 50 ) ; // wait for user to release encoder wheel
@ -1080,7 +1096,8 @@
do_blocking_move_to_z ( Z_CLEARANCE_DEPLOY_PROBE ) ;
do_blocking_move_to_xy ( lx , ly ) ;
}
# endif
# endif // NEWPANEL
bool unified_bed_leveling : : g29_parameter_parsing ( ) {
bool err_flag = false ;
@ -1114,19 +1131,34 @@
}
if ( parser . seen ( ' P ' ) ) {
g29_phase_value = parser . value_int ( ) ;
if ( ! WITHIN ( g29_phase_value , 0 , 6 ) ) {
SERIAL_PROTOCOLLNPGM ( " ?(P)hase value invalid (0-6). \n " ) ;
err_flag = true ;
}
const int pv = parser . value_int ( ) ;
# if !HAS_BED_PROBE
if ( pv = = 1 ) {
SERIAL_PROTOCOLLNPGM ( " G29 P1 requires a probe. \n " ) ;
err_flag = true ;
}
else
# endif
{
g29_phase_value = pv ;
if ( ! WITHIN ( g29_phase_value , 0 , 6 ) ) {
SERIAL_PROTOCOLLNPGM ( " ?(P)hase value invalid (0-6). \n " ) ;
err_flag = true ;
}
}
}
if ( parser . seen ( ' J ' ) ) {
g29_grid_size = parser . has_value ( ) ? parser . value_int ( ) : 0 ;
if ( g29_grid_size & & ! WITHIN ( g29_grid_size , 2 , 9 ) ) {
SERIAL_PROTOCOLLNPGM ( " ?Invalid grid size (J) specified (2-9). \n " ) ;
# if HAS_BED_PROBE
g29_grid_size = parser . has_value ( ) ? parser . value_int ( ) : 0 ;
if ( g29_grid_size & & ! WITHIN ( g29_grid_size , 2 , 9 ) ) {
SERIAL_PROTOCOLLNPGM ( " ?Invalid grid size (J) specified (2-9). \n " ) ;
err_flag = true ;
}
# else
SERIAL_PROTOCOLLNPGM ( " G29 J action requires a probe. \n " ) ;
err_flag = true ;
}
# endif
}
if ( g29_x_flag ! = g29_y_flag ) {
@ -1624,128 +1656,66 @@
}
}
void unified_bed_leveling : : tilt_mesh_based_on_probed_grid ( const bool do_ubl_mesh_map ) {
constexpr int16_t x_min = max ( MIN_PROBE_X , UBL_MESH_MIN_X ) ,
x_max = min ( MAX_PROBE_X , UBL_MESH_MAX_X ) ,
y_min = max ( MIN_PROBE_Y , UBL_MESH_MIN_Y ) ,
y_max = min ( MAX_PROBE_Y , UBL_MESH_MAX_Y ) ;
const float dx = float ( x_max - x_min ) / ( g29_grid_size - 1.0 ) ,
dy = float ( y_max - y_min ) / ( g29_grid_size - 1.0 ) ;
struct linear_fit_data lsf_results ;
incremental_LSF_reset ( & lsf_results ) ;
bool zig_zag = false ;
for ( uint8_t ix = 0 ; ix < g29_grid_size ; ix + + ) {
const float x = float ( x_min ) + ix * dx ;
for ( int8_t iy = 0 ; iy < g29_grid_size ; iy + + ) {
const float y = float ( y_min ) + dy * ( zig_zag ? g29_grid_size - 1 - iy : iy ) ;
float measured_z = probe_pt ( LOGICAL_X_POSITION ( x ) , LOGICAL_Y_POSITION ( y ) , parser . seen ( ' E ' ) , g29_verbose_level ) ; // TODO: Needs error handling
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_CHAR ( ' ( ' ) ;
SERIAL_PROTOCOL_F ( x , 7 ) ;
SERIAL_CHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y , 7 ) ;
SERIAL_ECHOPGM ( " ) logical: " ) ;
SERIAL_CHAR ( ' ( ' ) ;
SERIAL_PROTOCOL_F ( LOGICAL_X_POSITION ( x ) , 7 ) ;
SERIAL_CHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( LOGICAL_X_POSITION ( y ) , 7 ) ;
SERIAL_ECHOPGM ( " ) measured: " ) ;
SERIAL_PROTOCOL_F ( measured_z , 7 ) ;
SERIAL_ECHOPGM ( " correction: " ) ;
SERIAL_PROTOCOL_F ( get_z_correction ( LOGICAL_X_POSITION ( x ) , LOGICAL_Y_POSITION ( y ) ) , 7 ) ;
}
# endif
# if HAS_BED_PROBE
measured_z - = get_z_correction ( LOGICAL_X_POSITION ( x ) , LOGICAL_Y_POSITION ( y ) ) /* + zprobe_zoffset */ ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " final >>>---> " ) ;
SERIAL_PROTOCOL_F ( measured_z , 7 ) ;
SERIAL_EOL ( ) ;
}
# endif
incremental_LSF ( & lsf_results , x , y , measured_z ) ;
}
zig_zag ^ = true ;
}
if ( finish_incremental_LSF ( & lsf_results ) ) {
SERIAL_ECHOPGM ( " Could not complete LSF! " ) ;
return ;
}
void unified_bed_leveling : : tilt_mesh_based_on_probed_grid ( const bool do_ubl_mesh_map ) {
constexpr int16_t x_min = max ( MIN_PROBE_X , UBL_MESH_MIN_X ) ,
x_max = min ( MAX_PROBE_X , UBL_MESH_MAX_X ) ,
y_min = max ( MIN_PROBE_Y , UBL_MESH_MIN_Y ) ,
y_max = min ( MAX_PROBE_Y , UBL_MESH_MAX_Y ) ;
if ( g29_verbose_level > 3 ) {
SERIAL_ECHOPGM ( " LSF Results A= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . A , 7 ) ;
SERIAL_ECHOPGM ( " B= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . B , 7 ) ;
SERIAL_ECHOPGM ( " D= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . D , 7 ) ;
SERIAL_EOL ( ) ;
}
const float dx = float ( x_max - x_min ) / ( g29_grid_size - 1.0 ) ,
dy = float ( y_max - y_min ) / ( g29_grid_size - 1.0 ) ;
vector_3 normal = vector_3 ( lsf_results . A , lsf_results . B , 1.0000 ) . get_normal ( ) ;
struct linear_fit_data lsf_results ;
incremental_LSF_reset ( & lsf_results ) ;
bool zig_zag = false ;
for ( uint8_t ix = 0 ; ix < g29_grid_size ; ix + + ) {
const float x = float ( x_min ) + ix * dx ;
for ( int8_t iy = 0 ; iy < g29_grid_size ; iy + + ) {
const float y = float ( y_min ) + dy * ( zig_zag ? g29_grid_size - 1 - iy : iy ) ;
float measured_z = probe_pt ( LOGICAL_X_POSITION ( x ) , LOGICAL_Y_POSITION ( y ) , parser . seen ( ' E ' ) , g29_verbose_level ) ; // TODO: Needs error handling
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_CHAR ( ' ( ' ) ;
SERIAL_PROTOCOL_F ( x , 7 ) ;
SERIAL_CHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y , 7 ) ;
SERIAL_ECHOPGM ( " ) logical: " ) ;
SERIAL_CHAR ( ' ( ' ) ;
SERIAL_PROTOCOL_F ( LOGICAL_X_POSITION ( x ) , 7 ) ;
SERIAL_CHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( LOGICAL_X_POSITION ( y ) , 7 ) ;
SERIAL_ECHOPGM ( " ) measured: " ) ;
SERIAL_PROTOCOL_F ( measured_z , 7 ) ;
SERIAL_ECHOPGM ( " correction: " ) ;
SERIAL_PROTOCOL_F ( get_z_correction ( LOGICAL_X_POSITION ( x ) , LOGICAL_Y_POSITION ( y ) ) , 7 ) ;
}
# endif
if ( g29_verbose_level > 2 ) {
SERIAL_ECHOPGM ( " bed plane normal = [ " ) ;
SERIAL_PROTOCOL_F ( normal . x , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . y , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . z , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
}
measured_z - = get_z_correction ( LOGICAL_X_POSITION ( x ) , LOGICAL_Y_POSITION ( y ) ) /* + zprobe_zoffset */ ;
matrix_3x3 rotation = matrix_3x3 : : create_look_at ( vector_3 ( lsf_results . A , lsf_results . B , 1 ) ) ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " final >>>---> " ) ;
SERIAL_PROTOCOL_F ( measured_z , 7 ) ;
SERIAL_EOL ( ) ;
}
# endif
for ( uint8_t i = 0 ; i < GRID_MAX_POINTS_X ; i + + ) {
for ( uint8_t j = 0 ; j < GRID_MAX_POINTS_Y ; j + + ) {
float x_tmp = mesh_index_to_xpos ( i ) ,
y_tmp = mesh_index_to_ypos ( j ) ,
z_tmp = z_values [ i ] [ j ] ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " before rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOPGM ( " ] ---> " ) ;
safe_delay ( 20 ) ;
}
# endif
incremental_LSF ( & lsf_results , x , y , measured_z ) ;
}
apply_rotation_xyz ( rotation , x_tmp , y_tmp , z_tmp ) ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " after rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
safe_delay ( 55 ) ;
}
# endif
zig_zag ^ = true ;
}
z_values [ i ] [ j ] + = z_tmp - lsf_results . D ;
if ( finish_incremental_LSF ( & lsf_results ) ) {
SERIAL_ECHOPGM ( " Could not complete LSF! " ) ;
return ;
}
}
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
rotation . debug ( PSTR ( " rotation matrix: " ) ) ;
if ( g29_verbose_level > 3 ) {
SERIAL_ECHOPGM ( " LSF Results A= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . A , 7 ) ;
SERIAL_ECHOPGM ( " B= " ) ;
@ -1753,21 +1723,87 @@
SERIAL_ECHOPGM ( " D= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . D , 7 ) ;
SERIAL_EOL ( ) ;
safe_delay ( 55 ) ;
}
vector_3 normal = vector_3 ( lsf_results . A , lsf_results . B , 1.0000 ) . get_normal ( ) ;
if ( g29_verbose_level > 2 ) {
SERIAL_ECHOPGM ( " bed plane normal = [ " ) ;
SERIAL_PROTOCOL_F ( normal . x , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . y , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . z , 7 ) ;
SERIAL_ECHOPGM ( " ] \n " ) ;
SERIAL_EOL ( ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
}
# endif
if ( do_ubl_mesh_map ) display_map ( g29_map_type ) ;
}
matrix_3x3 rotation = matrix_3x3 : : create_look_at ( vector_3 ( lsf_results . A , lsf_results . B , 1 ) ) ;
for ( uint8_t i = 0 ; i < GRID_MAX_POINTS_X ; i + + ) {
for ( uint8_t j = 0 ; j < GRID_MAX_POINTS_Y ; j + + ) {
float x_tmp = mesh_index_to_xpos ( i ) ,
y_tmp = mesh_index_to_ypos ( j ) ,
z_tmp = z_values [ i ] [ j ] ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " before rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOPGM ( " ] ---> " ) ;
safe_delay ( 20 ) ;
}
# endif
apply_rotation_xyz ( rotation , x_tmp , y_tmp , z_tmp ) ;
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " after rotation = [ " ) ;
SERIAL_PROTOCOL_F ( x_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( y_tmp , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( z_tmp , 7 ) ;
SERIAL_ECHOLNPGM ( " ] " ) ;
safe_delay ( 55 ) ;
}
# endif
z_values [ i ] [ j ] + = z_tmp - lsf_results . D ;
}
}
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
rotation . debug ( PSTR ( " rotation matrix: " ) ) ;
SERIAL_ECHOPGM ( " LSF Results A= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . A , 7 ) ;
SERIAL_ECHOPGM ( " B= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . B , 7 ) ;
SERIAL_ECHOPGM ( " D= " ) ;
SERIAL_PROTOCOL_F ( lsf_results . D , 7 ) ;
SERIAL_EOL ( ) ;
safe_delay ( 55 ) ;
SERIAL_ECHOPGM ( " bed plane normal = [ " ) ;
SERIAL_PROTOCOL_F ( normal . x , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . y , 7 ) ;
SERIAL_PROTOCOLCHAR ( ' , ' ) ;
SERIAL_PROTOCOL_F ( normal . z , 7 ) ;
SERIAL_ECHOPGM ( " ] \n " ) ;
SERIAL_EOL ( ) ;
}
# endif
if ( do_ubl_mesh_map ) display_map ( g29_map_type ) ;
}
# endif // HAS_BED_PROBE
# if ENABLED(UBL_G29_P31)
void unified_bed_leveling : : smart_fill_wlsf ( const float & weight_factor ) {