Esempio n. 1
0
/**
 * - Move to the given XY
 * - Deploy the probe, if not already deployed
 * - Probe the bed, get the Z position
 * - Depending on the 'stow' flag
 *   - Stow the probe, or
 *   - Raise to the BETWEEN height
 * - Return the probed Z position
 */
float probe_pt(const float &lx, const float &ly, const bool stow, const uint8_t verbose_level, const bool printable/*=true*/) {
  #if ENABLED(DEBUG_LEVELING_FEATURE)
    if (DEBUGGING(LEVELING)) {
      SERIAL_ECHOPAIR(">>> probe_pt(", lx);
      SERIAL_ECHOPAIR(", ", ly);
      SERIAL_ECHOPAIR(", ", stow ? "" : "no ");
      SERIAL_ECHOLNPGM("stow)");
      DEBUG_POS("", current_position);
    }
  #endif

  const float nx = lx - (X_PROBE_OFFSET_FROM_EXTRUDER), ny = ly - (Y_PROBE_OFFSET_FROM_EXTRUDER);

  if (printable
    ? !position_is_reachable_xy(nx, ny)
    : !position_is_reachable_by_probe_xy(lx, ly)
  ) return NAN;


  const float old_feedrate_mm_s = feedrate_mm_s;

  #if ENABLED(DELTA)
    if (current_position[Z_AXIS] > delta_clip_start_height)
      do_blocking_move_to_z(delta_clip_start_height);
  #endif

  #if HAS_SOFTWARE_ENDSTOPS
    // Store the status of the soft endstops and disable if we're probing a non-printable location
    static bool enable_soft_endstops = soft_endstops_enabled;
    if (!printable) soft_endstops_enabled = false;
  #endif

  feedrate_mm_s = XY_PROBE_FEEDRATE_MM_S;

  // Move the probe to the given XY
  do_blocking_move_to_xy(nx, ny);

  float measured_z = NAN;
  if (!DEPLOY_PROBE()) {
    measured_z = run_z_probe(printable);

    if (!stow)
      do_blocking_move_to_z(current_position[Z_AXIS] + Z_CLEARANCE_BETWEEN_PROBES, MMM_TO_MMS(Z_PROBE_SPEED_FAST));
    else
      if (STOW_PROBE()) measured_z = NAN;
  }

  #if HAS_SOFTWARE_ENDSTOPS
    // Restore the soft endstop status
    soft_endstops_enabled = enable_soft_endstops;
  #endif

  if (verbose_level > 2) {
    SERIAL_PROTOCOLPGM("Bed X: ");
    SERIAL_PROTOCOL_F(lx, 3);
    SERIAL_PROTOCOLPGM(" Y: ");
    SERIAL_PROTOCOL_F(ly, 3);
    SERIAL_PROTOCOLPGM(" Z: ");
    SERIAL_PROTOCOL_F(measured_z, 3);
    SERIAL_EOL();
  }

  #if ENABLED(DEBUG_LEVELING_FEATURE)
    if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< probe_pt");
  #endif

  feedrate_mm_s = old_feedrate_mm_s;

  if (isnan(measured_z)) {
    LCD_MESSAGEPGM(MSG_ERR_PROBING_FAILED);
    SERIAL_ERROR_START();
    SERIAL_ERRORLNPGM(MSG_ERR_PROBING_FAILED);
  }

  return measured_z;
}
  /**
   * This function used to be inline code in G26. But there are so many
   * parameters it made sense to turn them into static globals and get
   * this code out of sight of the main routine.
   */
  bool unified_bed_leveling::parse_G26_parameters() {

    g26_extrusion_multiplier  = EXTRUSION_MULTIPLIER;
    g26_retraction_multiplier = RETRACTION_MULTIPLIER;
    g26_nozzle                = NOZZLE;
    g26_filament_diameter     = FILAMENT;
    g26_layer_height          = LAYER_HEIGHT;
    g26_prime_length          = PRIME_LENGTH;
    g26_bed_temp              = BED_TEMP;
    g26_hotend_temp           = HOTEND_TEMP;
    g26_prime_flag            = 0;

    g26_ooze_amount           = parser.linearval('O', OOZE_AMOUNT);
    g26_keep_heaters_on       = parser.boolval('K');
    g26_continue_with_closest = parser.boolval('C');

    if (parser.seenval('B')) {
      g26_bed_temp = parser.value_celsius();
      if (!WITHIN(g26_bed_temp, 15, 140)) {
        SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seenval('L')) {
      g26_layer_height = parser.value_linear_units();
      if (!WITHIN(g26_layer_height, 0.0, 2.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seen('Q')) {
      if (parser.has_value()) {
        g26_retraction_multiplier = parser.value_float();
        if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) {
          SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible.");
          return UBL_ERR;
        }
      }
      else {
        SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified.");
        return UBL_ERR;
      }
    }

    if (parser.seenval('S')) {
      g26_nozzle = parser.value_float();
      if (!WITHIN(g26_nozzle, 0.1, 1.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seen('P')) {
      if (!parser.has_value()) {
        #if ENABLED(NEWPANEL)
          g26_prime_flag = -1;
        #else
          SERIAL_PROTOCOLLNPGM("?Prime length must be specified when not using an LCD.");
          return UBL_ERR;
        #endif
      }
      else {
        g26_prime_flag++;
        g26_prime_length = parser.value_linear_units();
        if (!WITHIN(g26_prime_length, 0.0, 25.0)) {
          SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible.");
          return UBL_ERR;
        }
      }
    }

    if (parser.seenval('F')) {
      g26_filament_diameter = parser.value_linear_units();
      if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible.");
        return UBL_ERR;
      }
    }
    g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to
                                                                      // scale up or down the length needed to get the
                                                                      // same volume of filament

    g26_extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size

    if (parser.seenval('H')) {
      g26_hotend_temp = parser.value_celsius();
      if (!WITHIN(g26_hotend_temp, 165, 280)) {
        SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seen('U')) {
      randomSeed(millis());
      // This setting will persist for the next G26
      random_deviation = parser.has_value() ? parser.value_float() : 50.0;
    }

    #if ENABLED(NEWPANEL)
      g26_repeats = parser.intval('R', GRID_MAX_POINTS + 1);
    #else
      if (!parser.seen('R')) {
        SERIAL_PROTOCOLLNPGM("?(R)epeat must be specified when not using an LCD.");
        return UBL_ERR;
      }
      else
        g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1;
    #endif
    if (g26_repeats < 1) {
      SERIAL_PROTOCOLLNPGM("?(R)epeat value not plausible; must be at least 1.");
      return UBL_ERR;
    }

    g26_x_pos = parser.linearval('X', current_position[X_AXIS]);
    g26_y_pos = parser.linearval('Y', current_position[Y_AXIS]);
    if (!position_is_reachable_xy(g26_x_pos, g26_y_pos)) {
      SERIAL_PROTOCOLLNPGM("?Specified X,Y coordinate out of bounds.");
      return UBL_ERR;
    }

    /**
     * Wait until all parameters are verified before altering the state!
     */
    set_bed_leveling_enabled(!parser.seen('D'));

    return UBL_OK;
  }