Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Axis Backlash / Hysteresis Compensation (Code is Ready) #7579

Closed
Phaelz opened this issue Aug 28, 2017 · 23 comments

Comments

Projects
None yet
8 participants
@Phaelz
Copy link

commented Aug 28, 2017

First of all, I am immensely grateful for everyone that works for this community. I really wish I had the skills to program like you! I develop some 3D printers and Marlin was present from the beginning. I try my best to help this thing go forward! Here we go:

This was referenced in issue #3664 .

Why doesn't official Marlin have backlash compensation?

Lawsy from soolidoodle forums uploaded this to their fw.

I think Neil Martin was the guy who wrote these lines back in 2013.

http://www.soliforum.com/topic/313/hysteresis-fix/

The idea is that we have hysteresis on the movements of X and Y axis on printers based on belts and a little play/backlash in the nut on Z axis.

It's very visible when printing an object that is smooth on several layers and then have lots of artifacts on a layer. After lots of retractions and jumps, the rest of the layer become misaligned.

This backlash/hysteresis compensation would add movement to the planner ONLY if there is direction change on the axis. This would compensate belt stretching and play on pulleys. On the Z axis, it would be the same thing. When there is change in direction, a few steps are only used to compensate for this hysteresis and the movement would be made with real moving steps.

I think the code is ready for implementation. It's only necessary to adapt to the new variable names.

There are some topics on other forums about play, backlash, hysteresis and wobble on axis movement.

http://www.soliforum.com/topic/2342/backlash-hysterisis-and-wobble-an-exploration-of-the-topic/

Some members measured the positioning accuracy and they stated that this backlash is somewhat constant (there is a standard deviation around a fixed number). The code would always add a fixed distance on the planner in moves with direction change from the previous one. This distance would be in Configuration.h so the user could compensate for X, Y, Z and E axis (if the extruder is geared).

Edit: I've just found this #247
It seems that Neil stopped working on the code, but Rincewind from soliforum debugged it and perfected it. It is working flawlessly since 2013.

@Phaelz Phaelz changed the title [FR] Axis Backlash / Hysteresis Compensation [FR] Axis Backlash / Hysteresis Compensation (Code is Ready) Aug 28, 2017

@Phaelz

This comment has been minimized.

Copy link
Author

commented Aug 28, 2017

I'm trying to update my marlin with this new code...

Edit: after a few hours of work... I was massacred by the code hahahaha it seems a lot of functions and variables changed since that code was written. I could get nothing done.

Since this topic is kinda old, I know some people will come and say 3D printers don't suffer from backlash on belt systems, etc... BUT, several components of positioning systems have inherent backlash, even the stepper motors. When you add everything together, even a very well built machine will present some slight layer misalignment. I checked A LOT of 3D printers, from several manufacturers and all of theose from the desktop segment have backlash.
The only printers I didn't see layer misaligment were from Stratasys and cost more than 80k USD.

If we could compensante, even a little bit of the hysteresis caused by backlash it would improve repeatability and print quality significantly!

@Phaelz Phaelz referenced this issue Nov 9, 2017

Closed

Hysteresis #3664

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Feb 9, 2018

Why doesn't official Marlin have backlash compensation?

No one has implemented it yet, and demand is very low.

The implementation would need to be done in a way that is transparent to the high-level movement system. Essentially, anytime an axis reverses direction, extra steps are added in the new direction. This must be done at a very low level, somewhere between the Planner and the Stepper code. It would apply to steppers (A, B, C), not to cartesian axes (X, Y, Z).

@hectori4502

This comment has been minimized.

Copy link

commented Feb 23, 2018

I test the code from: (for the version 1.1.5)
marcio-ao commented on 14 Nov 2017

Here is an update on the backlash compensation code:

#define AXIS_BACKLASH {0.00, 0.00, 0.35, 0}

#if defined(AXIS_BACKLASH)
    #define SIGN(v) ((v < 0) ? -1.0 : 1.0)
    #define AXIS_BACKLASH_CORRECTION \
        { \
            static const float backlash[NUM_AXIS] = AXIS_BACKLASH; \
            static uint8_t last_direction_bits; \
            static bool is_correction = false; \
            if(!is_correction) { \
                uint8_t changed_dir = last_direction_bits ^ dm; \
                /* Ignore direction change if no steps are taken in that direction */ \
                if(da == 0) CBI(changed_dir, X_AXIS); \
                if(db == 0) CBI(changed_dir, Y_AXIS); \
                if(dc == 0) CBI(changed_dir, Z_AXIS); \
                if(de == 0) CBI(changed_dir, E_AXIS); \
                last_direction_bits ^= changed_dir; \
                /* When there is motion in an opposing direction, apply the backlash correction */ \
                if(changed_dir) { \
                    long saved_position[NUM_AXIS] = { 0 }; \
                    COPY(saved_position, position); \
                    const long x_backlash = TEST(changed_dir, X_AXIS) ? backlash[X_AXIS] * axis_steps_per_mm[X_AXIS] * SIGN(da) : 0; \
                    const long y_backlash = TEST(changed_dir, Y_AXIS) ? backlash[Y_AXIS] * axis_steps_per_mm[Y_AXIS] * SIGN(db) : 0; \
                    const long z_backlash = TEST(changed_dir, Z_AXIS) ? backlash[Z_AXIS] * axis_steps_per_mm[Z_AXIS] * SIGN(dc) : 0; \
                    const long e_backlash = TEST(changed_dir, E_AXIS) ? backlash[E_AXIS] * axis_steps_per_mm[E_AXIS] * SIGN(de) : 0; \
                    is_correction = true; /* Avoid infinite recursion */ \
                    _buffer_line( \
                        (position[X_AXIS] + x_backlash)/axis_steps_per_mm[X_AXIS], \
                        (position[Y_AXIS] + y_backlash)/axis_steps_per_mm[Y_AXIS], \
                        (position[Z_AXIS] + z_backlash)/axis_steps_per_mm[Z_AXIS], \
                        (position[E_AXIS] + e_backlash)/axis_steps_per_mm[E_AXIS_N], \
                        fr_mm_s, extruder \
                    ); \
                    is_correction = false; \
                    COPY(position, saved_position); \
                } \
            } \
        }
#else
    #define AXIS_BACKLASH_CORRECTION
#endif
Then in "planner.cpp", insert as such:

void Planner::_buffer_line(const float &a, const float &b, const float &c, const float &e, float fr_mm_s, const uint8_t extruder) {
  ...
  if (de < 0) SBI(dm, E_AXIS);

  AXIS_BACKLASH_CORRECTION

  const float esteps_float = de * volumetric_multiplier[extruder] * flow_percentage[extruder] * 0.01;
  ...
}
@hectori4502

This comment has been minimized.

Copy link

commented Feb 23, 2018

And I make it work for the marlin v 1.1.8 in my Delta Rostock Max V2.

I only change this part:

_buffer_line( \

by

buffer_segment( \

Then in "planner.cpp", insert as such:

void Planner::_buffer_steps(const int32_t (&target)[XYZE], float fr_mm_s, const uint8_t extruder) {
...
if (de < 0) SBI(dm, E_AXIS);

AXIS_BACKLASH_CORRECTION

  const float esteps_float = de * e_factor[extruder];
  const int32_t esteps = abs(esteps_float) + 0.5;

But I need help to fix this:

  1. M98 and M99

Hectori

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Feb 23, 2018

I recommend against calling _buffer_line (or buffer_segment) as the solution. Although this may accomplish something, it also modifies stepper.count_position[], so it is not transparent to the stepper code, and it breaks Stepper::get_axis_position_mm(...).

@Mike8-I

This comment has been minimized.

Copy link

commented Feb 23, 2018

I would like to support the issue of implementing backlash compensation in Marlin. I know that it has been discussed before. When a machine is optimised as good as possible with a given design, software backlash compensation is the way to go. Even professional CNC milling machines use it. It was the only way to compensate the last some hundreds of a millimeter on my CNC mill (done with Eding CNC), and I would like to do the same on my 3d printer. I Have even considerated to intercept the stepper direction and step lines in hardware and inject some steps on edge of direction signal. My machine would need rouhly 8/16th steps (one half step on the 400 steps per revolution stepper motors I used).

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Feb 24, 2018

Hi @Mike8-I — Welcome to Github!

I would like to support the issue of implementing backlash compensation in Marlin.

We do accept cash, paypal, and certified check.

But all kidding aside, I think "inserting steps on edge of direction signal" is a bit too low-level for what we can accomplish in our AVR-based firmware.

What we can do is determine in planner.buffer_steps how many extra steps need to be added. For this it will use an extra field in the block. The stepper ISR can then execute that block like any other, doing the sum of those steps, but only counting the normal steps.

I'm certain this next problem is already solved by some PhD. out there: where to place those extra steps in relation to the synchronized motions of multiple axes. But I'm at a loss how that would work.

Each axis at the stepper level is independent, with its own drive. If only one axis is reversing, but another isn't, Marlin will already be doing a deceleration for the reversing axis, and this leads to commensurate slowing of all the other axes. Since we can't have the non-reversing axis just stop and wait for the reversing axis to finish its anti-backlash motion we have to allow it to be minimally out of sync with the reversing axis as they both continuously move. So, there are some trade-offs.

@hectori4502

This comment has been minimized.

Copy link

commented Feb 25, 2018

But I need help to fix this:

  1. M98 and M99

When I compensated what my caliper showed me 0.20mm (the test was not good)
then compensate 0.10mm (I improve but something was missing)
when I did the test with 0.06mm (everything looks perfect)
dsc_0030

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Feb 28, 2018

It seems to me that this kind of problem could be better solved by the slicer than by the firmware.

@SimonSolar2C

This comment has been minimized.

Copy link

commented Mar 7, 2018

If we are talking backlash in the [geared] extruder, this reversing of direction is a retraction. Therefore doesn't the s3d 'Extra restart distance' provide the same effect? Or is the maths more complex than, be less than the retraction amount?
Or could be add something to the retraction script box?
In robot arms its always been required for each axis - they include a backlash routine which automagically finds the backlash amount.

@hectori4502

This comment has been minimized.

Copy link

commented May 26, 2018

I am happy with #define AXIS_BACKLASH_STEPS correction. which update in my marlin v1.1.8

Marlin v1.1.9 has many changes in planner.cpp and it does not work with the code

#define AXIS_BACKLASH_STEPS {0.13, 0.10, 0.08, 0}

check this video.
https://www.youtube.com/watch?v=4ZaTx0hO4XM

@thinkyhead

This comment has been minimized.

Copy link
Member

commented May 26, 2018

Marlin v1.1.9 has many changes in planner.ccp and it does not work with the code

The video is inspiring!

The AXIS_BACKLASH_STEPS feature will need to be updated to be compatible with the latest code. There's another implementation under development for Marlin 2.0.x that may have crossover with AXIS_BACKLASH_STEPS. We'll know more about that once a PR has been submitted for it.

@hectori4502

This comment has been minimized.

Copy link

commented May 31, 2018

Hi
backlash

@marcio-ao

This comment has been minimized.

Copy link
Contributor

commented Jun 15, 2018

It's been a while since I've visited this thread and I am pleased to learn that at least one of you is getting good results with the backlash compensation code I had posted here. That said, this is a very early version of the code and we've spent quite a bit of time tweaking it.

I guess I need to get a new PR together with our updated code.

@hectori4502

This comment has been minimized.

Copy link

commented Jun 17, 2018

hello marcio-ao,
I have tried the code and it seems to work very well.

#define CONFIGURATION_H_VERSION 010107 compile and work perfect.

but the version
#define CONFIGURATION_H_VERSION 010108
when I try to compile this is arduino returning

sketch \ Configuration.h: 653: 0: warning: "SIGN" redefined
      #define SIGN (v) ((v <0)? -1.0: 1.0)

Now I am working with my Delta Rostock max V2 with MKS Gen V1.4 TMC 2208 spreadCycle(Marlin 2.0 works very smoothly).
but without:

// #define AXIS_BACKLASH_STEPS {5.13, 0.10, 0.08, 0}

I'm ready to try new code about it.

@marcio-ao

This comment has been minimized.

Copy link
Contributor

commented Jun 19, 2018

@hectori4502, @thinkyhead: I have created a PR with the new backlash compensation code (PR#11061)

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Jun 20, 2018

Thanks Marcio! I will check it out tomorrow night. Flying to ERRF in the morning…

@kostyansd

This comment has been minimized.

Copy link

commented Jun 24, 2018

Where i must insert this code?

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Jul 1, 2018

Discussion moved to #11061.

@thinkyhead thinkyhead closed this Jul 1, 2018

@inventabuild

This comment has been minimized.

Copy link

commented Apr 12, 2019

Is BACKLASH_COMPENSATION best used primarily on the first layer and then tapered off over the next few layers OR can it be used with significant benefits throughout the whole print?

@thinkyhead

This comment has been minimized.

Copy link
Member

commented Apr 16, 2019

Backlash exists at all times and so compensation has to be left on at all times for it to have the proper effect. It is not something you would want to taper off.

@marcio-ao

This comment has been minimized.

Copy link
Contributor

commented Apr 16, 2019

Backlash exists at all times and so compensation has to be left on at all times for it to have the proper effect. It is not something you would want to taper off.

In an ideal world. But backlash compensation can introduce some defects in the surface quality. So I added the fading parameter so that it can be tapered off. We found backlash compensation is vital for the first layer to stick on a .25 mm nozzle, but tapering it off improves the surface finish at the expense of dimensional accuracy.

  1. So, in summary, for best dimensional accuracy, use backlash compensation at 100% on all layers.
  2. For best surface quality, do not use backlash compensation.
  3. For best bed adhesion and improved surface quality, enable backlash compensation at 100% on first layer and fade it out over the first few layers.
@inventabuild

This comment has been minimized.

Copy link

commented May 6, 2019

marcio-ao, I'm tapping the bed in a 6 point grid, 3(x-axis) x 2(y-axis), using copper strips as the electrical contacts as shown here: https://photos.app.goo.gl/Xv7vapDzZm8B9tYW9

I noticed the latest Lulzbot TAZ Marlin firmware has a backlash formula that assumes 4 points will be tapped:

/* Average the backlash from all four corners */
z_backlash_measured_mm += 0.25 * (current_position[Z_AXIS] - start_height); \

Does this formula always get applied when backlash is active? If I'm tapping 6 points instead of 4 points s/ I change 0.25 to 0.167 (i.e. 1/6) in the above formula? Is there anyplace else I will need to take into account 6 points instead of 4 points?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.