@ -2136,7 +2136,9 @@ static void clean_up_after_endstop_or_probe_move() {
# if ABL_PLANAR
planner . bed_level_matrix . set_to_identity ( ) ;
# elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
memset ( bed_level_grid , 0 , sizeof ( bed_level_grid ) ) ;
for ( uint8_t x = 0 ; x < ABL_GRID_POINTS_X ; x + + )
for ( uint8_t y = 0 ; y < ABL_GRID_POINTS_Y ; y + + )
bed_level_grid [ x ] [ y ] = 1000.0 ;
# endif
}
@ -2148,44 +2150,125 @@ static void clean_up_after_endstop_or_probe_move() {
* Extrapolate a single point from its neighbors
*/
static void extrapolate_one_point ( uint8_t x , uint8_t y , int8_t xdir , int8_t ydir ) {
if ( bed_level_grid [ x ] [ y ] ) return ; // Don't overwrite good values.
float a = 2 * bed_level_grid [ x + xdir ] [ y ] - bed_level_grid [ x + xdir * 2 ] [ y ] , // Left to right.
b = 2 * bed_level_grid [ x ] [ y + ydir ] - bed_level_grid [ x ] [ y + ydir * 2 ] , // Front to back.
c = 2 * bed_level_grid [ x + xdir ] [ y + ydir ] - bed_level_grid [ x + xdir * 2 ] [ y + ydir * 2 ] ; // Diagonal.
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) {
SERIAL_ECHOPGM ( " Extrapolate [ " ) ;
if ( x < 10 ) SERIAL_CHAR ( ' ' ) ;
SERIAL_ECHO ( ( int ) x ) ;
SERIAL_CHAR ( xdir ? ( xdir > 0 ? ' + ' : ' - ' ) : ' ' ) ;
SERIAL_CHAR ( ' ' ) ;
if ( y < 10 ) SERIAL_CHAR ( ' ' ) ;
SERIAL_ECHO ( ( int ) y ) ;
SERIAL_CHAR ( ydir ? ( ydir > 0 ? ' + ' : ' - ' ) : ' ' ) ;
SERIAL_CHAR ( ' ] ' ) ;
}
# endif
if ( bed_level_grid [ x ] [ y ] < 999.0 ) {
# if ENABLED(DEBUG_LEVELING_FEATURE)
if ( DEBUGGING ( LEVELING ) ) SERIAL_ECHOLNPGM ( " (done) " ) ;
# endif
return ; // Don't overwrite good values.
}
// Get X neighbors, Y neighbors, and XY neighbors
float a1 = bed_level_grid [ x + xdir ] [ y ] , a2 = bed_level_grid [ x + xdir * 2 ] [ y ] ,
b1 = bed_level_grid [ x ] [ y + ydir ] , b2 = bed_level_grid [ x ] [ y + ydir * 2 ] ,
c1 = bed_level_grid [ x + xdir ] [ y + ydir ] , c2 = bed_level_grid [ x + xdir * 2 ] [ y + ydir * 2 ] ;
// Treat far unprobed points as zero, near as equal to far
if ( a2 > 999.0 ) a2 = 0.0 ; if ( a1 > 999.0 ) a1 = a2 ;
if ( b2 > 999.0 ) b2 = 0.0 ; if ( b1 > 999.0 ) b1 = b2 ;
if ( c2 > 999.0 ) c2 = 0.0 ; if ( c1 > 999.0 ) c1 = c2 ;
float a = 2 * a1 - a2 , b = 2 * b1 - b2 , c = 2 * c1 - c2 ;
// Take the average intstead of the median
bed_level_grid [ x ] [ y ] = ( a + b + c ) / 3.0 ;
// Median is robust (ignores outliers).
bed_level_grid [ x ] [ y ] = ( a < b ) ? ( ( b < c ) ? b : ( c < a ) ? a : c )
: ( ( c < b ) ? b : ( a < c ) ? a : c ) ;
// bed_level_grid[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c)
// : ((c < b) ? b : (a < c ) ? a : c );
}
# define EXTRAPOLATE_FROM_EDGE
# if ENABLED(EXTRAPOLATE_FROM_EDGE)
# if ABL_GRID_POINTS_X < ABL_GRID_POINTS_Y
# define HALF_IN_X
# elif ABL_GRID_POINTS_Y < ABL_GRID_POINTS_X
# define HALF_IN_Y
# endif
# endif
/**
* Fill in the unprobed points ( corners of circular print surface )
* using linear extrapolation , away from the center .
*/
static void extrapolate_unprobed_bed_level ( ) {
int half_x = ( ABL_GRID_POINTS_X - 1 ) / 2 ,
half_y = ( ABL_GRID_POINTS_Y - 1 ) / 2 ;
for ( uint8_t y = 0 ; y < = half_y ; y + + ) {
for ( uint8_t x = 0 ; x < = half_x ; x + + ) {
if ( x + y < 3 ) continue ;
extrapolate_one_point ( half_x - x , half_y - y , x > 1 ? + 1 : 0 , y > 1 ? + 1 : 0 ) ;
extrapolate_one_point ( half_x + x , half_y - y , x > 1 ? - 1 : 0 , y > 1 ? + 1 : 0 ) ;
extrapolate_one_point ( half_x - x , half_y + y , x > 1 ? + 1 : 0 , y > 1 ? - 1 : 0 ) ;
extrapolate_one_point ( half_x + x , half_y + y , x > 1 ? - 1 : 0 , y > 1 ? - 1 : 0 ) ;
}
# ifdef HALF_IN_X
const uint8_t ctrx2 = 0 , xlen = ABL_GRID_POINTS_X - 1 ;
# else
const uint8_t ctrx1 = ( ABL_GRID_POINTS_X - 1 ) / 2 , // left-of-center
ctrx2 = ABL_GRID_POINTS_X / 2 , // right-of-center
xlen = ctrx1 ;
# endif
# ifdef HALF_IN_Y
const uint8_t ctry2 = 0 , ylen = ABL_GRID_POINTS_Y - 1 ;
# else
const uint8_t ctry1 = ( ABL_GRID_POINTS_Y - 1 ) / 2 , // top-of-center
ctry2 = ABL_GRID_POINTS_Y / 2 , // bottom-of-center
ylen = ctry1 ;
# endif
for ( uint8_t xo = 0 ; xo < = xlen ; xo + + )
for ( uint8_t yo = 0 ; yo < = ylen ; yo + + ) {
uint8_t x2 = ctrx2 + xo , y2 = ctry2 + yo ;
# ifndef HALF_IN_X
uint8_t x1 = ctrx1 - xo ;
# endif
# ifndef HALF_IN_Y
uint8_t y1 = ctry1 - yo ;
# ifndef HALF_IN_X
extrapolate_one_point ( x1 , y1 , + 1 , + 1 ) ; // left-below + +
# endif
extrapolate_one_point ( x2 , y1 , - 1 , + 1 ) ; // right-below - +
# endif
# ifndef HALF_IN_X
extrapolate_one_point ( x1 , y2 , + 1 , - 1 ) ; // left-above + -
# endif
extrapolate_one_point ( x2 , y2 , - 1 , - 1 ) ; // right-above - -
}
}
/**
* Print calibration results for plotting or manual frame adjustment .
*/
static void print_bed_level ( ) {
SERIAL_ECHOPGM ( " Bilinear Leveling Grid: \n " ) ;
for ( uint8_t x = 1 ; x < ABL_GRID_POINTS_X + 1 ; x + + ) {
SERIAL_PROTOCOLPGM ( " " ) ;
if ( x < 10 ) SERIAL_PROTOCOLCHAR ( ' ' ) ;
SERIAL_PROTOCOL ( ( int ) x ) ;
}
SERIAL_EOL ;
for ( uint8_t y = 0 ; y < ABL_GRID_POINTS_Y ; y + + ) {
if ( y < 9 ) SERIAL_PROTOCOLCHAR ( ' ' ) ;
SERIAL_PROTOCOL ( y + 1 ) ;
for ( uint8_t x = 0 ; x < ABL_GRID_POINTS_X ; x + + ) {
SERIAL_PROTOCOL_F ( bed_level_grid [ x ] [ y ] , 2 ) ;
SERIAL_PROTOCOLCHAR ( ' ' ) ;
float offset = bed_level_grid [ x ] [ y ] ;
if ( offset < 999.0 ) {
if ( offset > 0 ) SERIAL_CHAR ( ' + ' ) ;
SERIAL_PROTOCOL_F ( offset , 2 ) ;
}
else
SERIAL_PROTOCOLPGM ( " ==== " ) ;
}
SERIAL_EOL ;
}
SERIAL_EOL ;
}
# endif // AUTO_BED_LEVELING_BILINEAR