Marlin versus Work Coordinates (G10 L20)

https://reprap.org/wiki/G-code

Marlin uses G10/G11 for executing a retraction/unretraction move. Smoothie uses G10 for retract and G10 Ln for setting workspace coordinates. RepRap firmware interprets a G10 command with no P or L parameter as a retraction command.

I think this would be a good addition to Marlin. When I set up multiple work coordinate systems i had to use G54 and G92 and then switch G55, then G92 then switch back with G54.

I was not aware of G10 L20 but it sounds like you can set coordinates for other coordinate systems without switching to them.

The Marlin folks seem very open to more CNC things, so I think they would welcome this improvement. It just takes someone to implement it.

I have logged a feature request ticket with Marlin:

https://github.com/MarlinFirmware/Marlin/issues/14734

I’ll keep an eye on it and if nobody picks it up I might give it a shot.

I did a bit more testing:

CNCjs 1.9.20 [Marlin]
Connected to /dev/ttyUSB0 with a baud rate of 250000
start
feeder> M115
echo: External Reset
Marlin bugfix-2.0.x
echo: Last Updated: 2018-01-20 | Author: (V1 Engineering, Ryan, 402)
echo:Compiled: Jun 27 2019
echo: Free Memory: 3410 PlannerBufferBytes: 1456
echo:V64 stored settings retrieved (583 bytes; crc 20324)
echo: G21 ; Units in mm (mm)
echo: M149 C ; Units in Celsius
echo:Filament settings: Disabled
echo: M200 D3.00
echo: M200 D0
echo:Steps per unit:
echo: M92 X200.00 Y200.00 Z800.00 E200.00
echo:Maximum feedrates (units/s):
echo: M203 X120.00 Y120.00 Z30.00 E25.00
echo:Maximum Acceleration (units/s2):
echo: M201 X400.00 Y400.00 Z100.00 E2000.00
echo:Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>
echo: M204 P400.00 R3000.00 T400.00
echo:Advanced: B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate> J<junc_dev>
echo: M205 B20000.00 S0.00 T0.00 J0.00
echo:Home offset:
echo: M206 X0.00 Y0.00 Z0.00
echo:Material heatup parameters:
echo: M145 S0 H196 B92 F0
echo: M145 S1 H240 B110 F0
echo:PID settings:
echo: M301 P17.98 I0.98 D83.62
FIRMWARE_NAME:Marlin bugfix-2.0.x (Github) SOURCE_CODE_URL:https://github.com/MarlinFirmware/Marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:V1 E CNC EXTRUDER_COUNT:1 UUID:cede2a2f-41a2-4748-9b12-c55c62f367ff
Cap:SERIAL_XON_XOFF:0
Cap:BINARY_FILE_TRANSFER:0
Cap:EEPROM:1
Cap:VOLUMETRIC:1
Cap:AUTOREPORT_TEMP:1
Cap:PROGRESS:0
Cap:PRINT_JOB:1
Cap:AUTOLEVEL:0
Cap:Z_PROBE:0
Cap:LEVELING_DATA:0
Cap:BUILD_PERCENT:0
Cap:SOFTWARE_POWER:0
Cap:TOGGLE_LIGHTS:0
Cap:CASE_LIGHT_BRIGHTNESS:0
Cap:EMERGENCY_PARSER:0
Cap:PROMPT_SUPPORT:0
Cap:AUTOREPORT_SD_STATUS:0
Cap:THERMAL_PROTECTION:1
Cap:MOTION_MODES:1
Cap:CHAMBER_TEMPERATURE:0
ok
> G21 ; millimeters
ok
> G90 ; absolute coords
ok
> G53 ; machine coordinate system
ok
> M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:0 Y:0 Z:0
ok
> G54 ; switch to work coordinate system
Select workspace 0
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:0 Y:0 Z:0
ok
> G0 X10 Y10 ; move
ok
> M114 ; get position
X:10.00 Y:10.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
> G92 X0 Y0 ; set current position as new origin (similar to G10 L20 P1 X0 Y0)
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
> M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
> G53 ; switch back to machine coordinates
ok
> M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
>

Conclusion: Marlin 2.0 bugfix G53 and G54 coordinate systems are linked. You cannot set a new origin in one coordinate system without it doing the same for the other coordinate system.

If we now repeat the test for G53 versus G55 we get different results:

{startup output}
> G21 ; millimeters
ok
> G90 ; absolute coords
ok
> G53 ; machine coordinate system
ok
> M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:0 Y:0 Z:0
ok
> G55 ; switch to 2nd work coordinate system
Select workspace 1
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:0 Y:0 Z:0
ok
> G0 X10 Y10 ; move
ok
> M114 ; get position
X:10.00 Y:10.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
> G92 X0 Y0 ; set current position as new origin (similar to G10 L20 P2 X0 Y0)
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
> M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
> G53 ; switch back to machine coordinates
ok
> M114 ; get position
X:10.00 Y:10.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
>

Conclusion: Marlin G53 and G55 coordinate systems are not linked. You can set a new origin for G55 without it affecting the origin of G53. This is how work offset coordinates should work; you can zero the X and Y coordinates at any random position and start running your gcode from there.

I am surprised to learn Marlin does not treat the G54 coordinate system as a work offset coordinate system but links it to the machine coordinate system G53. You cannot set an origin in G54 without it affecting G53 as well. Strange…

1 Like

So I got it to work by doing the following:

  1. Power up MPCNC machine with spindle in lower left corner. This will be my machine coordinates X0 and Y0 as well as Xmin and Ymin.
  2. G21 ; millimeters
  3. G90 ; absolute coords
  4. G0 X200 Y200 ; move to center of spoil board. Make sure CNC.js Axes widget shows machine / work offset coordinates. Do not move spindle by hand (!) You can use keypad jogging.
  5. G55 ; Switch to 2nd work offset coordinate system
  6. G92 X0 Y0 Z0 ; set new origin
  7. G91 ; relative coords
  8. Run my Gcode.
Further testing showed endstops Xmin and Ymin positions remain relative to G53 machine coordinates origin as they should.

The one disadvantage is that CNC.js Axes widget does not display G55 work (offset) coordinates, only G54.

If would be nice if Marlin could keep G54 coordinate system origin separate from G53 origin just like it does for G55 + when asked to execute a G10 L20 P1 X0 Y0 Z0 could simply execute a G54 + G92 X0 Y0 Z0 and return to the coordinate system it was in.

There have been reports that G53 is broken. I haven’t looked into it in detail and I don’t fully understand what G53 should do. I have just avoided it and only used G54+. It sounds like you are encountering related anomalies.

G53 = Machine coordinates = always displays absolute true coordinates relative to the Xmin / Ymin endstops when the machine was first powered up. A well calibrated machine will always show the same coordinate values for a certain X Y or Z axis position, even after a restart. You cannot change the origin for machine coordinates; it always sits at the Xmin and Ymin endstop limit switches (if enabled in firmware). Marlin calls the calibrating or referencing operation where you touch the Xmin and Ymin endstops ‘Auto Home’.

(Note that you can also Auto Home using Xmax and Ymax. This is useful for totem corner post designs with integrated limit switches as the rollers can touch Xmax and Ymax limit switches just fine, but not Xmin and Ymin limit switches because of the spindle acting as an obstacle)

G54 = Work (offset) coordinates. Suppose you want to drill a hole grid pattern in your spoilboard for hold down clamps. You cannot use the bottom left corner of your spoilboard in your design as origin because the gantry will not be able to reach that position. You can however set the origin to the center of the spoilboard in your design and output gcode. After powering up your machine (and touching Xmin and Ymin endstops to reference the machine), you can keyboard jog your gantry to the centre of the spoilboard and zero X Y and Z work (offset) coordinates and run your gcode from here.

[BUG] G54 + G92 X0 Y0 inadvertently resets origin in G53 machine coordinate system as well:

Does this mean that in G53 coordinates G92 is illegal or perhaps it has no effect? Also would it mean that homing with G28 would affect all workspaces?

Im sure there’s a way for this to be a superset of the usual Marlin behavior. Here’s one way i think is equivalent:

Marlin wakes up in G54 coordinates with zero offset between G53 and G54. G92 sets an offset between G54 and G53 but does not change the limits enforced by soft endstops. I think this is the current behavior. Then G28 resets machine coordinates and also contains an implicit G92 to set current workspace coordinates to zero (or nonzero values based on the M206 value).

Would this be desirable? Perhaps in machine coordinates G53 any G92 has no effect, and homing with G28 does not respect homing offsets M206? But in any of the workspace coordinates the usual behavior is preserved.

[BUG] G54 + G92 X0 Y0 inadvertently resets origin in G53 machine coordinate system as well:
https://github.com/MarlinFirmware/Marlin/issues/14743

–> A fix has been made available for testing.

This has been driving me insane for the last few days, I’m so glad I found this thread. I just built an MPCNC over Christmas and have been using CNC.js with it, and had given up on trying to use the work coordinate system because it didn’t behave any differently from the MCS. I’ve just been typing in raw gcode in the console like a caveman.

So if the G53 and G54 coordinate systems are linked, we have to use G55 (or some other coord system) as the WCS.

It looks like if you type “G55” into the console, you can switch to the WCS and manipulate it separately from the MCS, but the “Axis” widget still shows the machine position and work position as identical. If you follow these steps:

{startup output}

G21 ; millimeters
ok
G90 ; absolute coords
ok
G53 ; machine coordinate system
ok
M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:0 Y:0 Z:0
ok
G55 ; switch to 2nd work coordinate system
Select workspace 1
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:0 Y:0 Z:0
ok
G0 X10 Y10 ; move
ok
M114 ; get position
X:10.00 Y:10.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok

At this point the Axis widget shows Machine position X10 Y10 Z0, Work position X10 Y10 Z0

G92 X0 Y0 ; set current position as new origin (similar to G10 L20 P2 X0 Y0)
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok
M114 ; get position
X:0.00 Y:0.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok

At this point the Axis widget shows Machine position X0 Y0 Z0, Work position X0 Y0 Z0

G53 ; switch back to machine coordinates
ok
M114 ; get position
X:10.00 Y:10.00 Z:0.00 E:0.00 Count X:2000 Y:2000 Z:0
ok

At this point the Axis widget shows Machine position X10 Y10 Z0, Work position X10 Y10 Z0

So it looks like the Axis widget in CNC.js only shows the current work position for both the Machine position and Work position?

1 Like

Sounds to me like cnc.js is oblivious to the workspace changes. If it has a gui element to show workspace coordinates specifically, separate from machine coordinates, then you would think it would track the workspace changes. It seems like this is where the G10 L20 stuff comes in, and cnc.js is not catching G53 G54 G55 stuff.

I think I saw a Marlin update where someone had added support for G10 L20 as an alternative to G54 but I’m not sure if it got approved and merged into the official code and propagated to the V1 firmware.

Here is someone claiming to have implemented it, but it’s a zip file, not a branch, so it would need conversion into a patch to submit a PR against Marlin. Probably not a big deal, and then it could eventually be officially supported.

If you are comfortable with firmware you could give it a shot and see if it works as advertised.

The way it gets the current position from Marlin is different than hoe it does it in grbl. The axis should follow the work coordinate system. Because that’s where the pattern is being drawn. I think one way to fix it is to see how cnc.js is querying the position and make that report the wcs position when in G55+

From the developer of CNC.js:

Other (non Marlin) controllers have a soft-configurable (does not require recompilation) option to include both machine and work coordinates in their position reports. For example, g2core tags machine coordinates with “mpos:” and work coordinates with “wpos:” in the JSON-formatted reports. The report format has little or nothing to do with the parsing of GCode. In the case of Marlin, there is no easy way to coerce it to automatically issue timely position reports. You have to send a command asking it for a report, and the periodic sending of those commands sometimes causes motion stuttering because the “send a report” command has to be interspersed with the GCode from the file. The lack of automatic position reports can be troublesome for milling, where it is common for a single GCode move to take several seconds - for example a long arc at a low feedrate. With Marlin, the DROs don’t update during that move, and might not update until the end of several such moves, depending on how often CNCjs has inserted “send position” commands.

1 Like

This makes a lot of sense, because I’ve noticed that the CNCjs position report in the Axis widget always lags behind the actual position by a not-insignificant amount.

More from CNC.js dev:

I did not spend much time looking at the changes because they are not presented in the standard form of a pull request (PR) against a specific version. There is a very good reason for that standard form - it saves time for primary developers, who are often very busy and overwhelmed with requests from many different people. With a PR, you can easily see exactly what changed, accept/merge it with the push of a button if it is good, comment on specific lines with a single click, etc.

Another meta issue is with the specific “ask” in the original issue posting “can someone take a look at it and confirm that it does what it is supposed to”. Asking CNCjs developers to review Marlin code is out of scope. As far as I know, there is no overlap between the CNCjs and Marlin development team. There just happens to be some g2core overlap, as I am also a g2core developer, but even so, I would expect requests for g2core code review to go to the g2core site.

But those meta issues aside, it seems to me that the thread has morphed into three separate issues:

Coordinate system support via G10
“automatic” position reports (actually a subset of a fully useful solution to that problem)
work coordinate reporting
(As with the PR meta-issue, when too many issues get conflated, it is hard for people to focus. When too-busy people are presented with conflated issues, the tendency is to disengage.)

Taking those one at a time:

G10: So what is the CNCjs issue here? Does CNCjs work with the changed version or not? If it does, what is the problem? If not, an issue specifically identifying how to reproduce the problem would be appropriate - but possibly time-consuming for the CNCjs developers to handle because testing it would require us to set up a Marlin compilation environment, compile the patched code, load it onto a board, etc. That might be worthwhile if this feature becomes standard on Marlin, but until is clear whether that will happen, it’s a “one off” situation.

“not really automatic” position reports: Again, does this work with CNCjs or not? My guess is that it does work, because CNCjs just deals with position reports whenever they arrive. There is no notion of “expected” vs “unexpected” reports. There is some CNCjs code to try and coerce Marlin to send some reports, but on the receiving side, whenever a position report happens to come in, things get updated. Perhaps the issue should be framed as an announcement?

“work coordinate reporting”: This was framed as “could you add mpos: and wpos: tags like g2core” and “what position reports should look like for optimum CNCjs compatibility”. As it currently stands, Marlin reports look nothing at all like g2core reports, so trying to shoehorn g2core syntax into Marlin syntax is not workable. g2core report syntax is highly structured using JSON notation, whereas Marlin is totally ad-hoc. With a structured report format, you add new features easily because the parser expects everything to be tagged. Any new tag is simply ignored by older versions of the code, which is possible because the parser can always tell what is a tag and what are the arguments for that tag. Ad-hoc formats are very tricky to change without risk of breaking old code. Since the format is unstructured, different UI agents probably use different strategies for recognizing the various different reports and pulling out the different fields. You must be very careful to design a new report that old parsers won’t confuse for a preexisting report - and just adding fields to an old report suffers from the same problem. To do this safely requires you to consider every different UI agent that purports to support Marlin - not just CNCjs.

And thus perhaps you can see why I am not a fan of Marlin for the use case of external UI control. Its serial communications framework is poorly designed at a very fundamental level. For the use case of running a 3D printer via an attached LCD panel, Marlin works brilliantly. I use it on my 3D printer. Copy the GCode to a USB stick, bung it in the printer, and let the job run for hours without worrying about whether an attached PC will go to sleep at a bad time.

The answer to “what should they look like for optimum CNCjs compatibility” is this: Compatibility with current releases of CNCjs is hopeless because CNCjs parses Marlin reports according to existing Marlin syntax which does not have work position. For the future, whatever you can convince the Marlin team to do will be okay with CNCjs, under the assumption that the Marlin team will invent something that is unambiguous (otherwise it will cause endless problems for everybody). The Marlin and g2core report parsers are totally separate so trying to make an amalgam of the two is not helpful. If Marlin were to use g2core style JSON reports, that might be helpful in theory, but the fact that there are so many copies of Marlin out there that use the existing Marlin format makes a new JSON format not helpful in practice.

Sorry if this sounded cranky - but the fact is that there are lots of factors in play and I wanted to lay them out so you understand the depth of the problem. Maintaining and enhancing complex software is a big problem, and is made much much harder by interactions between multiple separately-developed components.

1 Like

Thanks for sharing. That is an interesting perspective. I suspect that although json is great, it won’t fly on Marlin because of the constant need to be As Fast As Possible, and having a lot of embedded devs. The paragraph about not wanting to use marlin with a ui is a little odd, since they have a ui, and they added Marlin. It is unfortunate, but not incorrect for them to say all of this. It lacks good will towards others, but in an open source project, self protection and project protection often come first.