diff --git a/Marlin/src/feature/backlash.cpp b/Marlin/src/feature/backlash.cpp index c6eb0d33f3..07fa7725a0 100644 --- a/Marlin/src/feature/backlash.cpp +++ b/Marlin/src/feature/backlash.cpp @@ -63,25 +63,25 @@ Backlash backlash; * spread over multiple segments, smoothing out artifacts even more. */ -void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const AxisBits dm, block_t * const block) { +void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block) { AxisBits changed_dir = last_direction_bits ^ dm; // Ignore direction change unless steps are taken in that direction #if DISABLED(CORE_BACKLASH) || ANY(MARKFORGED_XY, MARKFORGED_YX) - if (!da) changed_dir.x = false; - if (!db) changed_dir.y = false; - if (!dc) changed_dir.z = false; + if (!dist.a) changed_dir.x = false; + if (!dist.b) changed_dir.y = false; + if (!dist.c) changed_dir.z = false; #elif CORE_IS_XY - if (!(da + db)) changed_dir.x = false; - if (!(da - db)) changed_dir.y = false; - if (!dc) changed_dir.z = false; + if (!(dist.a + dist.b)) changed_dir.x = false; + if (!(dist.a - dist.b)) changed_dir.y = false; + if (!dist.c) changed_dir.z = false; #elif CORE_IS_XZ - if (!(da + dc)) changed_dir.x = false; - if (!(da - dc)) changed_dir.z = false; - if (!db) changed_dir.y = false; + if (!(dist.a + dist.c)) changed_dir.x = false; + if (!(dist.a - dist.c)) changed_dir.z = false; + if (!dist.b) changed_dir.y = false; #elif CORE_IS_YZ - if (!(db + dc)) changed_dir.y = false; - if (!(db - dc)) changed_dir.z = false; - if (!da) changed_dir.x = false; + if (!(dist.b + dist.c)) changed_dir.y = false; + if (!(dist.b - dist.c)) changed_dir.z = false; + if (!dist.a) changed_dir.x = false; #endif last_direction_bits ^= changed_dir; @@ -97,7 +97,15 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const const float f_corr = float(correction) / all_on; + bool changed = false; + float millimeters_delta = 0.0f; + #if IS_KINEMATIC + float sqr_stepper_space_mm = 0.0f; + #endif + LOOP_NUM_AXES(axis) { + TERN_(IS_KINEMATIC, sqr_stepper_space_mm += sq(dist[axis] * planner.mm_per_step[axis])); + if (distance_mm[axis]) { const bool forward = dm[axis]; @@ -107,8 +115,6 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const // Decide how much of the residual error to correct in this segment int32_t error_correction = residual_error[axis]; - if (forward == (error_correction < 0)) - error_correction = 0; // Don't take up any backlash in this segment, as it would subtract steps #ifdef BACKLASH_SMOOTHING_MM if (error_correction && smoothing_mm != 0) { @@ -118,9 +124,18 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const } #endif + // Don't correct backlash in the opposite direction to movement on this axis and for accuracy in + // updating block->millimeters, don't add too many steps to the movement on this axis + if (forward) + LIMIT(error_correction, 0, dist[axis]); + else + LIMIT(error_correction, dist[axis], 0); + // This correction reduces the residual error and adds block steps if (error_correction) { + changed = true; block->steps[axis] += ABS(error_correction); + millimeters_delta += dist[axis] * error_correction * sq(planner.mm_per_step[axis]); #if ENABLED(CORE_BACKLASH) switch (axis) { case CORE_AXIS_1: @@ -142,6 +157,11 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const } } } + + // If backlash correction steps were added modify block->millimeters with a linear approximation + // See https://github.com/MarlinFirmware/Marlin/pull/26392 + if (changed) + block->millimeters += TERN(IS_KINEMATIC, millimeters_delta * block->millimeters / sqr_stepper_space_mm, millimeters_delta / block->millimeters); } int32_t Backlash::get_applied_steps(const AxisEnum axis) { @@ -151,8 +171,8 @@ int32_t Backlash::get_applied_steps(const AxisEnum axis) { const int32_t residual_error_axis = residual_error[axis]; - // At startup it is assumed the last move was forwards. So the applied - // steps will always be a non-positive number. + // At startup it is assumed the last move was forward. + // So the applied steps will always be negative. if (forward) return -residual_error_axis; diff --git a/Marlin/src/feature/backlash.h b/Marlin/src/feature/backlash.h index 14c0fe20e3..593e51b9d0 100644 --- a/Marlin/src/feature/backlash.h +++ b/Marlin/src/feature/backlash.h @@ -72,7 +72,7 @@ class Backlash { return has_measurement(X_AXIS) || has_measurement(Y_AXIS) || has_measurement(Z_AXIS); } - static void add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const AxisBits dm, block_t * const block); + static void add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block); static int32_t get_applied_steps(const AxisEnum axis); #if ENABLED(BACKLASH_GCODE) diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index ece6b3a5d7..da8f8d8a52 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -2178,7 +2178,7 @@ bool Planner::_populate_block( * A correction function is permitted to add steps to an axis, it * should *never* remove steps! */ - TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(dist.a, dist.b, dist.c, dm, block)); + TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(dist, dm, block)); } TERN_(HAS_EXTRUDERS, block->steps.e = esteps); diff --git a/README.md b/README.md index bdd80b4911..103c20011d 100644 --- a/README.md +++ b/README.md @@ -70,14 +70,22 @@ There is a *MarlinSimulator.exe* file provided to test out for yourself. It simu To create your own MarlinSimulator with you own build, start by changing in Configuration.h **MOTHERBOARD** to *BOARD_SIMULATED*, also disable `ENDSTOP_INTERRUPTS_FEATURE` and `PROUI_EX`, and then in platformio.ini **default_envs =** change to *simulator_windows*. The MarlinSimulator can only compile for Manual Mesh Bed Leveling for now, so make sure your configuration is set for `MESH_BED_LEVELING`. -Then you have to extract **SDL2-devel-2.28.0-mingw.zip** from /**docs**. To install SDL, navigate to the SDL2 directory in *MSYS2 MINGW64* terminal and type +Then you have to extract **SDL2-devel-2.28.4-mingw.zip** from /**docs**. To install SDL, navigate to the SDL2 directory in *MSYS2 MINGW64* terminal (Run as Administrator)ls and type: +> +> make cross +> +If you receive an error, then try the following: +> +> make install-package arch=x86_64-w64-mingw32 prefix=/usr +> +You can use instead a 32-bit version by passing: > > make native > -64-bit files are in \x86_64-w64-mingw32. Then **copy** the contents of ~\SDL2-2.28.2\x86_64-w64-mingw32\include\SDL2\\* into ~\.pio\libdeps\simulator_windows\\**imgui** +32-bit files are in \i686-w64-mingw32 if you use `make native`. Then **copy** the contents of ~\SDL2-2.28.4\x86_64-w64-mingw32\include\SDL2\\* into ~\.pio\libdeps\simulator_windows\\**imgui** -OR- -Copy the just folder ~\SDL2-2.28.2\x86_64-w64-mingw32\include\\**SDL2** into the directory ~\libdeps\\*simulator_windows* +Copy the just folder ~\SDL2-2.28.4\x86_64-w64-mingw32\include\\**SDL2** into the directory ~\libdeps\\*simulator_windows* You may have to first Build so the directory can be created. Once all that is done, just build like you would normally and *MarlinSimulator.exe* will be created. diff --git a/buildroot/share/PlatformIO/scripts/random-bin.py b/buildroot/share/PlatformIO/scripts/random-bin.py index 3e3b6d03c1..8c50540d27 100644 --- a/buildroot/share/PlatformIO/scripts/random-bin.py +++ b/buildroot/share/PlatformIO/scripts/random-bin.py @@ -10,3 +10,8 @@ env = DefaultEnvironment() Import("env") env['PROGNAME'] = datetime.now().strftime("firmware-%Y%m%d-%H%M%S") + def name_target(target, source, env): + print("FIRMWARE ELF: %s.elf" % env['PROGNAME']) + print("FIRMWARE BIN: %s.bin" % env['PROGNAME']) + import marlin + marlin.add_post_action(name_target) \ No newline at end of file diff --git a/buildroot/share/PlatformIO/scripts/schema.py b/buildroot/share/PlatformIO/scripts/schema.py index afac7b5d27..535a8f671e 100644 --- a/buildroot/share/PlatformIO/scripts/schema.py +++ b/buildroot/share/PlatformIO/scripts/schema.py @@ -85,7 +85,8 @@ class Parse: NORMAL = 0 # No condition yet BLOCK_COMMENT = 1 # Looking for the end of the block comment EOL_COMMENT = 2 # EOL comment started, maybe add the next comment? - GET_SENSORS = 3 # Gathering temperature sensor options + SLASH_COMMENT = 3 # Block-like comment, starting with aligned // + GET_SENSORS = 4 # Gathering temperature sensor options ERROR = 9 # Syntax error # List of files to process, with shorthand @@ -107,6 +108,7 @@ class Parse: line_number = 0 # Counter for the line number of the file conditions = [] # Create a condition stack for the current file comment_buff = [] # A temporary buffer for comments + prev_comment = '' # Copy before reset for an EOL comment options_json = '' # A buffer for the most recent options JSON found eol_options = False # The options came from end of line, so only apply once join_line = False # A flag that the line should be joined with the previous one @@ -143,9 +145,13 @@ class Parse: if not defmatch and the_line.startswith('//'): comment_buff.append(the_line[2:].strip()) else: - last_added_ref['comment'] = ' '.join(comment_buff) - comment_buff = [] state = Parse.NORMAL + cline = ' '.join(comment_buff) + comment_buff = [] + if cline != '': + # A (block or slash) comment was already added + cfield = 'notes' if 'comment' in last_added_ref else 'comment' + last_added_ref[cfield] = cline def use_comment(c, opt, sec, bufref): if c.startswith(':'): # If the comment starts with : then it has magic JSON @@ -162,6 +168,15 @@ def use_comment(c, opt, sec, bufref): bufref.append(c) return opt, sec + # For slash comments, capture consecutive slash comments. + # The comment will be applied to the next #define. + if state == Parse.SLASH_COMMENT: + if not defmatch and the_line.startswith('//'): + use_comment(the_line[2:].strip(), options_json, section, comment_buff) + continue + else: + state = Parse.NORMAL + # In a block comment, capture lines up to the end of the comment. # Assume nothing follows the comment closure. if state in (Parse.BLOCK_COMMENT, Parse.GET_SENSORS): @@ -178,14 +193,14 @@ def use_comment(c, opt, sec, bufref): state = Parse.NORMAL # Strip the leading '*' from block comments - if cline.startswith('*'): cline = cline[1:].strip() + cline = re.sub(r'^\* ?', '', cline) # Collect temperature sensors if state == Parse.GET_SENSORS: sens = re.match(r'^(-?\d+)\s*:\s*(.+)$', cline) if sens: s2 = sens[2].replace("'","''") - options_json += f"{sens[1]}:'{s2}', " + options_json += f"{sens[1]}:'{sens[1]} - {s2}', " elif state == Parse.BLOCK_COMMENT: @@ -216,15 +231,19 @@ def use_comment(c, opt, sec, bufref): # Comment after a define may be continued on the following lines if defmatch != None and cpos > 10: state = Parse.EOL_COMMENT + prev_comment = '\n'.join(comment_buff) comment_buff = [] + else: + state = Parse.SLASH_COMMENT # Process the start of a new comment if cpos != -1: + comment_buff = [] cline, line = line[cpos+2:].strip(), line[:cpos].strip() if state == Parse.BLOCK_COMMENT: # Strip leading '*' from block comments - if cline.startswith('*'): cline = cline[1:].strip() + cline = re.sub(r'^\* ?', '', cline) else: # Expire end-of-line options after first use if cline.startswith(':'): eol_options = True @@ -320,7 +339,7 @@ def atomize(s): if value_type != '': define_info['type'] = value_type # Join up accumulated conditions with && - if conditions: define_info['requires'] = ' && '.join(sum(conditions, [])) + if conditions: define_info['requires'] = '(' + ') && ('.join(sum(conditions, [])) + ')' # If the comment_buff is not empty, add the comment to the info if comment_buff: diff --git a/docs/SDL2-devel-2.28.2-mingw.zip b/docs/SDL2-devel-2.28.4-mingw.zip similarity index 68% rename from docs/SDL2-devel-2.28.2-mingw.zip rename to docs/SDL2-devel-2.28.4-mingw.zip index 0fc9c3ba4c..45f0e713e0 100644 Binary files a/docs/SDL2-devel-2.28.2-mingw.zip and b/docs/SDL2-devel-2.28.4-mingw.zip differ diff --git a/ini/stm32f4.ini b/ini/stm32f4.ini index ba59a87883..5a233cbaec 100644 --- a/ini/stm32f4.ini +++ b/ini/stm32f4.ini @@ -745,7 +745,6 @@ build_flags = ${stm32_variant.build_flags} -DSTEP_TIMER_IRQ_PRIO=0 -Wl,--no-warn-rwx-segment extra_scripts = ${stm32_variant.extra_scripts} - pre:buildroot/share/PlatformIO/scripts/random-bin.py upload_protocol = stlink debug_tool = stlink diff --git a/ini/stm32g0.ini b/ini/stm32g0.ini index e821a18258..75fb4f497b 100644 --- a/ini/stm32g0.ini +++ b/ini/stm32g0.ini @@ -61,7 +61,6 @@ build_flags = ${stm32_variant.build_flags} -DSTEP_TIMER_IRQ_PRIO=0 -Wl,--no-warn-rwx-segment extra_scripts = ${stm32_variant.extra_scripts} - pre:buildroot/share/PlatformIO/scripts/random-bin.py upload_protocol = stlink debug_tool = stlink diff --git a/platformio.ini b/platformio.ini index 40d5855310..200ee85faf 100644 --- a/platformio.ini +++ b/platformio.ini @@ -68,6 +68,7 @@ extra_scripts = pre:buildroot/share/PlatformIO/scripts/common-dependencies.py pre:buildroot/share/PlatformIO/scripts/common-cxxflags.py pre:buildroot/share/PlatformIO/scripts/preflight-checks.py + pre:buildroot/share/PlatformIO/scripts/random-bin.py post:buildroot/share/PlatformIO/scripts/common-dependencies-post.py lib_deps = default_src_filter = + - - @@ -148,15 +149,14 @@ default_src_filter = + - - # Default values apply to all 'env:' prefixed environments # [env] -framework = arduino -extra_scripts = ${common.extra_scripts} -build_flags = ${common.build_flags} -board_build.rename = firmware-{date}-{time}.bin -lib_deps = ${common.lib_deps} -monitor_speed = 250000 -monitor_eol = LF -monitor_echo = yes -monitor_filters = colorize, time, send_on_enter +framework = arduino +extra_scripts = ${common.extra_scripts} +build_flags = ${common.build_flags} +lib_deps = ${common.lib_deps} +monitor_speed = 250000 +monitor_eol = LF +monitor_echo = yes +monitor_filters = colorize, time, send_on_enter # # Just print the dependency tree