Idea: CoolRunning-Plugin


for my plugin-development I used the "Virtual-Printer", but for final testing I use my "real-printer".
In most cases I removed the filament, heating up the printer and start testing my plugin.

Would it be nice, if it's possible to start a print without heating and extrusion?
(or fireup the movement-speed :wink:

The plugin "Octolapse" has an build-in "test-mode", maybe it is possible to extract this to a "single-feature/plugin".

Before I start implementing my own plugin, what do you think?



I actually considered this before. In my version, I was imagining having one of those artist's models (made out of wood) and it's standing on the print bed. I would then create a timelapse-like video in which I use the print head to bump or otherwise position the model over time. But that would be a little too problematic to make actually work...

So then I imagined a different video in which the extruder assembly "dances", basically, to the background music. I considered making a plugin which would programmatically listen to music, as played, and then translate this into a geeky/robotic dance-like movement by the assembly. Either way, you don't need to heat, extrude or to control the fans in these scenarios, like yours.

Honestly, it sounds like what you need is either 1) something to ignore a subset of GCODE commands as seen or 2) something external to post-process the GCODE to comment-out or otherwise remove the parts you don't want. As a plugin, that would be the first. These days, I find writing processing scripts using the Go language to quickly process things easier, for what it's worth.

I conceptually called mine "dry run", by the way. It would be nice to just watch the printer go through the motions of a particular layer in the same way that a choreographer would ask the dancer(s) to take their places and perform a certain part of a show.


If you need any help extracting the test mode code, let me know. Or you could just use Octolapse and disable the snapshots :slight_smile:


@OutsourcedGuru The topic "CoolRunning" should act as a "clickbait" and it is not the final name :wink:

@FormerLurker Thx, for your offer. I will take a closer look to your sourcecode...if I have time.

So, it's on my list. I will start developing such general "dry run" plugin in near future.
Maybe I start with a UI-Mockup to discuss the behaviour.....or maybe it is to simple...will see.






You're really on fire aren't you :slight_smile:


  1. You will need to parse any G1 and G0 commands so that the E parameter can be removed (prevent extrusion)
  2. It might be a good idea to send 'cool down' and 'fan off' gcodes automatically when the print starts (this is not in my implementation).
  3. You might want to add a list for custom Gcode addresses to suppress. That is missing in my implementation ATM. Who knows what wacky codes folks will want to remove!

Here is my current list for suppression:

# Remove the E parameter if it exists for these commands
TestModeSuppressExtrusionCommands = G0.Command, G1.Command
# Prevent these commands from being sent, no rewrite necessary
TestModeSuppressCommands = [
        M104.Command, M140.Command, M141.Command,
        M109.Command, M190.Command, M191.Command,
        M116.Command, M106.Command


For fun, I added dryrun to my GcodeEdit compliled Go program (command line interface). I watched it now perform perfectly on my printer, going through the motions.


If you're on OSX, you can just pull down the executable. Otherwise, if you know the Go language, the source is there so that you can play with it.

It will comment-out any of the following plus remove any extrusion commands it sees inline for either G0 or G1 and will quash orphans as a result of that.

	M104 Set extruder temp
	M109 Set extruder temp and wait
	M140 Set bed temp
	M190 Wait for bed temp to reach target
	M141 Set chamber temp
	M191 Wait for chamber temp to reach target
	M116 Wait
	M106 Fan on
	M107 Fan off
	M101 Turn extruder 1 on
	M102 Turn extruder 1 on reverse
	M103 Turn all extruders off
	M128 Extruder pressure PWM


For the record, some firmwares actually include the dry run feature.

I've used it many times (repetier firmware), not entirely sure if marlin supports it though. Even made myself a little plugin to easily set the debug flags (only works with repetier firmware).

So for anyone using repetier firmware, you can just run your normal, unedited, gcode through it in dry run mode and it'll automagically ignore all the heating / extruding commands.


I collected all information from you and started with the UI.
Here are some screenshots:


What do you think, is something missing?


Well... technically your code on line 1 can sometimes create orphans. Imagine this line:

G1 F600 E12.3

So now line 1 kicks it's butt and it looks like

G1 F600

...which does what, exactly? Will this change the speed of the commands which follow? I dunno. Will it cause some sort of other mischief?

So my approach was to then follow-up with this safety code after my version of your line 1 above runs:

						orphanedFCommand, err := regexp.MatchString("G[0-1] F([0-9]+)[ ]?$", saveline)
						if (err == nil && orphanedFCommand) {
							// In some cases, this then leaves nothing but G1 F2400 left after
							// the removal of the extrusion command; let's lose that, too.
							saveline = ";" + saveline
							if (*verbose) {fmt.Printf("  Commented: %s\n", saveline)}
						} // if (err == nil

So I'm looking for a G0/G1 which only includes an Fn which is anchored at the end of the string and I just comment it out.


Thanks for the hint and also for the solution.
I will add the two expressions on the top and but the "remove" expression to the bottom.

match [^G[0-1] E[+]*[0-9]+[.]*[0-9]* F[0-9]+] single extrude, feedrate at the end
match [^G[0-1] F[0-9]+ E[+]*[0-9]+[.]*[0-9]*] single extrude, feedrate at the beginning


I suppose it would be correctly if you also do the version in which the G0/1 En doesn't include the feedrate... after those two above. If you did the naked version first, then the orphan doesn't match, get it?


I don't think commands such as G1 F100 are 'orphaned' at all. This would set the feedrate for commands that follow this one, and your slicer may rely on this for subsequent commands.

TLDR, you should definitely keep the 'naked' feedrate and send it to the printer.

Edit, change question mark to period


One more thing, I found that using regex to parse gcode is daunting. Initially I was using this technique for my plugin, and found that things were way easier to use a regex for each parameter. However, I found that even this doesn't work all the time either (I can elaborate if you want) and ended up writing my own parser. Let me know if you ever think about switching.


I'd be curious to hear this one.


@OutsourcedGuru, I was afraid you'd say that, lol! Check out this issue. Basically I learned that spaces could be added or removed anywhere within a valid gcode line and the result is also valid gcode. I'm not sure if every printer can handle this (probably not), but the Taz6 at least could. Also i learned that decimals can include a + (I already took the - into account).

As I tried to take every newly discovered situation into account my regex got crazier and crazier, until I decided to scrap my original code to try another approach. Unfortunately my parser now will likely accept gcode that many machines cannot interpret, but I figure it's better than misreading gcode that the printer CAN handle. I'm sure there are still improvements that can be made, but now I don't need to write any regex if I want to handle a new gcode, I just need to add a new command object to my list of accepted commands. The rest I just ignore.

Here is a command definition I created for G0 which contains the command address, a friendly name, a display template, the accepted parameters and the associated parameter value parsing function. Each paramater also includes a display order used when converting a command object back to a string:

G0 = Command(
        "Rapid linear move",
        "G0 - Linear move to X={X}, Y={Y}, Z={Z}, E={E}, F={F}",
            "X": CommandParameter("X", CommandParameter.parse_float, 1),
            "Y": CommandParameter("Y", CommandParameter.parse_float, 2),
            "Z": CommandParameter("Z", CommandParameter.parse_float, 3),
            "E": CommandParameter("E", CommandParameter.parse_float, 4),
            "F": CommandParameter("F", CommandParameter.parse_float_positive, 5)

This object is added to a command dictionary and for 'cool running mode' is also added to a list of commands that should have the E parameter stripped. Another list is maintained for commands we want to completely suppress in this mode.

Let me know what you think about this, especially if there are obvious flaws in my logic that I'm overlooking.


Thanks for all the work to type that up. I had no idea how loose the specification was. (And I'm usually the one to point out that 1E1 is actually a number to my students.). I wonder how the printer would do with this one G1 E-1E10? :evil laugh:


There is no actual specification, that's the problem :wink:


I REALLY hope that doesn't work :slight_smile:


In theory, that's a 100mm retraction.