Question about the M671 Command
-
Hi all,
I am finishing up a new i3 styled printer with spare parts I had lying around and a new Duet 3 Mini 5+ WiFi I recently purchased. Since this is my very first Duet 3 board I followed the article CNC Kitchen wrote about that (basically he swapped boards on a Prusa machine).
I set up my config.g file manually by looking what I have in other machines (Duet 2 driven) and the config.g file CNC Kitchen posted:
https://github.com/CNCKitchen/PrusaDUET/blob/master/SDCard/config.g
I got everything working with some tweaks here and there such as motor direction or sensorless homing, etc. The printer moves, homes, etc. However on the above posted config.g file, I saw the following line:
M671 X-37:287 Y0 S10
with my other machines I was not familiar with this command, I guess because both Z motors (cartesian printers) are on a single driver, which is not the case of this newer (also cartesian) printer.
I have checked the documentation regarding the M671 command, but apparently I am no savvy enough to fully understand what it means.
Could somebody please help me understand that? I searched also the forums, but to no avail. For now I just copy-pasted the command in my config.g file, but I guess I should measure something, although I don't now exactly what and why is that necessary.
Sorry for the very general question, but I don't know how else to ask.
-
@FelixH its the location of the Z leadscrews relative to the printer co-ordinate system.
Measure them from the nozzle when X is 0 to the centre of the leadscrews -
@jay_s_uk and why is that necessary exactly?
-
@FelixH it helps the firmware work out how much to adjust each leadscrew when performing gantry levelling by knowing where they are and how far away they are from each measurement point
-
-
@jay_s_uk ok, I think I understand. So with this command the adjustments for the bed leveling can be more accurate by moving both z motors independently from each other, right?.
In the line above, if I understand that right the leadscrew on the left hand side is offset by 37 mm in the X axis and 0 to the Y axis relative to the (0,0) point of the printer. The right hand side screw is offset 287 mm on the X axis and 0 on the Y axis.
Well, I don't have that option on my other Duet printers. I am curious to know if the adjustments will improve that much...
I wish the documentation would include some examples for complicated things, sometimes
-
@FelixH yes, thats right.
Just make sure that the order (e.g left then right), matches the order of the motors in M584 e.g. Z2:3 is then right. -
@FelixH you also don't need to put the M671 in config.g, it could go in bed.g
we have an example macro here https://teamgloomy.github.io/useful_macros.html#bedg-file-for-g32 -
@FelixH said in Question about the M671 Command:
Well, I don't have that option on my other Duet printers. I am curious to know if the adjustments will improve that much...
On machines with both Z (or any other axis) motors on the same stepper driver, the stepper motors will generally stay in sync, even through power cycles. However, if they go out of sync (eg one skips steps or gets blocked) it's a manual process first to notice this, then to correct it.
By putting each motor of the axis on a separate driver, this can be done automatically, using either the bed or frame for reference (depending on axis and probe), or using an endstop for each motor. This also means rather than one stepper driver with two motors, the load is spread across two stepper drivers. However, it causes another problem, in that on power up, a stepper motor jumps to the first full step, and this can be in the opposite direction to the other motor on the same axis.
So splitting the motors means you generally need to do bed/gantry levelling MORE often, and usually each time you start up. However, the X axis should be more accurately parallel with the bed than setting it by feeler gauges etc, assuming your probe has good accuracy.
Many very experienced users, eg @deckingman and @mrehorstdmd, don't use this method, and move their bed/gantry with one stepper, or two that are wired together. So it is not compulsory!
I wish the documentation would include some examples for complicated things, sometimes
There are examples on the page I linked. If we put the full explanation, example and related commands in the Gcode dictionary, it would unmanageably long (it already is!). That's what the other wiki pages are for.
If you need further examples, let me know. Would a diagram of a bed showing the leadscrew/pivot point offset might be useful?
Ian
-
@droftarts many thanks for your explanation. Sorry if my wish for more examples came across as a complaint. I understand that the Gcode doc page is already very long.
Now just another couple of short questions:
- When is the script bed.g called exactly? On my other machines I believe I have never even edited it and used as it came out of the configuration tool.
- If I understood that right it would be advisable to run a gantry leveling routine every time the printed is powered on, right?
- According to the link you posted the Y value of the M671 command doesn't matter if you have just two motors, but it must be equal, right?
wow, so overwhelming...
-
@FelixH said in Question about the M671 Command:
Sorry if my wish for more examples came across as a complaint.
No apology necessary! Let me know how to make things clearer if they are not. After this thread, I'm thinking of a 'pros and cons' section for the wiki page, and a couple of diagrams. And I've just realised the wiki page isn't linked in the M671 entry on the Gcode page, which I'll add.
When is the script bed.g called exactly? On my other machines I believe I have never even edited it and used as it came out of the configuration tool.
G32 calls bed.g. If you have never edited it, it probably just contains M561 (to clear any bed transformation) and G29 (which does a bed mesh). Usually auto-levelling replaces running a bed mesh, instead doing the levelling. This should leave the machine in a 'known state', and a presaved bed mesh can be loaded with G29 S1 (or redo the bed mesh) at the end, followed by a G30 in the centre to home Z. At least, that's what mine does.
If I understood that right it would be advisable to run a gantry leveling routine every time the printed is powered on, right?
Ideally, yes, because of the motor jumping to the next full step when enabled, or the possibility that the motors have moved independently of one another when the machine was off. Any axis that has two motors on one axis, whether on the same driver or different ones, is potentially in an 'unknown' state when powered on.
According to the link you posted the Y value of the M671 command doesn't matter if you have just two motors, but it must be equal, right?
For two motors, I don't think it even has to be equal, as it is basically ignored. But I haven't tested.
One more, somewhat overlooked, thing with bed/gantry levelling. The thing that you reference (ie the bed or frame if you are levelling a gantry; the plane of the probe if you are levelling the bed in a CoreXY) needs to be square with the axis. Eg, for gantry levelling, you are trying to set the X axis square to the Z axis, but using the bed as a reference, so the bed needs to be square to the Z axis. You may be able to physically set this (eg use a square against the Z axis to level the bed first), but you can also do it the other way around, by setting the gantry square to the Z axis (eg by using a square, or measuring off the frame), then use a manual bed levelling macro to set the bed plane level with the plane of the probe/nozzle. I use a macro that checks the bed plane with three points, and suggests adjustments to the manual bed levelling screws; see https://docs.duet3d.com/en/User_manual/Connecting_hardware/Z_probe_manual_levelling. I do this occasionally, and assume the bed doesn't move that much, and run the auto-levelling as part of homing. I'd do it even less frequently if I had a milled flat piece of aluminium for a bed, rather than a flexible PCB heater, mounted on a wobbly wood carriage, with glass on top!
Ian
-
comming back to the setting up of the whole thing, I am looking now at the bed.g script. On the example I found it looks like this:
; bed.g ; called to perform automatic bed compensation via G32 ; ; generated by RepRapFirmware Configuration Tool v3.2.3 on Mon Mar 15 2021 19:09:36 GMT+0100 (Mitteleuropäische Normalzeit) M561 ; Clear any existing bed transform. G28 ; home G1 Z220 F10000 M558 F10000 G30 M558 F100 A5 S0.003 G30 P0 X25 Y105 Z-99999 ; probe near a leadscrew, half way along Y axis G30 P1 X240 Y105 Z-99999 S2 ; probe near a leadscrew and calibrate 2 motors M558 F200 A1 G1 X10 Y210 Z10 F10000
I can just copy paste it and adapt it to my setup, but I would like to know what is the point of the line
G1 Z220 F10000
which just sends the x axis all the way up only to bring it down again. Any insights?
Additionally, after some test I see that the coordinates on the G30 command refer to the probe itself and not the nozzle as per usual. Am I right there? I looked the documentation up and I saw no reference on that.
Finally, when everything is setup and working. Does it make sense to add the G32 command to the starting Gcode or where is it normally used?
-
That is a odd piece of coding. It's hard to believe it was generated by the config tool. I have never coded bed.g like that.
Where did it come from?
For future reference you can use code like this to run multiple bed leveling operations to try to insure getting the best results. Of course the X and Y values in the G30 P# commands would need to be edited to suit your printer. And this code is strictly the bed leveling code, it doesn't show homing, probe configuration, etc. that you would include before to prepare to run the bed leveling or the code you would include after to finish up the bed leveling. I would be glad to show that as well.
Frederick
var msg = "" var success = false while true ; run leveling pass G30 P1 X0 Y100 Z-99999 G30 P2 X145 Y-65 Z-99999 S2 if move.calibration.initial.deviation < 0.02 set var.success = true break ; check pass limit - exit loop if pass limit reached if iterations = 5 break ; --- check for failure --- if !var.success set var.msg = "Unable to level bed - pass limit reached" M291 R{var.msg} P"Aborting" S2 abort var.msg
-
@fcwilt said in Question about the M671 Command:
Where did it come from?
-
Thanks.
My advice is to use the existing GCode dictionary and folks here to develop a firm understanding of what needs to be done and how and then create you own code.
While the bit of code you posted isn't "wrong" it certainly isn't the "the one and only correct way" to do things.
And some of the rest of the code from that site you referenced is "odd" as well.
Fell free to ask all the questions you wish.
Frederick
-
@FelixH Examples in the wiki are here: https://docs.duet3d.com/en/User_manual/Connecting_hardware/Z_probe_auto_levelling#examples
But they are basically the same as the one you found and @fcwilt has posted.An alternative way of coding a repeating cycle until the number of iterations or specific accuracy is achieved could be (thanks to @Sindarius ) :
while true G30 P0 X25 Y105 Z-99999 ; probe near a leadscrew, half way along Y axis G30 P1 X240 Y105 Z-99999 S2 ; probe near a leadscrew and calibrate 2 motors if abs(move.calibration.initial.mean) < 0.01 || iterations > 3 break
Ian