OctoPrint / Plugin-Examples

MIT License
20 stars 18 forks source link

Missing example how to replace one gcode line with multiple lines #1

Open mrvn opened 8 years ago

mrvn commented 8 years ago

The octoprint.comm.protocol.gcode hook allows removing or rewriting gcode during printing. But how do I replace one gcdoe with multiple?

The problem I want to solve is the backlash correction for the M3D printer. The current plugin corrects this during slicing, resulting in a totaly eratic tool path in the gcode viewer. I want to do this during printing instead so the viewer still sees the clear code. But for this little movement commands must be inserted before changes in direction. E.g. if I have G1 X0 E0 G1 X10 E10 G1 X0 E20 then the head will not end up at X0 due to backlash. Before the 3rd line a "G1 X9" must be inserted followed by "G1 X-1 E20". So I need to both insert and rewrite. Do I just return "G1 X9\nG1 X-1 E20" then? Is that allowed? Is there a better way?

Salandora commented 8 years ago

I guess it would be better here to do an serial factory plugin.

Or you could try and do something like this "G1 X9 G1 X-1 E20" based on your firmware this may or may not be supportet.

markwal commented 8 years ago

How about using this: http://docs.octoprint.org/en/master/plugins/hooks.html#octoprint-filemanager-preprocessor?

And you might be interested in the sources of this plugin: http://plugins.octoprint.org/plugins/commandsplitter/

mrvn commented 8 years ago

Doesn't octoprint-filemanager-preprocessor also affect what the previewer sees? The M3d-fio plugin currently does all its preprocessing when slicing and the preview is totaly useless since, with bed level correction, every single gcode ends up with a different z. So the preview things you have 435873648 layers, all consiting of a single move. It is important to me that the correction only happens during print so the preview remains functional.

foosel commented 8 years ago

The comm hooks currently don't allow multiple lines to be returned as a replacement for one, an oversight on my part which I intend to correct.

Until then you could try hooking into the "queuing" phase though, manually queue your multiple lines and suppress the queuing of the actual command.

Something like this (untested at the moment):

def queuing_hook(comm, phase, cmd, cmd_type, gcode, *args, **kwargs):
    if this_is_my_command(cmd):
        comm._sendCommand("G1 X0 E0")
        comm._sendCommand("G1 X10 E10")
        comm._sendCommand("G1 X0 E20")
        return None,

__plugin_hooks__ = {
    "octoprint.comm.protocol.gcode.queuing": queuing_hook
}

The sending queue has a reentrant lock, so that should work without causing dead locks. It is admittedly quite dirty and only a workaround until the phase hooks allow returning multiple commands.

mrvn commented 8 years ago

That sounds promising. One thing is unclear to me though.

For backlash compensation the algorithm needs state, specifically a history of past moves. E.g. if the X axis was incremented last and now is decreased a backlash compensation needs to be inserted. Storing this globally in the plugin sounds like a bad idea (e.g. what if you later have 2 printers printing at the same time?). Do I piggy back that into the comm object? Or would a serial factory as poposed above be cleaner there?

foosel commented 8 years ago

Since OctoPrint currently only supports one concurrent printer connection anyhow (you need multiple instances for multiple printers, which naturally don't share their state), there's nothing to worry about with regards to that.