🚸 Enable G92.9 with rotational axes (#26174)

- Supporting axes that can rotate forever.
This commit is contained in:
DerAndere 2024-03-02 04:16:39 +01:00 committed by GitHub
parent d609bb4671
commit c8d51c2723
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 29 additions and 14 deletions

View file

@ -42,7 +42,7 @@
* G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E].
* G92.1 : Zero XYZ Workspace Offsets (so the reported position = the native position). * G92.1 : Zero XYZ Workspace Offsets (so the reported position = the native position).
* *
* With POWER_LOSS_RECOVERY: * With POWER_LOSS_RECOVERY or with AXISn_ROTATES:
* G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E].
*/ */
void GcodeSuite::G92() { void GcodeSuite::G92() {
@ -67,7 +67,7 @@ void GcodeSuite::G92() {
break; break;
#endif #endif
#if ENABLED(POWER_LOSS_RECOVERY) #if ANY(POWER_LOSS_RECOVERY, HAS_ROTATIONAL_AXES)
case 9: // G92.9 - Set Current Position directly (like Marlin 1.0) case 9: // G92.9 - Set Current Position directly (like Marlin 1.0)
LOOP_LOGICAL_AXES(i) { LOOP_LOGICAL_AXES(i) {
if (parser.seenval(AXIS_CHAR(i))) { if (parser.seenval(AXIS_CHAR(i))) {

View file

@ -3279,7 +3279,7 @@
#endif #endif
// Add commands that need sub-codes to this list // Add commands that need sub-codes to this list
#if ANY(G38_PROBE_TARGET, CNC_COORDINATE_SYSTEMS, POWER_LOSS_RECOVERY) #if ANY(G38_PROBE_TARGET, CNC_COORDINATE_SYSTEMS, POWER_LOSS_RECOVERY, HAS_ROTATIONAL_AXES)
#define USE_GCODE_SUBCODES 1 #define USE_GCODE_SUBCODES 1
#endif #endif

View file

@ -23,6 +23,7 @@
#include "../inc/MarlinConfig.h" #include "../inc/MarlinConfig.h"
#include "../MarlinCore.h" // for printingIsPaused #include "../MarlinCore.h" // for printingIsPaused
#include "../gcode/parser.h" // for axis_is_rotational, using_inch_units
#if LED_POWEROFF_TIMEOUT > 0 || ALL(HAS_WIRED_LCD, PRINTER_EVENT_LEDS) || (HAS_BACKLIGHT_TIMEOUT && defined(NEOPIXEL_BKGD_INDEX_FIRST)) #if LED_POWEROFF_TIMEOUT > 0 || ALL(HAS_WIRED_LCD, PRINTER_EVENT_LEDS) || (HAS_BACKLIGHT_TIMEOUT && defined(NEOPIXEL_BKGD_INDEX_FIRST))
#include "../feature/leds/leds.h" #include "../feature/leds/leds.h"
@ -824,6 +825,13 @@ void MarlinUI::init() {
const feedRate_t fr_mm_s = (axis < LOGICAL_AXES) ? manual_feedrate_mm_s[axis] : XY_PROBE_FEEDRATE_MM_S; const feedRate_t fr_mm_s = (axis < LOGICAL_AXES) ? manual_feedrate_mm_s[axis] : XY_PROBE_FEEDRATE_MM_S;
/**
* For a rotational axis apply the "inch" to "mm" conversion factor. This mimics behaviour of the G-code G1
* (see get_destination_from_command). For moves involving only rotational axes, the planner will convert
* back to the feedrate in degrees-per-time unit.
*/
const feedRate_t fr = parser.axis_is_rotational(axis) && parser.using_inch_units() ? IN_TO_MM(fr_mm_s) : fr_mm_s;
#if IS_KINEMATIC #if IS_KINEMATIC
#if HAS_MULTI_EXTRUDER #if HAS_MULTI_EXTRUDER
@ -850,13 +858,13 @@ void MarlinUI::init() {
// previous invocation is being blocked. Modifications to offset shouldn't be made while // previous invocation is being blocked. Modifications to offset shouldn't be made while
// processing is true or the planner will get out of sync. // processing is true or the planner will get out of sync.
processing = true; processing = true;
prepare_internal_move_to_destination(fr_mm_s); // will set current_position from destination prepare_internal_move_to_destination(fr); // will set current_position from destination
processing = false; processing = false;
#else #else
// For Cartesian / Core motion simply move to the current_position // For Cartesian / Core motion simply move to the current_position
planner.buffer_line(current_position, fr_mm_s, planner.buffer_line(current_position, fr,
TERN_(MULTI_E_MANUAL, axis == E_AXIS ? e_index :) active_extruder TERN_(MULTI_E_MANUAL, axis == E_AXIS ? e_index :) active_extruder
); );

View file

@ -78,8 +78,8 @@ void lcd_move_axis(const AxisEnum axis) {
if (ui.should_draw()) { if (ui.should_draw()) {
MenuEditItemBase::itemIndex = axis; MenuEditItemBase::itemIndex = axis;
const float pos = ui.manual_move.axis_value(axis); const float pos = ui.manual_move.axis_value(axis);
if (parser.using_inch_units()) { if (parser.using_inch_units() && !parser.axis_is_rotational(axis)) {
const float imp_pos = LINEAR_UNIT(pos); const float imp_pos = parser.per_axis_value(axis, pos);
MenuEditItemBase::draw_edit_screen(GET_TEXT_F(MSG_MOVE_N), ftostr63(imp_pos)); MenuEditItemBase::draw_edit_screen(GET_TEXT_F(MSG_MOVE_N), ftostr63(imp_pos));
} }
else else

View file

@ -1153,10 +1153,13 @@ float get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXES, bool
#if HAS_ROTATIONAL_AXES #if HAS_ROTATIONAL_AXES
if (UNEAR_ZERO(distance_sqr)) { if (UNEAR_ZERO(distance_sqr)) {
// Move involves only rotational axes. Calculate angular distance in accordance with LinuxCNC // Move involves no linear axes. Calculate angular distance in accordance with LinuxCNC
is_cartesian_move = false;
distance_sqr = ROTATIONAL_AXIS_GANG(sq(diff.i), + sq(diff.j), + sq(diff.k), + sq(diff.u), + sq(diff.v), + sq(diff.w)); distance_sqr = ROTATIONAL_AXIS_GANG(sq(diff.i), + sq(diff.j), + sq(diff.k), + sq(diff.u), + sq(diff.v), + sq(diff.w));
} }
if (!UNEAR_ZERO(distance_sqr)) {
// Move involves rotational axes, not just the extruder
is_cartesian_move = false;
}
#endif #endif
#endif #endif

View file

@ -2079,11 +2079,11 @@ bool Planner::_populate_block(
/** /**
* This part of the code calculates the total length of the movement. * This part of the code calculates the total length of the movement.
* For cartesian bots, the X_AXIS is the real X movement and same for Y_AXIS. * For cartesian bots, the distance along the X axis equals the X_AXIS joint displacement and same holds true for Y_AXIS.
* But for corexy bots, that is not true. The "X_AXIS" and "Y_AXIS" motors (that should be named to A_AXIS * But for geometries like CORE_XY that is not true. For these machines we need to create 2 additional variables, named X_HEAD and Y_HEAD, to store the displacent of the head along the X and Y axes in a cartesian coordinate system.
* and B_AXIS) cannot be used for X and Y length, because A=X+Y and B=X-Y. * The displacement of the head along the axes of the cartesian coordinate system has to be calculated from "X_AXIS" and "Y_AXIS" (should be renamed to A_JOINT and B_JOINT)
* So we need to create other 2 "AXIS", named X_HEAD and Y_HEAD, meaning the real displacement of the Head. * displacements in joints space using forward kinematics (A=X+Y and B=X-Y in the case of CORE_XY).
* Having the real displacement of the head, we can calculate the total movement length and apply the desired speed. * Next we can calculate the total movement length and apply the desired speed.
*/ */
struct DistanceMM : abce_float_t { struct DistanceMM : abce_float_t {
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
@ -2308,6 +2308,10 @@ bool Planner::_populate_block(
// Example 2: At 120°/s a 60° move involving only rotational axes takes 0.5s. So this will give 2.0. // Example 2: At 120°/s a 60° move involving only rotational axes takes 0.5s. So this will give 2.0.
float inverse_secs = inverse_millimeters * ( float inverse_secs = inverse_millimeters * (
#if ALL(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) #if ALL(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT)
/**
* Workaround for premature feedrate conversion
* from in/s to mm/s by get_distance_from_command.
*/
cartesian_move ? fr_mm_s : LINEAR_UNIT(fr_mm_s) cartesian_move ? fr_mm_s : LINEAR_UNIT(fr_mm_s)
#else #else
fr_mm_s fr_mm_s