diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 2b1ae1f1fe..562cddbaa0 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -78,6 +78,14 @@ void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P( void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); } +void serial_offset(const_float_t v, const uint8_t sp/*=0*/) { + if (v == 0 && sp == 1) + SERIAL_CHAR(' '); + else if (v > 0 || (v == 0 && sp == 2)) + SERIAL_CHAR('+'); + SERIAL_DECIMAL(v); +} + void serial_ternary(const bool onoff, FSTR_P const pre, FSTR_P const on, FSTR_P const off, FSTR_P const post/*=nullptr*/) { if (pre) serial_print(pre); serial_print(onoff ? on : off); diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index aee4d4d43d..98e82b6d72 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -345,6 +345,7 @@ void serialprint_onoff(const bool onoff); void serialprintln_onoff(const bool onoff); void serialprint_truefalse(const bool tf); void serial_spaces(uint8_t count); +void serial_offset(const_float_t v, const uint8_t sp=0); // For v==0 draw space (sp==1) or plus (sp==2) void print_bin(const uint16_t val); void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr); diff --git a/Marlin/src/core/utility.cpp b/Marlin/src/core/utility.cpp index 19e7626744..59e59d4cb7 100644 --- a/Marlin/src/core/utility.cpp +++ b/Marlin/src/core/utility.cpp @@ -126,10 +126,8 @@ void safe_delay(millis_t ms) { #if ABL_PLANAR SERIAL_ECHOPGM("ABL Adjustment"); LOOP_LINEAR_AXES(a) { - const float v = planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]; SERIAL_CHAR(' ', AXIS_CHAR(a)); - if (v > 0) SERIAL_CHAR('+'); - SERIAL_DECIMAL(v); + serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]); } #else #if ENABLED(AUTO_BED_LEVELING_UBL) diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index 964f1123fe..c162062f86 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp @@ -213,8 +213,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { else if (isnan(f)) SERIAL_ECHOF(human ? F(" . ") : F("NAN")); else if (human || csv) { - if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0) - SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits + if (human && f >= 0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0) + SERIAL_DECIMAL(f); // Positive: 5 digits, Negative: 6 digits } if (csv && i < (GRID_MAX_POINTS_X) - 1) SERIAL_CHAR('\t'); diff --git a/Marlin/src/feature/mixing.cpp b/Marlin/src/feature/mixing.cpp index 9ebc90127f..b1a069e320 100644 --- a/Marlin/src/feature/mixing.cpp +++ b/Marlin/src/feature/mixing.cpp @@ -63,7 +63,7 @@ void Mixer::normalize(const uint8_t tool_index) { #ifdef MIXER_NORMALIZER_DEBUG SERIAL_ECHOPGM("Mixer: Old relation : [ "); MIXER_STEPPER_LOOP(i) { - SERIAL_ECHO_F(collector[i] / csum, 3); + SERIAL_DECIMAL(collector[i] / csum); SERIAL_CHAR(' '); } SERIAL_ECHOLNPGM("]"); diff --git a/Marlin/src/feature/x_twist.cpp b/Marlin/src/feature/x_twist.cpp index 8910091239..b5ad25cba8 100644 --- a/Marlin/src/feature/x_twist.cpp +++ b/Marlin/src/feature/x_twist.cpp @@ -36,8 +36,8 @@ void XATC::reset() { constexpr float xzo[] = XATC_Z_OFFSETS; static_assert(COUNT(xzo) == XATC_MAX_POINTS, "XATC_Z_OFFSETS is the wrong size."); COPY(z_offset, xzo); - xatc.spacing = (probe.max_x() - probe.min_x()) / (XATC_MAX_POINTS - 1); - xatc.start = probe.min_x(); + start = probe.min_x(); + spacing = (probe.max_x() - start) / (XATC_MAX_POINTS - 1); enabled = true; } @@ -45,14 +45,10 @@ void XATC::print_points() { SERIAL_ECHOLNPGM(" X-Twist Correction:"); LOOP_L_N(x, XATC_MAX_POINTS) { SERIAL_CHAR(' '); - if (!isnan(z_offset[x])) { - if (z_offset[x] >= 0) SERIAL_CHAR('+'); - SERIAL_ECHO_F(z_offset[x], 3); - } - else { - LOOP_L_N(i, 6) - SERIAL_CHAR(i ? '=' : ' '); - } + if (!isnan(z_offset[x])) + serial_offset(z_offset[x]); + else + LOOP_L_N(i, 6) SERIAL_CHAR(i ? '=' : ' '); } SERIAL_EOL(); } @@ -63,8 +59,7 @@ float XATC::compensation(const xy_pos_t &raw) { if (!enabled) return 0; if (NEAR_ZERO(spacing)) return 0; float t = (raw.x - start) / spacing; - int i = FLOOR(t); - LIMIT(i, 0, XATC_MAX_POINTS - 2); + const int i = constrain(FLOOR(t), 0, XATC_MAX_POINTS - 2); t -= i; return lerp(t, z_offset[i], z_offset[i + 1]); } diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index a4b9aec01b..506f367947 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -98,8 +98,7 @@ void ac_cleanup(TERN_(HAS_MULTI_HOTEND, const uint8_t old_tool_index)) { void print_signed_float(FSTR_P const prefix, const_float_t f) { SERIAL_ECHOPGM(" "); SERIAL_ECHOF(prefix, AS_CHAR(':')); - if (f >= 0) SERIAL_CHAR('+'); - SERIAL_ECHO_F(f, 2); + serial_offset(f); } /** diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index a150aca41d..6e331c1273 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -1195,6 +1195,11 @@ private: static void M1000(); #endif + #if ENABLED(X_AXIS_TWIST_COMPENSATION) + static void M423(); + static void M423_report(const bool forReplay=true); + #endif + #if ENABLED(SDSUPPORT) static void M1001(); #endif diff --git a/Marlin/src/gcode/probe/M423.cpp b/Marlin/src/gcode/probe/M423.cpp new file mode 100644 index 0000000000..fde5aaaf87 --- /dev/null +++ b/Marlin/src/gcode/probe/M423.cpp @@ -0,0 +1,99 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * M423.cpp - X-Axis Twist Compensation + */ + +#include "../../inc/MarlinConfig.h" + +#if ENABLED(X_AXIS_TWIST_COMPENSATION) + +#include "../gcode.h" +#include "../../feature/x_twist.h" +#include "../../module/probe.h" + +/** + * M423: Set a Z offset for X-Twist (added to the mesh on future G29). + * M423 [R] [A] [I] [X Z] + * + * R - Reset the twist compensation data + * A - Set the X twist starting X position + * E - Set the X twist ending X position + * I - Set the X twist X-spacing directly + * X - Index of a Z value in the list + * Z - A Z value to set + */ +void GcodeSuite::M423() { + + bool do_report = true; + float new_spacing = 0; + + if (parser.seen_test('R')) { + do_report = false; + xatc.reset(); + } + if (parser.seenval('A')) { + do_report = false; + xatc.start = parser.value_float(); + new_spacing = (probe.max_x() - xatc.start) / (XATC_MAX_POINTS - 1); + } + if (parser.seenval('E')) { + do_report = false; + new_spacing = (parser.value_float() - xatc.start) / (XATC_MAX_POINTS - 1); + } + else if (parser.seenval('I')) { + do_report = false; + new_spacing = parser.value_float(); + } + + if (new_spacing) xatc.spacing = new_spacing; + + if (parser.seenval('X')) { + do_report = false; + const int8_t x = parser.value_int(); + if (!WITHIN(x, 0, XATC_MAX_POINTS - 1)) + SERIAL_ECHOLNPGM("?(X) out of range (0..", XATC_MAX_POINTS - 1, ")."); + else { + if (parser.seenval('Z')) + xatc.z_offset[x] = parser.value_linear_units(); + else + SERIAL_ECHOLNPGM("?(Z) required."); + } + } + + if (do_report) M423_report(); + +} + +void GcodeSuite::M423_report(const bool forReplay/*=true*/) { + report_heading(forReplay, F("X-Twist Correction")); + SERIAL_ECHOLNPGM(" M423 A", xatc.start, " I", xatc.spacing); + LOOP_L_N(x, XATC_MAX_POINTS) { + const float z = xatc.z_offset[x]; + SERIAL_ECHOPGM(" M423 X", x, " Z"); + serial_offset(isnan(z) ? 0 : z); + SERIAL_EOL(); + } +} + +#endif // X_AXIS_TWIST_COMPENSATION diff --git a/Marlin/src/lcd/menu/menu_x_twist.cpp b/Marlin/src/lcd/menu/menu_x_twist.cpp index 93f8de07ad..ce46053dfc 100644 --- a/Marlin/src/lcd/menu/menu_x_twist.cpp +++ b/Marlin/src/lcd/menu/menu_x_twist.cpp @@ -153,7 +153,7 @@ void xatc_wizard_goto_next_point() { measured_z = probe.probe_at_point(x, XATC_Y_POSITION, PROBE_PT_STOW); xatc.set_enabled(true); current_position += probe.offset_xy; - current_position.z = XATC_START_Z - probe.offset.z + measured_z; + current_position.z = (XATC_START_Z) - probe.offset.z + measured_z; line_to_current_position(MMM_TO_MMS(XY_PROBE_FEEDRATE)); ui.wait_for_move = false; } diff --git a/Marlin/src/libs/vector_3.cpp b/Marlin/src/libs/vector_3.cpp index 614d2121b8..02945fe687 100644 --- a/Marlin/src/libs/vector_3.cpp +++ b/Marlin/src/libs/vector_3.cpp @@ -141,8 +141,7 @@ void matrix_3x3::debug(FSTR_P const title) { if (title) SERIAL_ECHOLNF(title); LOOP_L_N(i, 3) { LOOP_L_N(j, 3) { - if (vectors[i][j] >= 0.0) SERIAL_CHAR('+'); - SERIAL_ECHO_F(vectors[i][j], 6); + serial_offset(vectors[i][j], 2); SERIAL_CHAR(' '); } SERIAL_EOL(); diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index 2b2e335565..6eb17d5d2e 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -277,7 +277,7 @@ typedef struct SettingsDataStruct { // X_AXIS_TWIST_COMPENSATION // #if ENABLED(X_AXIS_TWIST_COMPENSATION) - XATC xatc; // TBD + XATC xatc; // M423 X Z #endif // @@ -901,7 +901,9 @@ void MarlinSettings::postprocess() { // #if ENABLED(X_AXIS_TWIST_COMPENSATION) _FIELD_TEST(xatc); - EEPROM_WRITE(xatc); + EEPROM_WRITE(xatc.spacing); + EEPROM_WRITE(xatc.start); + EEPROM_WRITE(xatc.z_offset); #endif // @@ -1809,7 +1811,10 @@ void MarlinSettings::postprocess() { // X Axis Twist Compensation // #if ENABLED(X_AXIS_TWIST_COMPENSATION) - EEPROM_READ(xatc); + _FIELD_TEST(xatc); + EEPROM_READ(xatc.spacing); + EEPROM_READ(xatc.start); + EEPROM_READ(xatc.z_offset); #endif // @@ -3337,14 +3342,13 @@ void MarlinSettings::reset() { #endif - // TODO: Create G-code for settings - //#if ENABLED(X_AXIS_TWIST_COMPENSATION) - // CONFIG_ECHO_START(); - // xatc.print_points(); - //#endif - #endif // HAS_LEVELING + // + // X Axis Twist Compensation + // + TERN_(X_AXIS_TWIST_COMPENSATION, gcode.M423_report(forReplay)); + // // Editable Servo Angles // diff --git a/ini/features.ini b/ini/features.ini index 48b6a2c47a..8e45b71e42 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -98,7 +98,7 @@ USB_FLASH_DRIVE_SUPPORT = src_filter=+ + AUTO_BED_LEVELING_BILINEAR = src_filter=+ AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+ -X_AXIS_TWIST_COMPENSATION = src_filter=+ + +X_AXIS_TWIST_COMPENSATION = src_filter=+ + + MESH_BED_LEVELING = src_filter=+ + AUTO_BED_LEVELING_UBL = src_filter=+ + UBL_HILBERT_CURVE = src_filter=+ diff --git a/platformio.ini b/platformio.ini index 9b64bdd377..0e50da2b73 100644 --- a/platformio.ini +++ b/platformio.ini @@ -150,7 +150,7 @@ default_src_filter = + - - + - - - - - - + - - - - -