I'm just finishing up travelling for the summer and I've been slowly testing new code while I can. As of a couple days ago, I've finished the automatic backlash determination function and have it running as a gcode function in Marlin.
The goal of this piece of code is to use the endstops on the printer to automatically determine the backlash in each axis. To do this, the printer first homes itself so that the given carriage to test is pressing into its endstop switch. It then steps the carriage the opposite direction and counts how many steps it takes to deactivate the endstop. It is theoretically a very simple piece of code, just a "G28" (home all axes) call and a while loop to step each axis and count, but Marlin has a timeout safety feature that restarts the printer if the main control loop is interrupted for more than ~5 seconds.
It took quite a bit of trial and error to find a solution, but it turns out that if you wrap your function in an unused gcode name, M954 in my case, the main control loop will allow your function to run until completion. This is what I ended up using, and as a handy side effect, it also makes it very easy to add any other function into Marlin. I'll put out a short tutorial in my next update on how to add your own functions into Marlin, and what I've had to lookout for while building mine.
Here's the backlash determination function in its current state:
First I'll go through the function itself and what it outputs, and then I'll go through how it is called in a second update when I have the time.
When the printer receives "M954", the function first checks if the axes haven't been homed, or if any of the endstops aren't triggered. If either is true, it then homes the axes. This ensures when the rest of the program runs that the carriages are in position to be tested. Currently, the code is only configured to run the Y axis, but the final code will simply loop the entire function over each axis.
"stepper.synchronize()" then tells the printer to wait for all moves in the buffer to clear before continuing. This means that if the printer is still moving, the function won't continue past this line until everything's done. This prevents functions from stepping on eachother.
"WRITE(Y_DIR_PIN, LOW)" then writes a low value to the Y axis drivers direction pin, making the stepper turn in the opposite direction that it homed. WRITE(...) is part of the fastio.h library in Marlin, which is an extremely useful for tool for directly controlling or reading the output of pins on your printers control board. For anybody else trying to write functions for Marlin, fastio.h is very much your friend. (READ(pin) is also from fastio.h)
Now that the axis is safely homed and prepared to be stepped in the right direction, the while loop will begin to step the given axis forward until, "READ(Y_MIN_PIN)" returns 0, eg. the endstop deactivates. When complete, the step direction pin is then returned to HIGH.
The counted steps are then divided by the axis steps/mm, given by planner.axis_steps_per_mm[Y_AXIS], finally yielding a backlash in mm. For the time being, the backlash is simply echoed over serial, but in the final iteration the code will set values to be used by the backlash compensation function, which I described in the previous update.
The final output from the arduino serial monitor looks like this:
How accurate the function is remains to be seen, but the 2.6mm value is relatively close to the 2.3mm I've been measuring by hand. The extra distance looks like it's coming from the endstops themselves, as due to their internal switch mechanism, there is some "give" before the endstop releases after it is pressed. This distance should be relatively consistent between endstops of the same model, so dealing with it in code should be simple enough. I'll get around to accurately measuring it when I can. Updates on that later.
I should also note that this code is not at all generalized for different printer configurations, and running this on a delta machine or core-xy could seriously damage or misalign your printer. My level of Marlin knowledge is not far along enough to write safe code for anything other than cartesian machines, so a more advanced Marlin-er will need to take up the challenge before anything can be integrated into released code.
Thanks for reading! The next update should be quick.