示例#1
0
/**
 * M900: Get or Set Linear Advance K-factor
 *
 *  K<factor>   Set advance K factor
 */
void GcodeSuite::M900() {

  #if EXTRUDERS < 2
    constexpr uint8_t tmp_extruder = 0;
  #else
    const uint8_t tmp_extruder = parser.seenval('T') ? parser.value_int() : active_extruder;
    if (tmp_extruder >= EXTRUDERS) {
      SERIAL_ECHOLNPGM("?T value out of range.");
      return;
    }
  #endif

  if (parser.seenval('K')) {
    const float newK = parser.floatval('K');
    if (WITHIN(newK, 0, 10)) {
      planner.synchronize();
      planner.extruder_advance_K[tmp_extruder] = newK;
    }
    else
      SERIAL_ECHOLNPGM("?K value out of range (0-10).");
  }
  else {
    SERIAL_ECHO_START();
    #if EXTRUDERS < 2
      SERIAL_ECHOLNPAIR("Advance K=", planner.extruder_advance_K[0]);
    #else
      SERIAL_ECHOPGM("Advance K");
      LOOP_L_N(i, EXTRUDERS) {
        SERIAL_CHAR(' '); SERIAL_ECHO(int(i));
        SERIAL_CHAR('='); SERIAL_ECHO(planner.extruder_advance_K[i]);
      }
      SERIAL_EOL();
    #endif
  }
示例#2
0
void dac_print_values() {
  if (!dac_present) return;

  SERIAL_ECHO_START();
  SERIAL_ECHOLNPGM("Stepper current values in % (Amps):");
  SERIAL_ECHO_START();
  SERIAL_ECHOPAIR(" X:",  dac_perc(X_AXIS));
  SERIAL_ECHOPAIR(" (",   dac_amps(X_AXIS));
  SERIAL_ECHOPAIR(") Y:", dac_perc(Y_AXIS));
  SERIAL_ECHOPAIR(" (",   dac_amps(Y_AXIS));
  SERIAL_ECHOPAIR(") Z:", dac_perc(Z_AXIS));
  SERIAL_ECHOPAIR(" (",   dac_amps(Z_AXIS));
  SERIAL_ECHOPAIR(") E:", dac_perc(E_AXIS));
  SERIAL_ECHOPAIR(" (",   dac_amps(E_AXIS));
  SERIAL_ECHOLN(")");
}
示例#3
0
文件: M0_M1.cpp 项目: aon3d/Marlin
/**
 * M0: Unconditional stop - Wait for user button press on LCD
 * M1: Conditional stop   - Wait for user button press on LCD
 */
void GcodeSuite::M0_M1() {
  const char * const args = parser.string_arg;

  millis_t ms = 0;
  bool hasP = false, hasS = false;
  if (parser.seenval('P')) {
    ms = parser.value_millis(); // milliseconds to wait
    hasP = ms > 0;
  }
  if (parser.seenval('S')) {
    ms = parser.value_millis_from_seconds(); // seconds to wait
    hasS = ms > 0;
  }

  #if ENABLED(ULTIPANEL)

    if (!hasP && !hasS && args && *args)
      lcd_setstatus(args, true);
    else {
      LCD_MESSAGEPGM(MSG_USERWAIT);
      #if ENABLED(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0
        dontExpireStatus();
      #endif
    }

  #else

    if (!hasP && !hasS && args && *args) {
      SERIAL_ECHO_START();
      SERIAL_ECHOLN(args);
    }

  #endif

  KEEPALIVE_STATE(PAUSED_FOR_USER);
  wait_for_user = true;

  stepper.synchronize();
  refresh_cmd_timeout();

  if (ms > 0) {
    ms += previous_cmd_ms;  // wait until this time for a click
    while (PENDING(millis(), ms) && wait_for_user) idle();
  }
  else {
    #if ENABLED(ULTIPANEL)
      if (lcd_detected()) {
        while (wait_for_user) idle();
        IS_SD_PRINTING ? LCD_MESSAGEPGM(MSG_RESUMING) : LCD_MESSAGEPGM(WELCOME_MSG);
      }
    #else
      while (wait_for_user) idle();
    #endif
  }

  wait_for_user = false;
  KEEPALIVE_STATE(IN_HANDLER);
}
示例#4
0
 FORCE_INLINE void mod_zprobe_zoffset(const float &offs) {
   if (true
     #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
       && active_extruder == 0
     #endif
   ) {
     zprobe_zoffset += offs;
     SERIAL_ECHO_START();
     SERIAL_ECHOLNPAIR(MSG_PROBE_Z_OFFSET ": ", zprobe_zoffset);
   }
   #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
     else {
       hotend_offset[Z_AXIS][active_extruder] -= offs;
       SERIAL_ECHO_START();
       SERIAL_ECHOLNPAIR(MSG_IDEX_Z_OFFSET ": ", hotend_offset[Z_AXIS][active_extruder]);
     }
   #endif
 }
示例#5
0
文件: M113.cpp 项目: aon3d/Marlin
/**
 * M113: Get or set Host Keepalive interval (0 to disable)
 *
 *   S<seconds> Optional. Set the keepalive interval.
 */
void GcodeSuite::M113() {
  if (parser.seenval('S')) {
    host_keepalive_interval = parser.value_byte();
    NOMORE(host_keepalive_interval, 60);
  }
  else {
    SERIAL_ECHO_START();
    SERIAL_ECHOLNPAIR("M113 S", (unsigned long)host_keepalive_interval);
  }
}
示例#6
0
bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
  while (size--) {
    uint8_t * const p = (uint8_t * const)pos;
    uint8_t v = *value;
    // EEPROM has only ~100,000 write cycles,
    // so only write bytes that have changed!
    if (v != eeprom_read_byte(p)) {
      eeprom_write_byte(p, v);
      if (eeprom_read_byte(p) != v) {
        SERIAL_ECHO_START();
        SERIAL_ECHOLNPGM(MSG_ERR_EEPROM_WRITE);
        return true;
      }
    }
    crc16(crc, &v, 1);
    pos++;
    value++;
  };
  return false;
}
示例#7
0
/**
 * Perform a tool-change, which may result in moving the
 * previous tool out of the way and the new tool into place.
 */
void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool no_move/*=false*/) {
  #if ENABLED(MIXING_EXTRUDER)

    UNUSED(fr_mm_s); UNUSED(no_move);

    if (tmp_extruder >= MIXING_VIRTUAL_TOOLS)
      return invalid_extruder_error(tmp_extruder);

    #if MIXING_VIRTUAL_TOOLS > 1
      // T0-Tnnn: Switch virtual tool by changing the index to the mix
      mixer.T(tmp_extruder);
    #endif

  #elif ENABLED(PRUSA_MMU2)

    UNUSED(fr_mm_s); UNUSED(no_move);

    mmu2.toolChange(tmp_extruder);

  #elif EXTRUDERS < 2

    UNUSED(fr_mm_s); UNUSED(no_move);

    if (tmp_extruder) invalid_extruder_error(tmp_extruder);
    return;

  #else // EXTRUDERS > 1

    planner.synchronize();

    #if ENABLED(DUAL_X_CARRIAGE)  // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_MIRRORED_MODE
      if (tmp_extruder != 0 && dxc_is_duplicating())
         return invalid_extruder_error(tmp_extruder);
    #endif

    #if HAS_LEVELING
      // Set current position to the physical position
      const bool leveling_was_active = planner.leveling_active;
      set_bed_leveling_enabled(false);
    #endif

    if (tmp_extruder >= EXTRUDERS)
      return invalid_extruder_error(tmp_extruder);

    if (!no_move && !all_axes_homed()) {
      no_move = true;
      if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("No move on toolchange");
    }

    #if HAS_LCD_MENU
      ui.return_to_status();
    #endif

    #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
      const bool should_swap = !no_move && toolchange_settings.swap_length;
      #if ENABLED(PREVENT_COLD_EXTRUSION)
        const bool too_cold = !DEBUGGING(DRYRUN) && (thermalManager.targetTooColdToExtrude(active_extruder) || thermalManager.targetTooColdToExtrude(tmp_extruder));
      #else
        constexpr bool too_cold = false;
      #endif
      if (should_swap) {
        if (too_cold) {
          SERIAL_ECHO_MSG(MSG_ERR_HOTEND_TOO_COLD);
          #if ENABLED(SINGLENOZZLE)
            active_extruder = tmp_extruder;
            return;
          #endif
        }
        else {
          #if ENABLED(ADVANCED_PAUSE_FEATURE)
            do_pause_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
          #else
            current_position[E_AXIS] -= toolchange_settings.swap_length / planner.e_factor[active_extruder];
            planner.buffer_line(current_position, MMM_TO_MMS(toolchange_settings.retract_speed), active_extruder);
          #endif
        }
      }
    #endif // TOOLCHANGE_FILAMENT_SWAP

    if (tmp_extruder != active_extruder) {

      #if SWITCHING_NOZZLE_TWO_SERVOS
        raise_nozzle(active_extruder);
      #endif

      const float old_feedrate_mm_s = fr_mm_s > 0.0 ? fr_mm_s : feedrate_mm_s;
      feedrate_mm_s = fr_mm_s > 0.0 ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S;

      #if HAS_SOFTWARE_ENDSTOPS && ENABLED(DUAL_X_CARRIAGE)
        update_software_endstops(X_AXIS, active_extruder, tmp_extruder);
      #endif

      set_destination_from_current();

      if (!no_move) {
        #if DISABLED(SWITCHING_NOZZLE)
          // Do a small lift to avoid the workpiece in the move back (below)
          #if ENABLED(TOOLCHANGE_PARK)
            current_position[X_AXIS] = toolchange_settings.change_point.x;
            current_position[Y_AXIS] = toolchange_settings.change_point.y;
          #endif
          current_position[Z_AXIS] += toolchange_settings.z_raise;
          #if HAS_SOFTWARE_ENDSTOPS
            NOMORE(current_position[Z_AXIS], soft_endstop[Z_AXIS].max);
          #endif
          planner.buffer_line(current_position, feedrate_mm_s, active_extruder);
        #endif
        planner.synchronize();
      }

      #if HAS_HOTEND_OFFSET
        #if ENABLED(DUAL_X_CARRIAGE)
          constexpr float xdiff = 0;
        #else
          const float xdiff = hotend_offset[X_AXIS][tmp_extruder] - hotend_offset[X_AXIS][active_extruder];
        #endif
        const float ydiff = hotend_offset[Y_AXIS][tmp_extruder] - hotend_offset[Y_AXIS][active_extruder],
                    zdiff = hotend_offset[Z_AXIS][tmp_extruder] - hotend_offset[Z_AXIS][active_extruder];
      #else
        constexpr float xdiff = 0, ydiff = 0, zdiff = 0;
      #endif

      #if ENABLED(DUAL_X_CARRIAGE)
        dualx_tool_change(tmp_extruder, no_move);
      #elif ENABLED(PARKING_EXTRUDER) // Dual Parking extruder
        parking_extruder_tool_change(tmp_extruder, no_move);
      #elif ENABLED(MAGNETIC_PARKING_EXTRUDER) // Magnetic Parking extruder
        magnetic_parking_extruder_tool_change(tmp_extruder);
      #elif ENABLED(SWITCHING_TOOLHEAD) // Switching Toolhead
        switching_toolhead_tool_change(tmp_extruder, fr_mm_s, no_move);
      #elif ENABLED(SWITCHING_NOZZLE) && !SWITCHING_NOZZLE_TWO_SERVOS
        // Raise by a configured distance to avoid workpiece, except with
        // SWITCHING_NOZZLE_TWO_SERVOS, as both nozzles will lift instead.
        current_position[Z_AXIS] += MAX(-zdiff, 0.0) + toolchange_settings.z_raise;
        #if HAS_SOFTWARE_ENDSTOPS
          NOMORE(current_position[Z_AXIS], soft_endstop[Z_AXIS].max);
        #endif
        if (!no_move) fast_line_to_current(Z_AXIS);
        move_nozzle_servo(tmp_extruder);
      #endif

      if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Offset Tool XY by { ", xdiff, ", ", ydiff, ", ", zdiff, " }");

      // The newly-selected extruder XY is actually at...
      current_position[X_AXIS] += xdiff;
      current_position[Y_AXIS] += ydiff;
      current_position[Z_AXIS] += zdiff;

      // Set the new active extruder if not already done in tool specific function above
      active_extruder = tmp_extruder;

      // Tell the planner the new "current position"
      sync_plan_position();

      #if ENABLED(DELTA)
        //LOOP_XYZ(i) update_software_endstops(i); // or modify the constrain function
        const bool safe_to_move = current_position[Z_AXIS] < delta_clip_start_height - 1;
      #else
        constexpr bool safe_to_move = true;
      #endif

      // Return to position and lower again
      if (safe_to_move && !no_move && IsRunning()) {
        if (DEBUGGING(LEVELING)) DEBUG_POS("Move back", destination);

        #if ENABLED(SINGLENOZZLE)
          #if FAN_COUNT > 0
            singlenozzle_fan_speed[active_extruder] = thermalManager.fan_speed[0];
            thermalManager.fan_speed[0] = singlenozzle_fan_speed[tmp_extruder];
          #endif

          singlenozzle_temp[active_extruder] = thermalManager.temp_hotend[0].target;
          if (singlenozzle_temp[tmp_extruder] && singlenozzle_temp[tmp_extruder] != singlenozzle_temp[active_extruder]) {
            thermalManager.setTargetHotend(singlenozzle_temp[tmp_extruder], 0);
            #if EITHER(ULTRA_LCD, EXTENSIBLE_UI)
              thermalManager.set_heating_message(0);
            #endif
            (void)thermalManager.wait_for_hotend(0, false);  // Wait for heating or cooling
          }
          active_extruder = tmp_extruder;
        #endif

        #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
          if (should_swap && !too_cold) {
            #if ENABLED(ADVANCED_PAUSE_FEATURE)
              do_pause_e_move(toolchange_settings.swap_length + TOOLCHANGE_FIL_EXTRA_PRIME, toolchange_settings.prime_speed);
            #else
              current_position[E_AXIS] += (toolchange_settings.swap_length + TOOLCHANGE_FIL_EXTRA_PRIME) / planner.e_factor[tmp_extruder];
              planner.buffer_line(current_position, toolchange_settings.prime_speed, tmp_extruder);
            #endif
            planner.synchronize();

            #if TOOLCHANGE_FIL_EXTRA_PRIME
              planner.set_e_position_mm((destination[E_AXIS] = current_position[E_AXIS] = current_position[E_AXIS] - (TOOLCHANGE_FIL_EXTRA_PRIME)));
            #endif
          }
        #endif

        // Prevent a move outside physical bounds
        apply_motion_limits(destination);

        // Move back to the original (or tweaked) position
        do_blocking_move_to(destination);

        #if ENABLED(DUAL_X_CARRIAGE)
          active_extruder_parked = false;
        #endif
        feedrate_mm_s = old_feedrate_mm_s;
      }
      #if ENABLED(SWITCHING_NOZZLE)
        else {
          // Move back down. (Including when the new tool is higher.)
          do_blocking_move_to_z(destination[Z_AXIS], planner.settings.max_feedrate_mm_s[Z_AXIS]);
        }
      #endif

      #if ENABLED(PRUSA_MMU2)
        mmu2.toolChange(tmp_extruder);
      #endif

      #if SWITCHING_NOZZLE_TWO_SERVOS
        lower_nozzle(active_extruder);
      #endif

      #if ENABLED(TOOLCHANGE_FILAMENT_SWAP) && ADVANCED_PAUSE_RESUME_PRIME != 0
        if (should_swap && !too_cold) {
          const float resume_eaxis = current_position[E_AXIS];
          #if ENABLED(ADVANCED_PAUSE_FEATURE)
            do_pause_e_move(toolchange_settings.swap_length, toolchange_settings.prime_speed);
          #else
            current_position[E_AXIS] += (ADVANCED_PAUSE_RESUME_PRIME) / planner.e_factor[active_extruder];
            planner.buffer_line(current_position, ADVANCED_PAUSE_PURGE_FEEDRATE, active_extruder);
          #endif
          planner.synchronize();
          planner.set_e_position_mm((destination[E_AXIS] = current_position[E_AXIS] = resume_eaxis));
        }
      #endif

    } // (tmp_extruder != active_extruder)

    planner.synchronize();

    #if ENABLED(EXT_SOLENOID) && DISABLED(PARKING_EXTRUDER)
      disable_all_solenoids();
      enable_solenoid_on_active_extruder();
    #endif

    #if ENABLED(MK2_MULTIPLEXER)
      if (tmp_extruder >= E_STEPPERS) return invalid_extruder_error(tmp_extruder);
      select_multiplexed_stepper(tmp_extruder);
    #endif

    #if DO_SWITCH_EXTRUDER
      planner.synchronize();
      move_extruder_servo(active_extruder);
    #endif

    #if HAS_FANMUX
      fanmux_switch(active_extruder);
    #endif

    #if HAS_LEVELING
      // Restore leveling to re-establish the logical position
      set_bed_leveling_enabled(leveling_was_active);
    #endif

    SERIAL_ECHO_START();
    SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(active_extruder));

  #endif // EXTRUDERS > 1
}
示例#8
0
inline void invalid_extruder_error(const uint8_t e) {
  SERIAL_ECHO_START();
  SERIAL_CHAR('T'); SERIAL_ECHO(int(e));
  SERIAL_CHAR(' '); SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER);
}
示例#9
0
/**
 * M420: Enable/Disable Bed Leveling and/or set the Z fade height.
 *
 *   S[bool]   Turns leveling on or off
 *   Z[height] Sets the Z fade height (0 or none to disable)
 *   V[bool]   Verbose - Print the leveling grid
 *
 * With AUTO_BED_LEVELING_UBL only:
 *
 *   L[index]  Load UBL mesh from index (0 is default)
 *   T[map]    0:Human-readable 1:CSV 2:"LCD" 4:Compact
 *
 * With mesh-based leveling only:
 *
 *   C         Center mesh on the mean of the lowest and highest
 *
 * With MARLIN_DEV_MODE:
 *   S2        Create a simple random mesh and enable
 */
void GcodeSuite::M420() {
  const bool seen_S = parser.seen('S'),
             to_enable = seen_S ? parser.value_bool() : planner.leveling_active;

  #if ENABLED(MARLIN_DEV_MODE)
    if (parser.intval('S') == 2) {
      #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
        bilinear_start[X_AXIS] = MIN_PROBE_X;
        bilinear_start[Y_AXIS] = MIN_PROBE_Y;
        bilinear_grid_spacing[X_AXIS] = (MAX_PROBE_X - (MIN_PROBE_X)) / (GRID_MAX_POINTS_X - 1);
        bilinear_grid_spacing[Y_AXIS] = (MAX_PROBE_Y - (MIN_PROBE_Y)) / (GRID_MAX_POINTS_Y - 1);
      #endif
      for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
          Z_VALUES(x, y) = 0.001 * random(-200, 200);
      SERIAL_ECHOPGM("Simulated " STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_X) " mesh ");
      SERIAL_ECHOPAIR(" (", MIN_PROBE_X);
      SERIAL_CHAR(','); SERIAL_ECHO(MIN_PROBE_Y);
      SERIAL_ECHOPAIR(")-(", MAX_PROBE_X);
      SERIAL_CHAR(','); SERIAL_ECHO(MAX_PROBE_Y);
      SERIAL_ECHOLNPGM(")");
    }
  #endif

  // If disabling leveling do it right away
  // (Don't disable for just M420 or M420 V)
  if (seen_S && !to_enable) set_bed_leveling_enabled(false);

  const float oldpos[] = { current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] };

  #if ENABLED(AUTO_BED_LEVELING_UBL)

    // L to load a mesh from the EEPROM
    if (parser.seen('L')) {

      set_bed_leveling_enabled(false);

      #if ENABLED(EEPROM_SETTINGS)
        const int8_t storage_slot = parser.has_value() ? parser.value_int() : ubl.storage_slot;
        const int16_t a = settings.calc_num_meshes();

        if (!a) {
          SERIAL_ECHOLNPGM("?EEPROM storage not available.");
          return;
        }

        if (!WITHIN(storage_slot, 0, a - 1)) {
          SERIAL_ECHOLNPGM("?Invalid storage slot.");
          SERIAL_ECHOLNPAIR("?Use 0 to ", a - 1);
          return;
        }

        settings.load_mesh(storage_slot);
        ubl.storage_slot = storage_slot;

      #else

        SERIAL_ECHOLNPGM("?EEPROM storage not available.");
        return;

      #endif
    }

    // L or V display the map info
    if (parser.seen('L') || parser.seen('V')) {
      ubl.display_map(parser.byteval('T'));
      SERIAL_ECHOPGM("Mesh is ");
      if (!ubl.mesh_is_valid()) SERIAL_ECHOPGM("in");
      SERIAL_ECHOLNPAIR("valid\nStorage slot: ", ubl.storage_slot);
    }

  #endif // AUTO_BED_LEVELING_UBL

  const bool seenV = parser.seen('V');

  #if HAS_MESH

    if (leveling_is_valid()) {

      // Subtract the given value or the mean from all mesh values
      if (parser.seen('C')) {
        const float cval = parser.value_float();
        #if ENABLED(AUTO_BED_LEVELING_UBL)

          set_bed_leveling_enabled(false);
          ubl.adjust_mesh_to_mean(true, cval);

        #else

          #if ENABLED(M420_C_USE_MEAN)

            // Get the sum and average of all mesh values
            float mesh_sum = 0;
            for (uint8_t x = GRID_MAX_POINTS_X; x--;)
              for (uint8_t y = GRID_MAX_POINTS_Y; y--;)
                mesh_sum += Z_VALUES(x, y);
            const float zmean = mesh_sum / float(GRID_MAX_POINTS);

          #else

            // Find the low and high mesh values
            float lo_val = 100, hi_val = -100;
            for (uint8_t x = GRID_MAX_POINTS_X; x--;)
              for (uint8_t y = GRID_MAX_POINTS_Y; y--;) {
                const float z = Z_VALUES(x, y);
                NOMORE(lo_val, z);
                NOLESS(hi_val, z);
              }
            // Take the mean of the lowest and highest
            const float zmean = (lo_val + hi_val) / 2.0 + cval;

          #endif

          // If not very close to 0, adjust the mesh
          if (!NEAR_ZERO(zmean)) {
            set_bed_leveling_enabled(false);
            // Subtract the mean from all values
            for (uint8_t x = GRID_MAX_POINTS_X; x--;)
              for (uint8_t y = GRID_MAX_POINTS_Y; y--;)
                Z_VALUES(x, y) -= zmean;
            #if ENABLED(ABL_BILINEAR_SUBDIVISION)
              bed_level_virt_interpolate();
            #endif
          }

        #endif
      }

    }
    else if (to_enable || seenV) {
      SERIAL_ECHO_MSG("Invalid mesh.");
      goto EXIT_M420;
    }

  #endif // HAS_MESH

  // V to print the matrix or mesh
  if (seenV) {
    #if ABL_PLANAR
      planner.bed_level_matrix.debug(PSTR("Bed Level Correction Matrix:"));
    #else
      if (leveling_is_valid()) {
        #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
          print_bilinear_leveling_grid();
          #if ENABLED(ABL_BILINEAR_SUBDIVISION)
            print_bilinear_leveling_grid_virt();
          #endif
        #elif ENABLED(MESH_BED_LEVELING)
          SERIAL_ECHOLNPGM("Mesh Bed Level data:");
          mbl.report_mesh();
        #endif
      }
    #endif
  }

  #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
    if (parser.seen('Z')) set_z_fade_height(parser.value_linear_units(), false);
  #endif

  // Enable leveling if specified, or if previously active
  set_bed_leveling_enabled(to_enable);

  #if HAS_MESH
    EXIT_M420:
  #endif

  // Error if leveling failed to enable or reenable
  if (to_enable && !planner.leveling_active)
    SERIAL_ERROR_MSG(MSG_ERR_M420_FAILED);

  SERIAL_ECHO_START();
  SERIAL_ECHOPGM("Bed Leveling ");
  serialprintln_onoff(planner.leveling_active);

  #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
    SERIAL_ECHO_START();
    SERIAL_ECHOPGM("Fade Height ");
    if (planner.z_fade_height > 0.0)
      SERIAL_ECHOLN(planner.z_fade_height);
    else
      SERIAL_ECHOLNPGM(MSG_OFF);
  #endif

  // Report change in position
  if (memcmp(oldpos, current_position, sizeof(oldpos)))
    report_current_position();
}
示例#10
0
void GCodeParser::unknown_command_error() {
  SERIAL_ECHO_START();
  SERIAL_ECHOPAIR(MSG_UNKNOWN_COMMAND, command_ptr);
  SERIAL_CHAR('"');
  SERIAL_EOL();
}
示例#11
0
文件: M92.cpp 项目: teemuatlut/Marlin
/**
 * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, and E.
 *      (Follows the same syntax as G92)
 *
 *      With multiple extruders use T to specify which one.
 *
 *      If no argument is given print the current values.
 *
 *    With MAGIC_NUMBERS_GCODE:
 *      Use 'H' and/or 'L' to get ideal layer-height information.
 *      'H' specifies micro-steps to use. We guess if it's not supplied.
 *      'L' specifies a desired layer height. Nearest good heights are shown.
 */
void GcodeSuite::M92() {

  const int8_t target_extruder = get_target_extruder_from_command();
  if (target_extruder < 0) return;

  // No arguments? Show M92 report.
  if (!parser.seen("XYZE"
    #if ENABLED(MAGIC_NUMBERS_GCODE)
      "HL"
    #endif
  )) return report_M92(
    #if NUM_SERIAL > 1
      command_queue_port[cmd_queue_index_r],
    #endif
    true, target_extruder
  );

  LOOP_XYZE(i) {
    if (parser.seenval(axis_codes[i])) {
      if (i == E_AXIS) {
        const float value = parser.value_per_axis_units((AxisEnum)(E_AXIS_N(target_extruder)));
        if (value < 20) {
          float factor = planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] / value; // increase e constants if M92 E14 is given for netfab.
          #if HAS_CLASSIC_JERK && (DISABLED(JUNCTION_DEVIATION) || DISABLED(LIN_ADVANCE))
            planner.max_jerk[E_AXIS] *= factor;
          #endif
          planner.settings.max_feedrate_mm_s[E_AXIS_N(target_extruder)] *= factor;
          planner.max_acceleration_steps_per_s2[E_AXIS_N(target_extruder)] *= factor;
        }
        planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] = value;
      }
      else {
        planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
      }
    }
  }
  planner.refresh_positioning();

  #if ENABLED(MAGIC_NUMBERS_GCODE)
    #ifndef Z_MICROSTEPS
      #define Z_MICROSTEPS 16
    #endif
    const float wanted = parser.floatval('L');
    if (parser.seen('H') || wanted) {
      const uint16_t argH = parser.ushortval('H'),
                     micro_steps = argH ? argH : Z_MICROSTEPS;
      const float z_full_step_mm = micro_steps * planner.steps_to_mm[Z_AXIS];
      SERIAL_ECHO_START();
      SERIAL_ECHOPAIR("{ micro_steps:", micro_steps);
      SERIAL_ECHOPAIR(", z_full_step_mm:", z_full_step_mm);
      if (wanted) {
        const float best = uint16_t(wanted / z_full_step_mm) * z_full_step_mm;
        SERIAL_ECHOPGM(", best:[");
        SERIAL_ECHO(best);
        if (best != wanted) { SERIAL_CHAR(','); SERIAL_ECHO(best + z_full_step_mm); }
        SERIAL_CHAR(']');
      }
      SERIAL_ECHOLNPGM(" }");
    }
  #endif
}