OpenSCAD and Python looking to finally be resolved

G-Code is a pretty old language and is even an ISO standard.

There are some G-Codes which controller/machine vendors don’t support like not everyone supports Arcs(G2, G3) so CAM generators need to know if they are going to create their own segmented curves or implement the arc G-Code. Probably a few others but the majority is quite standard. Supporting the add-on implemented in M-codes can be tricky but we’re talking about expecting one programming language to support CNC machines of all kinds besides milling, routing, plasma cutting, water jet cutting, lasering and FFF machines. There’s lots of variations bumped on one programming language. Probably why you don’t see Klipper on every other kind of machine out there. But surprisingly, the ~30 year old LinuxCNC(EMC) has been validated by me to be capable of driving lasers with LightBurn output(post processed), 3D Printer(Ender 3) from Prusa Slicer output and of course CNC machines. I think it’s one of the older/oldest G-Code processors around.

1 Like

There are significant differences in how different controllers handle the features that either aren’t in the standard or weren’t when the manufacturer first implemented them. Look up Haas and Okuma canned cycles, variables, and mid-program probing validation as examples. Haas and Okuma also handle multiple work offset, lathe stock feeders, and five axis milling in different ways.

None of it is insurmountable but it also isn’t trivial.

2 Likes

So is the C programming language, and it can still be a chore to port between operating systems, even when using the same compiler; even more so with different compilers.

2 Likes

My experience is only with the basics of LinuxCNC and the various buffered firmware systems(Marlin, GRBL, Sailfish, etc) and generally at that level hardware vendors have been sticking with mostly the generally supported firmware so most CAM works the same.

And article or video I watched seemed to imply that companies who make large commercial machines add lots of their own features to both their control firmware and their control software if it’s different.

The only thing I can point out about G-Code vs C is that G-Code is more specifically aimed at NC machinery while C is very much a general purpose language. But I get the comment about porting to different OSs.

1 Like

Well, I think there are quite a few parallels. Here are some off the top of my head.

  • Difference in standards interpretation. G codes that act a little differently on different machines seem analogous to trying to port from most versions of Unix to VMS with certified POSIX compliance, or far worse, to SCO UNIX (what a steaming pile of broken junk that was).
  • Missing pieces: Lack of many commands, such as G2/G3 arcs, are kind of like trying to port full code written on a full POSIX OS to a microcontroller (though with today’s microcontrollers running microcontroller OSes make this easier, of course).
  • Optional libraries that occasionally have incompatible overlap remind me of M codes where it’s not that unusual to have the same M code do completely different things on different hardware.

Yes, I think naturally the open CAM sw, firmware, and controllers do a better job of staying in sync since they’re often used together and often are developed by the direct users.

I’m pretty grumpy with the commercial CNC sw developers and manufactures because they love lock-in via non-standard features. Maybe Tormach is better since they use LinuxCNC?

1 Like

The installation for this has been updated and now uses a normal Python:

https://www.python.org/ftp/python/3.11.5/python-3.11.5-amd64.exe

Hello on Makerforums!

I was just curious to learn about the company which you funded into and later on got employed by,
but it appears the links are dead ?

1 Like

Yes, For Firmware see some of the work that Duet3D have put into RRF recently. It’s a formidable beast these days in terms of geometries, axes aand sensors. This explicitly targets general commercial NC applications.

I suspect there are an awful lot of old PC’s with ISA/PCI IO extenders, or PI’s etc out there in the bowls of big industrial machines running LinuxCNC or some specialist fork/hack or it.

I think path generation for (say) six-axis milling is often AutoCad + some very expensive plugins and extensions.

1 Like

I work for Carbide 3D:

https://carbide3d.com

and came to it by way of the Shapeoko project/wiki, which was originally an opensource project:

http://shapeoko.github.io/Docs/

but the wiki has since gone away (but is gradually being brought back at: index - shapeoko )

and since then I’ve been working off and on on a book:

2 Likes

After experimenting on this a bit, I worked up a file, gcodewrite.py:

def writeln(*arguments):
    line_to_write = ""
    for number in arguments:
        line_to_write += number
    f.write(line_to_write)

fn = "gcode.nc" 
f = open(fn, "w")

which I import by setting the preamble in OpenSCAD Graph Editor to:

//!OpenSCAD

use <gcodewrite.py>

$fa = 4;
$fs = 0.0625;

which is working well:

But it seems AFAICT that loading Python modules isn’t reliable for some reason, and that it isn’t possible to have a persistent file handle between Python function calls, so this is being shelved until the next release.

There is now a new version which while it doesn’t change the fundamental architecture, it does add support for the Customizer:

1 Like

In corresponding with the developer, I’ve learned/come to understand a couple of things:

  • when loading a Python file from OpenSCAD, arbitrary code is not processed — only function definitions are used to define functions for later usage
  • variable redefinition does work for variables in Python

There’s at least one person on the OpenSCAD mailing list trying to build this on the Mac — but no word on when it will be merged into the main branch and become available from openscad.org

Curious if anyone else has tried this and if so, to what effect.

I guess there are a couple of notable options:

  • just use Python for 3D modeling, w/ OpenSCAD as a front-end
  • call Python from w/in OpenSCAD and use Python for the heavy-lifting in terms of programming
  • use Python to facilitate writing out DXF or SVG files which can then be combined — there’s already one tool for re-processing SVGs from OpenSCAD and combining them to facilitate laser output
  • write using/model with/output G-code as I’ve been trying to do
2 Likes

I’ve been experimenting further, and have worked out a couple of things:

  • the error reporting, esp. when calling Python from OpenSCAD is not robust or thorough
  • because of that it’s better to write in pure Python to define things

Doing this, I’ve managed to arrive at a proof-of-concept which at least writes to a file:

Gcode_filename = "gcode.nc"
a = 3


def opengcodefile(fn):
    global f
    f = open(fn, "w")

def writeln(*arguments):
    line_to_write = ""
    for element in arguments:
        line_to_write += element
    f.write(line_to_write)
    f.write("\n")

def closegcodefile():
    f.close()

opengcodefile(Gcode_filename)

writeln("Test")

writeln(str(a))

closegcodefile()

which is something I can build on to make something a bit more useful.

1 Like

The equivalent OpenSCAD code for that would be:

gcodewrite.py

def opengcodefile(fn):
    global f
    f = open(fn, "w")

def writeln(*arguments):
    line_to_write = ""
    for element in arguments:
        line_to_write += element
    f.write(line_to_write)
    f.write("\n")

def closegcodefile():
    f.close()

and then an OpenSCAD file:

//!OpenSCAD

use <C:\Users\willa\OneDrive\Documents\OpenSCAD\libraries\gcodewrite.py>;

/* [G-code] */
Gcode_filename = "gcode.nc"; 

a = 300;

opengcodefile(Gcode_filename);

writeln("Test");

writeln("Second");

writeln(str(a));

writeln("Final");

closegcodefile();

which of course creates the file gcode.nc:

Test
Second
300
Final
1 Like

A slight variation on the above, instead in OpenSCAD, using the same gcodewrite.py we instead have:

//!OpenSCAD

use <C:\Users\willa\OneDrive\Documents\OpenSCAD\libraries\gcodewrite.py>;

module writecomment(comment) {
    if (generategcode == true) {
	    writeln("(",comment,")");
    }
}

/* [G-code] */
Gcode_filename = "gcode.nc"; 
/* [G-code] */
generategcode = true;

a = 300;

opengcodefile(Gcode_filename);

writecomment("Test");

writecomment("Second");

writecomment(str(a));

writecomment("Final");

closegcodefile();

which creates the gcode.nc file:

(Test)
(Second)
(300)
(Final)
1 Like

There are two ways to incorporate files into OpenSCAD:

  • use — this will allow definitions in either Python, or in OpenSCAD and using a mix of OpenSCAD and Python code
  • include — this allows using variables from the main OpenSCAD file, but does not allow directly making use a function defined in Python

Since we want to be able to turn on/off calling Python from w/in OpenSCAD we require a total of 3 files:

  • a Python file which is loaded using use <gcodepreview.py>; — this is able to define Python functions
  • an OpenSCAD file which is loaded using use <pygcodepreview.scad>; — this wraps the defined Python function in OpenSCAD
  • an OpenSCAD file which is loaded using include <gcodepreview.scad>; — this allows using OpenSCAD variables from the main file to determine whether or no an OpenSCAD module which calls a Python module should be called

Thus we have:

gcodepreview.py

def popengcodefile(fn):
    global f
    f = open(fn, "w")

def writeln(*arguments):
    line_to_write = ""
    for element in arguments:
        line_to_write += element
    f.write(line_to_write)
    f.write("\n")

def pclosegcodefile():
    f.close()

pygcodepreview.scad

//!OpenSCAD

module oopengcodefile(fn) {
    popengcodefile(fn);
}

module owritecomment(comment) {
    writeln("(",comment,")");
}

module oclosegcodefile() {
    pclosegcodefile();
} 

gcodepreview.scad

//!OpenSCAD

module opengcodefile(fn) {
if (generategcode == true) {
    oopengcodefile(fn);
    }
}

module writecomment(comment) {
if (generategcode == true) {
    owritecomment(comment);
    }
}

module closegcodefile() {
    if (generategcode == true) {
    oclosegcodefile();
    }
}

which is all put together by an OpenSCAD file:

//!OpenSCAD

use <gcodepreview.py>;
use <pygcodepreview.scad>;
include <gcodepreview.scad>;

/* [G-code] */
Gcode_filename = "gcode.nc"; 
/* [G-code] */
generategcode = true;

a = 300;

opengcodefile(Gcode_filename);

writecomment(str(a));

writecomment("Test");

closegcodefile();

which when run, creates the file:

gcode.nc

(300)
(Test)

Success!

3 Likes

Put together a bit more on this — made a template file:

Place the library files:

in the OpenSCAD library folder to get a gcode file:

2 Likes

First formal, versioned release:

and in addition to writing out G-code so as to cut files, it now has an option to write out polylines — which may be open/unclosed.

The sample/template file should be pretty-much self-explanatory and I will hopefully manage to get some more interesting things working presently.

2 Likes