-
Notifications
You must be signed in to change notification settings - Fork 298
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
backlash compensation #67
Comments
Backlash compensation is one of those issues that is more complex than it seems. It's not as simple as putting in steps when you reverse direction. One test is to determine how the machine should behave when tracing a circle. The direction reversals are very slow. If you wanted to correct by N steps you don't just want to do that all at once and leave a discontinuity at the 90 degree points. Another issue is acceleration. Reversing direction is one of the times that acceleration management kicks into high gear. Just adding or removing steps or changing direction will cause unexpected discontinuities in acceleration, and possibly motor stalls. I think it can be done, and I encourage you to experiment. It's probably best handled above the loader level. Take a look at st_prep_line() in stepper.cpp. There is a block of code that bracketed by #ifdef __STEP_CORRECTION which uses a "nudge" strategy for correcting positional errors (i.e. incorporating encoder feedback) without upsetting the step integrity. That's probably the place to start. |
Thanks for the help! I only have a very basic understanding of backlash compensation, but it seems to me like it actually is better to put in all the steps at once rather than spreading them out. A (probably overly) simplistic way to think about it is that the axis won't move while those steps are being inserted. The motor and leadscrew will turn, but the nut won't actually move at all. Since nothing is moving, accelerations don't matter either, at least as long as the acceleration planner doesn't know about the extra steps (does it?). I suppose this really is an overly simplistic since view cutting forces could cause the axis to move. Regardless, st_prep_line() looks like a good place to do some experimenting. Seems like it could be as simple as adding:
Does that look workable? I'm assuming travel_steps is full motor steps, not microsteps? I'll give it a try later. Just need to figure out how to add a backlash configuration variable. |
You can give it a try, but I suspect it's more complex that this. To add configuration variables take a look in config_app.cpp. Follow the instructions at the top of the table to add a new variable. You will find many, many worked examples there and in the various module files. Take a look at the sys / ja (junction acceleration) parameter as a good example that's close to what you need. Also see the print function in canonical_machine.cpp. |
I gave it a try Saturday night. The actual code I tried was:
Implementing the config variables was fairly straightforward. It probably makes the most sense for them to be defined in terms of distance units of backlash for each axis. However, currently I've implemented them as the number of steps of backlash for each motor, as that was easier. So, as you've guessed it doesn't work very well. I tested it by moving the x-axis back and forth. I could tell it was injecting the extra steps at the beginning of each move, as expected. However, for backlash values of more than ~10, the steps are injected faster than the motor can handle, so I need to figure out how to slow that down. I only have ~3 steps worth of backlash in my x-axis, but I measured no change with such small values, so I suspect that travel_steps[motor] is actually microsteps, not steps. I'm using 16 microstepping on that axis. For some moves, extra steps were injected at both the beginning and end of the move. Then the next move (in the opposite direction) would have no steps injected. I don't know why steps would be injected at the end, maybe in certain cases the controller is specifying a short segment in the reverse direction to slow down the machine? My next steps are:
I'm still interested in getting this simple model of backlash compensation working, but I'm also starting to see ways in which the physical reality is more complicated. For example, If the machine is moving fast and then stopped quickly, the inertia of the machine will keep it moving until it has taken up the backlash slop. In this case it would have been better to not add any backlash steps to the move. |
I have confirmed that some G0 moves end with a move segment in the opposite direction as the rest of the move. This may be a bug. The magnitude of the offending move segment is ~1/1000 of a microstep. I have also confirmed that Increasing the values of |
Ok, I've grokked the pseudo-encoder system and following error correction, which explains all the correction steps when trying to change I think the way forward might be to temper the following error within
|
Tested. All I did was linear moves in air, no cutting yet. But, it seems to work well. I found I had to decrease |
This is fascinating. I look forward to hearing more. |
Thinking about this a little more, I realize the timing info I wrote above is not quite correct. It actually takes a bit longer to do the correction because the length (travel_steps) of the first and last few move segments are shorter than the value of STEP_CORRECTION_MAX (currently = 0.6). So, the step correction for those segments will be truncated to be equal to travel_steps for those moves, by the following bit of code:
So, for the first few move segments, the value of travel_steps will be doubled. After the first few, travel_steps becomes greater than STEP_CORRECTION_MAX, and so it is increased by that amount. I'm a bit worried about those first few moves. Doubling the move segment distance is equivalent to doubling the jerk, since the time for those segments remains the same. That may result in dropped steps. While this could be accounted for by the user halving the max jerk value for that axis, that would slow down all moves. Instead I propose adding another step correction factor, STEP_CORRECTION_JERK_INCREASE, to be implemented like so:
A default value of 0.25 seems reasonable. I'd also suggest that we convert all of the STEP_CORRECTION values into user-tunable configuration variables. |
Just tested this update with some actual cutting and it works great, it cut a circle that is as good as I can measure. So, as I see it, this is ready to be incorporated into the code base. How do I go about that? Also, here is an example of what happens during a short (0.1 inch) move with 40 microsteps of backlash compensation. Each move segment is one line of output. I've listed my step correction values at the top:
As you can see the backlash compensation is completed in about the first 1/3 of the move. |
Nice work. Please report back your results as you have a chance to run this. Also, do you have a fork of the github repo where we can look at the code? lastly, some description of the machine and your settings would be useful. You have it set up for your case and I wonder what's involved in the more general case. Really cool. |
Here is a fork. Be careful if you test it, I inverted the global enable pin to make it work with my set-up. Backlash can be set in MICROsteps using the $1bl, $2bl, etc variables. I haven't broken out the step_correction variables yet. Let me know if that would be useful. My machine is a cnc router cobbled together from some surplus linear motion stages. Working envelope is 20"x12"x5" (X Y Z). Nema 23 stepper motors, ballscrews on X and Y, acme on Z. Stepper motor drivers are IM483. Spindle is a 2.25hp router. The Y-axis has preloaded bearings and ballnut, and thus has essentially zero backlash. The X-axis has neither, and as a result has ~0.006" of backlash. Photo here. I've used the backlash code to cut a couple real parts now. The parts are similar to a gear and include holes for bearings to fit into. No complaints. |
This looks awesome. I can't wait to try this. I think this is especially useful for timing belt-based machines. |
Why wasn't this merged? Was there additional problems with it? |
I would like to see some basic backlash compensation in G2. Unless someone is motivated to to implement it, I'd be willing to take a stab at it, although I'm not sure my programming skills are up to the task.
Looking through the code it seems like maybe the place to implement it would be in the _load_move() section of stepper.cpp. There is already a check for change in direction there. I think implementation could be as simple as adding a few steps upon a positive direction change, and substracting a few steps upon a negative direction change. Of course, some new configuration values would have to be added for the amount of backlash for each axis.
Does this seem like a reasonable strategy and/or a reasonable place to implement it? What variable holds the number of steps to move by in this case, st_run.mot[MOTOR_1].substep_accumulator?
The text was updated successfully, but these errors were encountered: