Esempio n. 1
0
// Get the Z adjustment for non-linear bed leveling
float bilinear_z_offset(const float raw[XYZ]) {

  static float z1, d2, z3, d4, L, D, ratio_x, ratio_y,
               last_x = -999.999, last_y = -999.999;

  // Whole units for the grid line indices. Constrained within bounds.
  static int8_t gridx, gridy, nextx, nexty,
                last_gridx = -99, last_gridy = -99;

  // XY relative to the probed area
  const float rx = raw[X_AXIS] - bilinear_start[X_AXIS],
              ry = raw[Y_AXIS] - bilinear_start[Y_AXIS];

  #if ENABLED(EXTRAPOLATE_BEYOND_GRID)
    // Keep using the last grid box
    #define FAR_EDGE_OR_BOX 2
  #else
    // Just use the grid far edge
    #define FAR_EDGE_OR_BOX 1
  #endif

  if (last_x != rx) {
    last_x = rx;
    ratio_x = rx * ABL_BG_FACTOR(X_AXIS);
    const float gx = constrain(FLOOR(ratio_x), 0, ABL_BG_POINTS_X - (FAR_EDGE_OR_BOX));
    ratio_x -= gx;      // Subtract whole to get the ratio within the grid box

    #if DISABLED(EXTRAPOLATE_BEYOND_GRID)
      // Beyond the grid maintain height at grid edges
      NOLESS(ratio_x, 0); // Never < 0.0. (> 1.0 is ok when nextx==gridx.)
    #endif

    gridx = gx;
    nextx = MIN(gridx + 1, ABL_BG_POINTS_X - 1);
  }

  if (last_y != ry || last_gridx != gridx) {

    if (last_y != ry) {
      last_y = ry;
      ratio_y = ry * ABL_BG_FACTOR(Y_AXIS);
      const float gy = constrain(FLOOR(ratio_y), 0, ABL_BG_POINTS_Y - (FAR_EDGE_OR_BOX));
      ratio_y -= gy;

      #if DISABLED(EXTRAPOLATE_BEYOND_GRID)
        // Beyond the grid maintain height at grid edges
        NOLESS(ratio_y, 0); // Never < 0.0. (> 1.0 is ok when nexty==gridy.)
      #endif

      gridy = gy;
      nexty = MIN(gridy + 1, ABL_BG_POINTS_Y - 1);
    }

    if (last_gridx != gridx || last_gridy != gridy) {
      last_gridx = gridx;
      last_gridy = gridy;
      // Z at the box corners
      z1 = ABL_BG_GRID(gridx, gridy);       // left-front
      d2 = ABL_BG_GRID(gridx, nexty) - z1;  // left-back (delta)
      z3 = ABL_BG_GRID(nextx, gridy);       // right-front
      d4 = ABL_BG_GRID(nextx, nexty) - z3;  // right-back (delta)
    }

    // Bilinear interpolate. Needed since ry or gridx has changed.
                L = z1 + d2 * ratio_y;   // Linear interp. LF -> LB
    const float R = z3 + d4 * ratio_y;   // Linear interp. RF -> RB

    D = R - L;
  }

  const float offset = L + ratio_x * D;   // the offset almost always changes

  /*
  static float last_offset = 0;
  if (ABS(last_offset - offset) > 0.2) {
    SERIAL_ECHOPGM("Sudden Shift at ");
    SERIAL_ECHOPAIR("x=", rx);
    SERIAL_ECHOPAIR(" / ", bilinear_grid_spacing[X_AXIS]);
    SERIAL_ECHOLNPAIR(" -> gridx=", gridx);
    SERIAL_ECHOPAIR(" y=", ry);
    SERIAL_ECHOPAIR(" / ", bilinear_grid_spacing[Y_AXIS]);
    SERIAL_ECHOLNPAIR(" -> gridy=", gridy);
    SERIAL_ECHOPAIR(" ratio_x=", ratio_x);
    SERIAL_ECHOLNPAIR(" ratio_y=", ratio_y);
    SERIAL_ECHOPAIR(" z1=", z1);
    SERIAL_ECHOPAIR(" z2=", z2);
    SERIAL_ECHOPAIR(" z3=", z3);
    SERIAL_ECHOLNPAIR(" z4=", z4);
    SERIAL_ECHOPAIR(" L=", L);
    SERIAL_ECHOPAIR(" R=", R);
    SERIAL_ECHOLNPAIR(" offset=", offset);
  }
  last_offset = offset;
  //*/

  return offset;
}
Esempio n. 2
0
    // Get the Z adjustment for non-linear bed leveling
    float Bed_level::bilinear_z_offset(const float logical[XYZ]) {

      static float  z1, d2, z3, d4, L, D, ratio_x, ratio_y,
                    last_x = -999.999, last_y = -999.999;

      // Whole units for the grid line indices. Constrained within bounds.
      static int8_t gridx, gridy, nextx, nexty,
                    last_gridx = -99, last_gridy = -99;

      // XY relative to the probed area
      const float x = RAW_X_POSITION(logical[X_AXIS]) - bilinear_start[X_AXIS],
                  y = RAW_Y_POSITION(logical[Y_AXIS]) - bilinear_start[Y_AXIS];

      if (last_x != x) {
        last_x = x;
        ratio_x = x * ABL_BG_FACTOR(X_AXIS);
        const float gx = constrain(floor(ratio_x), 0, ABL_BG_POINTS_X - 1);
        ratio_x -= gx;      // Subtract whole to get the ratio within the grid box
        NOLESS(ratio_x, 0); // Never < 0.0. (> 1.0 is ok when nextx==gridx.)
        gridx = gx;
        nextx = min(gridx + 1, ABL_BG_POINTS_X - 1);
      }

      if (last_y != y || last_gridx != gridx) {

        if (last_y != y) {
          last_y = y;
          ratio_y = y * ABL_BG_FACTOR(Y_AXIS);
          const float gy = constrain(floor(ratio_y), 0, ABL_BG_POINTS_Y - 1);
          ratio_y -= gy;
          NOLESS(ratio_y, 0);
          gridy = gy;
          nexty = min(gridy + 1, ABL_BG_POINTS_Y - 1);
        }

        if (last_gridx != gridx || last_gridy != gridy) {
          last_gridx = gridx;
          last_gridy = gridy;
          // Z at the box corners
          z1 = ABL_BG_GRID(gridx, gridy);       // left-front
          d2 = ABL_BG_GRID(gridx, nexty) - z1;  // left-back (delta)
          z3 = ABL_BG_GRID(nextx, gridy);       // right-front
          d4 = ABL_BG_GRID(nextx, nexty) - z3;  // right-back (delta)
        }

        // Bilinear interpolate. Needed since y or gridx has changed.
                    L = z1 + d2 * ratio_y;   // Linear interp. LF -> LB
        const float R = z3 + d4 * ratio_y;   // Linear interp. RF -> RB

        D = R - L;
      }

      const float offset = L + ratio_x * D;   // the offset almost always changes

      /*
      static float last_offset = 0;
      if (FABS(last_offset - offset) > 0.2) {
        SERIAL_MSG("Sudden Shift at ");
        SERIAL_MV("x=", x);
        SERIAL_MV(" / ", ABL_BG_SPACING(X_AXIS));
        SERIAL_EMV(" -> gridx=", gridx);
        SERIAL_MV(" y=", y);
        SERIAL_MV(" / ", ABL_BG_SPACING(Y_AXIS));
        SERIAL_EMV(" -> gridy=", gridy);
        SERIAL_MV(" ratio_x=", ratio_x);
        SERIAL_EMV(" ratio_y=", ratio_y);
        SERIAL_MV(" z1=", z1);
        SERIAL_MV(" d2=", d2);
        SERIAL_MV(" z3=", z3);
        SERIAL_EMV(" d4=", d4);
        SERIAL_MV(" L=", L);
        SERIAL_MV(" R=", R);
        SERIAL_EMV(" offset=", offset);
      }
      last_offset = offset;
      */

      return offset;
    }