fragmuffin / pygcode

GCODE Parser for Python
GNU General Public License v3.0
123 stars 38 forks source link

E motion letter support for 3D printers #8

Open revarbat opened 6 years ago

revarbat commented 6 years ago

This is a beautiful library for parsing CNC subtractive process GCode. However, 3D printing, an additive process, uses a slight variant on GCode.

Almost all cheap 3D printers use the E letter to denote extruder motion, such that X, Y, Z and E are motion axes. Yes, it would have been smarter to use the A, B, C, U, V, or W codes instead. Unfortunately E became the standard, and it's too late to do much about that.

In addition:

If there is a way you could at least enable the E motion axis in this library, that'd let me use this library to write a program to visually preview GCode files with PyOpenGL.

fragmuffin commented 6 years ago

Thanks for the lesson!, I don't have a 3d printer, but this library is intended to be useful for both additive and subtractive processes.

The issue is being able to support multiple conflicting variants of the gcode language.

Modifying Base G-Code set I could provide a function to add and modify the LinuxCNC defined gcodes, but that would mean you couldn't parse subtractive and additive gcode in the same script. (and it's messy and hard to trace what each GCode class actually contains)

Registering Language Variants I could have the LinuxCNC defined codes as the base set, then modifications as languages. So to change the language you could...

import pygcode
pygcode.set_lang('reprap')
# or
pygcode.set_lang('marlin')

That's a bit more work, but I like it.

Workaround But for now... in 0.2.1 you can write:

import pygcode

# Add 'E' parameter to all motion commands
for cls in pygcode.gcodes._subclasses(pygcode.GCodeMotion):
    cls.param_letters.add('E')

# Add G29 gcode
class GCodeAutomaticBedLevel(pygcode.GCode):
    word_key = pygcode.Word('G', 29)

# Cannot create duplicate codes, so G82 and G83 will be broken

Then the code

lines = [
    'G1 X1 Y2 E3',
    'G82',
    'G83',
    'G29',
]
for line in lines:
    print(pygcode.text2gcodes(line))

will give

[<GCodeLinearMove: G01{E3, X1, Y2}>]
[<GCodeDrillingCycleDwell: G82>]
[<GCodeDrillingCyclePeck: G83>]
[<GCodeAutomaticBedLevel: G29>]

I doubt passing these into a virtual Machine will do what you expect.

fragmuffin commented 6 years ago

Thanks for raising this issue @revarbat ! this really helps me make this library useful.

revarbat commented 6 years ago

The variants plan in #9 sounds excellent. One correction, though, is the E axis relative/absolute mode codes are M82 and M83, not G-codes. So, no conflicts with standard GCode, I think. But how does the parser return them?

fragmuffin commented 6 years ago

oh!, of course, my mistake. then there's no conflict.

# Add M82 / M83 gcodes
class GCodeExtruderAbsoluteMotion(pygcode.GCode):
    word_key = pygcode.Word('M', 82)

class GCodeExtruderRelativeMotion(pygcode.GCode):
    word_key = pygcode.Word('M', 83)

but still, they won't be modal until I've done #9.

@revarbat: do you have a pressing need to have this done soon?

IanCarr-deAvelon commented 4 years ago

A further problem with 3d printer gcode is that S has other uses and pygcode takes them all as spindle speed changes. Eg M420 S1 = retrieve bed leveling from memory M106 S255 = set cooling fan power to $FF ie. max Probably all Ms should be dealt with separately. Yours Ian

petaflot commented 3 months ago

see https://github.com/petaflot/pygcode