Are there notes anywhere about the most compact form of GCode that Smoothie accepts?

Are there notes anywhere about the most compact form of GCode that Smoothie accepts? Specifically I’m looking for:

  • Is it legal to omit the leading zero before a decimal?
  • Are spaces required between codes (the Wiki mentions this)
  • Is it legal to send multiple G1 commands on a single line, effectively using it as the separator (instead of newline)?
  • Does Smoothie deal gracefully with multiple switches between G90 and G91? (as in, for rastering, I’d flip to G91, then back to G90 for normal vector work)

I’ve got Smoothie support running and I’m just trying to make sure the performance is as high as it can be.

No ( or I don’t think so ).
Not in most cases.
It could work but not sure if reliably
Pretty sure.

Note G1/G0 is modal so you can do things like :
G1 X10
X20
X10

I think the most compact way to send gcode is something like this :
G1X0.1S0.1
X0.1S0.2
X0.1S0.3
etc

I’m already doing that (without the G91 switch), but I was under the impression from reading other threads that packing more commands into single lines would result in fewer ‘ok’ responses, and allow for higher throughput. My app is already beating the http://fast-stream.py script on Windows for throughput, I was just curious if it could be pushed further.

The leading zero trim would make your example:
G1X.1S.1
X.1S.2
X.1S.3
(roughly a 20% reduction)

I’ve seen GCode “in the wild” that did that, but I wasn’t sure if Smoothie would accept it. I’ll likely give it a go and see what happens. Thanks for the quick reply!

@Wolfmanjm I know you already gave this info but would you mind giving a refresher ? @Jason_Dorie is trying to get fast raster from Windows, and I think seeing how fast he can get would be very interesting and might disprove some misconceptions that have been roaming around.

@Jason_Dorie Would you mind documenting ( with numbers ) the speeds you are seeing ? The more data the better, it’d really be very helpful.

I think my last run I was getting about 610 gcode lines / sec, or about 6kb/sec, and the fast-stream script hit 550 on the same file. I’m emitting dithered pixels, so basically alternating S0 and S0.5 (or whatever the second code ends up being). I’ll change it to G91 mode tonight and re-test. I’m doing alternating reads / writes in a thread into/out of a pair of ring buffers, so the comm code should be able to run as fast as the OS allows. The higher level sender counts outgoing lines and incoming ok’s, and as long as I’m not more than 10 ahead I just shove them out. I’ve tried letting it run “un-tethered” but it locks up, so I’m not positive Qt / Windows is properly using the hardware flow control.

Following. That approach (10 lines), if it works without blocking the sender thread, may be what we need.

Can the baud-rate setting on the Smoothie config go above 115200? Has anyone tried just creating a dumb reader on the Smoothie hardware that just eats data as fast as possible, to see what the upper limit is per operating system?

Smoothie talks at whatever baud rate the host program is at. That 115200 value you are seeing is specifically for the hardware serial port (read: rx and tx pins on board’s serial header). You can talk to Smoothie at 250k baud (or try higher) and that’s that, without having to touch the config.txt.

This is mildly interesting - I modified my gcode sender to use relative instead of absolute coords, and the overall data size transmitted went down, but the processing time barely changed. The “bytes per second” value went down, implying that it may actually be hitting a buffering limit, not something else. I’m running these at 150mm/sec, from a dithered image, pixel size of 0.2mm, so the gcode commands are really short.

Absolute coords
107300 lines sent in 179.709 seconds, or 597.076 lines per second
1071256 bytes at 5961.06 bytes per second

Relative coords
107996 lines sent in 180.37 seconds, or 598.747 lines per second
1025956 bytes at 5688.06 bytes per second

Relative with leading zeros removed
107284 lines sent in 178.821 seconds, or 599.952 lines per second
859158 bytes at 4804.57 bytes per second

I’m not certain this isn’t somehow my fault - I am keeping myself within 10 lines ahead of the ‘ok’ responses, so it’s possible it’s still effectively line throttled. I’m going to keep poking at it.

Here’s a link to the generated gcode if you’d like to try it: https://drive.google.com/open?id=0B7LY8p6DmhEAYjY5aVUtUENnUVk

Ignore the baud rate; it doesn’t matter since there is no serial port. It’s only there because the USB CDC class was designed for usb-serial converters.

I tried different baud rates, but as you said it made no difference.

The buffer is only so long and 0.2mm moves are pretty short.

Agreed, but for raster image processing that’s on the large side. I do notice that it runs significantly smoother over the parts of the image that have a sparser dither pattern (dark or light portions) which makes me think this is just the planner filling up and not being able to push any harder. Also, I lied - I was actually sending 0.1mm pixels. Bumping it to 0.2mm does make it run considerably smoother, which is also evidence that it’s just a full buffer.

When you say “the buffer is only so long” - I assume this is the plan buffer? 32 codes by default, if I’m not mistaken?

Would it be feasible to have a longer look-ahead just for delta x moves (or delta y), where the sign is the same and the feed rate doesn’t change? The planner is looking to see “how far do I have to stop, if I need to?”, so if you had a way of tagging x or y only moves where the feed rate didn’t change, you could potentially seek further ahead with relatively low processing because you wouldn’t need a full plan for those moves - could you “fake extend” the current move? (I’m speaking off the cuff here - I don’t know the guts, so feel free to shut me down).

I’ll have to defer to those that know the internals more. But I think such short moves break acceleration such that you’ll never get up to speed.

…that was kind of my point - If you know you have a dozen short moves in exactly the same direction, for the purpose of acceleration you could treat them as a single, longer move. If I understand right, the only reason to limit your speed is to be sure you can stop in time. If you could tell that your next 60 moves were all in positive X, the accumulation of those moves is now how far you know you’re traveling, but only a special case for delta-x or delta-y moves. Like I said, not sure how feasible it is, but it shouldn’t take nearly as much horsepower as doubling the size of the plan buffer.

From Jim Morris :
[…] sending less [data] makes no difference or very little. [ this is not how it works ] It is not bandwidth limited over a decent USB.
however stopping every 10 lines is going to severly limit the throughput. You MUST totally decouple the sending lines with the reading OKs
the example fast-stream makes that very clear. Currently he is getting about half the throughput he could be getting if he was doing it properly
he is not using a decoupled read/write threads.
which is why it is so slow
and also why it hangs when he just sends he gets deadlock in the O/S
I think macos is broken in this respect the USB I/O is not thread safe
[…]
well http://fast-stream.py works best for me
I have a c++ version that may work if python on mac is broken. Also point him at that thread where we worked out what was the issue.
[ he means : https://github.com/Smoothieware/Smoothieware/issues/1096 ]
but sending 10 lines and waiting for 10 oks is not much better than sending one line and waiting for one ok, anytime you stop to wait for ok the system stalls
you just need to consume the ok as fast as you can but never wait for it
I also have a fast stream mode built into the smoothie host code, using asyncio. not sure it is any better or worse though
also you get 1 ok per LINE not per gcode
and you can have multiple gcodes on one line, no spaces needed however I think .1 is illegal must be 0.1
that is standard NIST AFAIL
AFAIK
the upper limit for 0.1mm pixels (and 0.2mm) is the planner which can at max do about 1000 pixels/sec fedeing it faster won’t help

Listen to Jim, he knows how this works :slight_smile:

« Would it be feasible to have a longer look-ahead just for delta x moves (or delta y), where the sign is the same and the feed rate doesn’t change? »
What you really want is a modal raster mode where you only receive power values ( movement lenght and speed stays constant ) and it skips the planner and just moves and sets power separately.
It’d be a week or so of work to code, but nobody has done it so far. I hope somebody will jump in at some point and do it.

I’m not sending 10 lines and waiting for 10 oks though - I’m sending lines and receiving oks, decoupled, and only pausing the line send if I get further than X number of lines ahead of the ok counter. Setting X to 10, 12, and 16 all have the same performance, as does reading from the SD. http://Fast-stream.py is registering slightly lower throughput than mine. Try the Gcode link I posted - I’d be curious to see if it performs better on Unix.

FWIW I had already read the full thread Jim mentioned, and numerous others, and looked to http://fast-stream.py as the benchmark implementation knowing that I needed to decouple reads and writes.

I think I actually am just hitting the processing limit here - I’ve set this to run at 150mm/sec, so any time I hit “full density” on a line it slows down (that’d be 1500 pix/sec). The lines with less dither run full speed because they don’t contain as much data.