Category Archives: Technology

Virtual G-code Controller vgcodectl

Status: experimental, not yet released

Updates:

  • 2022/11/29: covers 0.1.6 API
  • 2022/10/31: published
  • 2022/10/28: starting write up

Introduction

As I was developing the 5-axis PAX printhead, and implement Inverse Kinematic (IK) for it in RepRapFirmware (RRF) for Duet3 board, the development speed was slow due the overhead to get to know the RRF written in C++, hence very verbose code, and the “recompiling, uploading, and reboot of the board” cycle to iterate the development – which turned out to be very slow and tedious.

My first remedy was to do a pre- or post-processor which takes tool coordinates and converts into motor positions applying IK, and Print3r supports it via declaring a post-processor like --post_something=something %i %o and then use with --post=something, but would only be a Print3r-centric solution.

So I thought, why not do a virtual serial device, and have a framework where the controller behaves like a physical one, but is pure software and thereby shorten development cycle to convert G-code coming out of a slicer or some software and then being processed and then sent to the 3D printer or robot – so the Virtual G-code Controller (vgcodectl) was born.

It’s main feature is that it operates bidirectional:

  • it takes input and optionally changes it, and outputs it to a file or a device
  • it takes output from a device, and forwards it back to the virtual serial to so it can read back transparently

in essence it operates as in bidirectional intermediary looking like a serial port and thereby can be integrated into existing G-code-based machine park.

slicer/console/controller ⇆ physical device

slicer/console/controller ⇆ vgcodectl ⇆ physical device

as a result the setup looks like a capability extended device:

Features

  • simple to write G-code extensions with Python:
    • execute macros and calculate additional values
    • code execution from G-code
    • synchronize G-code with external devices, e.g. webcam
  • extend drivers/controller, like Inverse Kinematics (IK) which otherwise would run on the controller
  • live reloading of controller code: change printer/robot behavior while it’s processing G-code
    • fast iteration of code due scripting (no compiling, uploading or reboot)
  • supported platforms: Linux

Limitations

  • line-based processing: one line comes in, one line or multiple lines comes out (future version might lift this constraint)

Usage

% vgcodectl -h
VirtualGcodeController 0.1.4 USAGE: [<opts>]
   options:
      --help or -h               this help
      --version                  display version & exit

      --verbose=<n>              increase verbosity
         -v or -vvv
      --quiet or -q              don't output to device or console anything unless an error

      --output=<device/file>     set output, e.g. /dev/ttyUSB0 or file or another device (default: /dev/stdout)
         -o <device/file>
      --controller=<ctl>         set controller (default: conf['output'])
         -c <ctl>
         
      --keep-orig or -O          enable to keep original g-code line as comment (default: off)
      --keep-comment or -C       enable to keep original comment (default: off)
                                    hint: --keep-orig/-O includes comment as well
      --serial-speed=<s>         set serial speed [baudrate] (default: 115200)
      --serial-timeout=<s>       set serial timeout [s] (default: 0.1)
      --check-code-timeout=<s>   set code checking timeout [s] (default: 1)
      --output-value-format=<fmt>  set output value format (default: .4f)
      
   examples:
      vgcodectl --output=/dev/ttyUSB0 &
      cat test01.gcode > pass0.pty
      print3r --device=pass0.pty print tests/test01.gcode
      print3r --device=pass0.pty print --scad 'cube(20)'
      
      vgcodectl -o /dev/ttyACM0 -c gcode+ -Ov

Let’s try pass2 controller, which doubles X, Y and Z coordinates.

As first we start the controller:

% vgcodectl -c pass2 -O
== VirtualGcodeController 0.0.3 == https://github.com/Spiritdude/VirtualGcodeController
; VirtualGcodeController 0.0.3, created 2022-10-28T13:23:23.513285
;   verbose = 0
;   output = "/dev/stdout
;   serial_speed = 115200
;   controller = "pass2"

In another terminal we take a sample G-code and send it into pass20.pty serial port (“pass2” plus the “0” indicates the first instance of pass2 controller):

% cat tests/test01.gcode > pass20.pty

and the vgcodectl outputs to stdout as it is the default:

G28 X0 Y0 ; G28 X Y
G92 ; G92   ; reset
G90 ; G90   ; abs coords
G0 X200 Y200 ; G0 X100 Y100
G1 X200 Y220 E1.2000 ; G1 X100 Y110 E1
M84 ; M84

As you notice, the new G-code is altered, e.g. X, Y and Z is doubled, the E is multiplied by 1.2 in this case, and the original G-code is appended as comment due the -O switch used (--keep_orig or -O).

If we did call vgcodectl with --output=/dev/ttyACM0 the end point would be a real 3D printer for example at /dev/ttyACM0.

Print3r

% print3r --printer=ashtar-k-3 --device=pass20.pty print tests/test01.gcode
== Print3r 0.3.18 == https://github.com/Spiritdude/Print3r
print3r: conf: device pass20.pty, Ashtar K #3 E3 38x30x33, build/v 300x300x330mm, nozzle/d 0.4mm, layer/h 0.25mm, filament/d 1.75mm
print3r: authenticated "Ashtar K #3 E3 38x30x33" (8a09209a-1b93-11ed-861d-0242ac120002) at pass20.pty
print3r: print: 0h 00m elapsed, eta 0h 00m, 100.0% complete, z=0.00mm, layer #0, filament 0.00m  

as indicated, the pass20.pty operates bidirectional, reports back the proper UUID as requested by print3r and then sends G-code forward and does proper synchronous messaging back and forth.

print3rpass2*.pty:vgcodectl/dev/ttyACM0

Controllers

Following controllers are available:

  • pass: it’s a simple pass-through changing no code, for debugging purposes
  • pass2: double X, Y and Z, and multiply E by 1.2
    • don’t use with actual 3D printer, only for debugging purposes
  • scale: scaling X, Y, Z and E, rather experimental / for debugging purposes
    • CLI argument: use --scale=<s> to set scale in , e.g. 0.8 (default: 1.0)
    • actually produces some working G-code
  • gcode+: writing low-level G-code and replace E automatically based on distance
    • use G0 X100 Y100 and then G1 Y110 E and the G1‘s extrusion will be calculated
    • actually produces some working G-code
    • CLI arguments:
      • --layer-height=<lh> [mm] (default: 0.2)
      • --line-width=<lw> [mm] (default: 0.4)
      • --filament-diameter=<d> [mm] (default: 1.75)
  • delta: implementing cartesian XYZ -> T1,T2,T2 motor angles, using Delta printer inverse kinematics
  • pax: implementing 5-axis inverse kinematics for PAX printhead
  • 5axis: generalized 5-axis driver, define forward kinematics, automatic inverse kinematics calculated:
    • open5x: Open5x
    • pax: PAX Printhead, same as pax controller, but defined within 5axis controller
  • macros: implementing RepRapFirmware’s M98 functionality

Download

Writing A Controller

Note: vgcodectl is currently under heavy development, API subject to change a lot – check back this page frequently.

This covers vgtcodectl 0.1.6 API:

  • controllers/<controller> /:
    • main.py
      • must contain def _map(self,c=None) function, in there you can recalculate any existing G-code, the c contains a dictionary with all the G-code values, the function returns
        • a dict of the remapped variables, e.g. { "G": 0, "X": 100.0 } – note: order matters, make sure ‘G’ or ‘M’ key comes first for G or M commands
        • a string, e.g. "G0 X100.0" or G0 X100.0\nG1 X110 E1.2"
        • a tuple or list of
          • strings, e.g. [ "G0 X100.0", "G0 X110.0" ], each element is a line
          • dictionaries, e.g. [ { "G": 0, "X": 100 }, { "G": 0, "X": 110 } ], each element is a line
        • if None is returned, no change of G-code is made and the original data is passed on
        • if "" (empty string) is returned, nothing is passed on (mute)
      • optionally def __init__(self,conf=None) function be composed, where persistent state can be stored, and referenced in _map() then; the conf is the configuration of vgcodectl:
        • command line arguments vgcodectl --test="ABC" ... becomes conf['test'] available within __init__(), the controller profile profile.json is loaded and available as conf['profile']
        and if you store conf as self.conf then _map() has access to it as well with self.conf['test'] or self.conf['profile']['name']
    • profile.json (optional):
      • basic JSON file with follow keys:
        • name (string): full name of the controller
        • version (string): version of the controller, e.g. “0.1.0”
        • and any other key value default relevant for the controller

e.g. controllers/mine/main.py:

def __init__(self,conf=None):
   pass

def _map(self,c=None):
   if 'X' in c:
       c['X'] *= 2
   return c

then the controller can be referenced as such:

% vgcodectl -c mine -v
== VirtualGcodeController 0.0.7 == https://github.com/Spiritdude/VirtualGcodeController
vgcodectl: 2022-10-31T06:48:14.026650: loading <mine> profile
vgcodectl: 2022-10-31T06:48:14.026705: loading <mine> code
vgcodectl: 2022-10-31T06:48:14.027444: created mine0.pty (/dev/ptmx,/dev/pts/7)
vgcodectl: 2022-10-31T06:48:14.027473: opening /dev/ptmx
; VirtualGcodeController 0.0.7,  2022-10-31T06:48:14.027622
;   verbose = 1
;   quiet = 0
;   output = "/dev/stdout"
;   keep_orig = 0
;   keep_comment = 0
;   serial_speed = 115200
;   serial_timeout = 0.1
;   check_code_timeout = 1
;   output_value_format = ".4f"
;   ignore_codes = ["M117"]
;   controller = "mine"

Scale Controller

The scale controller is just an experiment, to scale G-code with a factor:

% vgcodectl -c scale --scale=0.8 -o /dev/ttyACM0 &
% print3r --printer=ashtar-k-3 print --scad 'cube(20)' --fill-density=0 --device=scale0.pty
cube(20) in –-scale=.8, --scale=1, --scale=1.2 processed with scale controller

References

Misc: More Materials – Testing JLCPCB 3D Printing Services 2022

Updates:

  • 2022/10/26: published finally
  • 2022/09/27: adding measurements and verdict
  • 2022/09/15: starting write up

Introduction

Beside Fused Deposition Material (FDM) /  Fused Filament Fabrication (FFF) aka extruding hot filament, there are more methods to 3D print:

  • SLA (stereolithography): resin based printing
  • SLS (selective laser sintering): laser sintering, like polyamid powder
  • MJF (material jetting): deposite material and binder in one go
  • SLM (selective laser melting): metal laser sintering, aka metal printing

and I choose JLCPCB which provides all four of them, whereas SLM only stainless steel is available as of 2022 – other 3D printing services provide wide-range of metals as well.

Review

I ordered Pulley 20T 6ID (GT2 20 teeth 6mm inner diameter) as created via OpenSCAD Customizer, a piece which requires high accuracy and is mechanical stressed when in use, in following materials:

  • 8x PA12 aka Nylon aka Polyamid, black reflective (MJF), 1.04 EUR / pc
  • 8x 9000R resin, natural white (SLA), 1.04 EUR / pc
  • 8x 3201PA-F aka Nylon, dark gray matte (SLS), 1.04 EUR / pc
  • 1x 316L stainless steel (SLM), 8.30 EUR / pc

after 3 weeks the pieces arrived:

The overall quality of all pieces are excellent, regardless of automatic warnings I received while requesting the 3D printing task.

MJF: PA12 / Polyamid / Nylon

MJF has a nice finish, slightly reflective, deep dark, slightly grainy surface, and the top of the pulley is uneven, otherwise very precise.

  • diameter 16.1mm (+0.62%)
  • height 15.5mm (+0%)
  • cost EUR 1.04

SLS: 3201PA-F / Polyamid / Nylon

3201PA with SLS is a very good piece, dark gray matte, grainy surface, very precise.

  • diameter 16.05mm (+0.31%)
  • height 15.6mm (+0.65%)
  • cost EUR 1.04

SLA: 9000R Resin

9000R resin with SLA produced a very nice piece, best finish at the top (near perfection), milky white color (vs cold white or warm white), but as it turns out not very precise:

  • diameter 17.75mm (+4.68%)
  • height 16.1mm (+3.87%)
  • cost EUR 1.04

It is very surprising to see the SLA having the biggest imprecision of all the samples.

SLM: 310L Stainless Steel

316L stainless steel with SLM produced a nice piece as well, the top of the pulley is good, some unevenness where the top goes over the gear:

overall it’s grainy surface – indicating powder-based additive procedure. Holding the piece in the hand feels heavy compared the other materials.

  • diameter 16.0mm (+0%)
  • height 15.5mm (+0%)
  • cost EUR 8.30

Verdict

The SLA / resin piece looked most smooth but it had the biggest imprecisions with over 3% in height and diameter – very surprising to me, it should comparatively be as precise as SLS and MJF. I cannot determine if it’s from the JLCPCB resin printer, or inherent of SLA.

SLS and MJF with Nylon performed expectedly very good, very sturdy and precise.

SLM stainless steel surprisingly very precise, yet unsuitable in real life application due the heavy weight.

Long Term Usage

I will update this part as soon long term (1-2 years) usage experience is available:

  • SLA: Resin 9000R: (not yet)
  • MJF: Polyamid/Nylon PA12: (not yet)
  • SLS: Polyamid 3201PA-F: (not yet)
  • SLM: Stainsteel 310L: (not yet)

Materials & 3D Printing Methods

Material vs Printing Methods

Comparing MJF Nylon vs SLS Nylon

PA12 vs 3201PA-F

Comparing Resins

Resins

References

Misc: MKS Monster8 Board Configuration with Marlin for Ashtar K & C

Update:

  • 2022/11/20: Linux DFU upload details added
  • 2022/09/19: adding Ashtar C M503 dump beside Ashtar K
  • 2022/08/24: extending with part cooler fan and extruder fan connection
  • 2022/08/14: starting with the notes

Introduction

MKS Monster8 V1.0 board

These are just my notes for configuring Makerbase (MKS) Monster8 V1.0 for Ashtar K and Ashtar C:

  • STM32M407VET6 (ARM Cortex M4), 168MHz, 512KB Flash, 192KB RAM
  • 8 stepper drivers TMC2209, configured in UART mode
  • MKS MINI 12864 V3 display (the “V3” is relevant)
  • 12V power in/out
  • 3 hotends & bed heating
  • Price ~EUR 55 (2022/08) incl. 8 stepper drivers TMC 2209 and 12864 display

Pros:

  • cost effective, EUR 55 (2022/08) incl. 8x TMC 2209 stepper drivers and 12864 display
  • 8 stepper drivers: e.g. X, Y, Z1/Z2 (on-board splitter) and 5 extruders (e.g. E0, E1, E2, E3, E4 – but only 3 hotends possible)
  • TMC 2208 or TMC 2209 silent drivers
  • good connectors on board, clean setup
  • github with Marlin source (partially preconfigured) for Arduino*) & PlatformIO

Cons:

  • no RepRapFirmware
  • no Wifi (the V2.0 version has optional Wifi board to attach)
  • no Ethernet
  • requires Marlin with PlatformIO (tedious to configure, recompiling required, reupload)
  • limited documentation: actual details are scattered around

Stepper Motor UART Mode

As first putting in the jumpers on all the driver sockets, in my case I choose UART mode for each one of the 8 drivers:

Marlin with Arduino vs PlatformIO

As of 2022/08, it seems Arduino is no longer able to compile Marlin-2.x (various compile errors within Arduino), at least with this board and everybody moved on the PlatformIO, which really surprised me.

PlatformIO CLI

As of 2022/08 there is no Linux GUI for PlatformIO but only PlatformIO CLI, but it’s simple enough:

pip3 install platformio

Download

As next download the firmware, Marlin 2.0.x source from github:

git clone https://github.com/makerbase-mks/MKS-Monster8/

Building

By default the board is configured for Voron 2.4 CoreXY, with 3x Z motors and Z probing in the midst of the bed and other things, so I had to edit Marlin/Configuration.h:

  • #define MACHINE_UUID "..." (use online generator to generate one)
  • #define CUSTOM_MACHINE_NAME "Ashtar K #x L8", given Lead 8×8 are used
  • #define LINEAR_AXES 3
  • #define EXTRUDERS 1 (or 2, 3 max)
  • comment out //#define PREVENT_COLD_EXTRUSION needed for calibration
  • comment out //define COREXY
  • define [XYZ]_DRIVER_TYPE and E[012]_DRIVER_TYPE
  • #define DEFAULT_AXIS_STEPS_PER_UNIT aren’t that important, as one can define it with M92 and M500 saving to EEPROM
  • comment out //#define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
  • test motors regarding #define INVERT_[XYZ]_DIR true or false
  • test motors regarding #define INVERT_E[012]_DIR true or false
  • #define [XYZ]_HOME_DIR -1
  • #define X_BED_SIZE 380
  • #define Y_BED_SIZE 300
  • #define Z_MAX_POS 330

and Configuration_adv.h:

  • #define NUM_Z_STEPPER_DRIVERS 1 even when two Z-stepper motors are attached
  • if you want an automatic E0 fan which turns on only when nozzle is heated: #define E0_AUTO_FAN_PIN PA1 and attach extruder fan (watch polarity) on FAN1/J12 connector

once those changes are made, build the firmware:

cd marlin\ firmware/MKS_MONSTER_Marlin-2.0.x/Marlin-2.0.x/
platformio run

After a short while (~1min) it should finish successfully (if not, edit files).

Firmware Installation

SD Card Firmware Update

Use a SD card, e.g. 8GB with simple FAT filesytem, and copy .pio/build/mks_monster8_usb_flash_drive/firmware.bin and mks_monster8.bin on the SDcard.

Insert the SD card into the Monster8 board next to the USB connector, and turn off and on the board (power cycle) – wait 5-10 seconds so the new firmware is installed, then the display should show the Marlin splashscreen eventually, and the board becomes available as USB device, in my case as /dev/ttyACM0 on Linux Ubuntu 20.04 LTS.

DFU Util Firmware Update

  • connect board with USB cable and optionally select POWER USB (via jumper)
  • power cycle board (e.g. via USB cable) while you push BOOT 0 button in the center of the board briefly (~2 secs)
  • the device will appear as a new USB device

Linux: install apt install dfu-util and then

% sudo dfu-util -a 0 -s 0x0800C000:leave -D .pio/build/mks_monster8_usb_flash_drive/mks_monster8.bin -d 0483:df11
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 0483:df11
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuERROR, status = 10
dfuERROR, clearing status
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash  "
Downloading to address = 0x0800c000, size = 178820
Download        [=========================] 100%       178820 bytes
Download done.
File downloaded successfully
Transitioning to dfuMANIFEST state
% 

M503 Dump for Ashtar K

Ashtar K with 300×300 bed, single extruder:

> M503
-----
echo:  G21    ; Units in mm (mm)
echo:  M149 C ; Units in Celsius

echo:; Filament settings: Disabled
echo:  M200 S0 D1.75
echo:; Steps per unit:
echo: M92 X100.00 Y100.00 Z400.00 E95.00
echo:; Maximum feedrates (units/s):
echo:  M203 X300.00 Y300.00 Z5.00 E25.00
echo:; Maximum Acceleration (units/s2):
echo:  M201 X2500.00 Y2500.00 Z100.00 E5000.00
echo:; Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>
echo:  M204 P3000.00 R3000.00 T3000.00
echo:; Advanced: B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate> X<max_x_jerk> Y<max_y_jerk> Z<max_z_jerk> E<max_e_jerk>
echo:  M205 B20000.00 S0.00 T0.00 X10.00 Y10.00 Z0.30 E5.00
echo:; Home offset:
echo:  M206 X-35.00 Y-3.00 Z0.15
echo:; Material heatup parameters:
echo:  M145 S0 H180.00 B70.00 F0
echo:  M145 S1 H240.00 B110.00 F0
echo:; PID settings:
echo:  M301 P22.20 I1.08 D114.00
echo:; LCD Contrast:
echo:  M250 C255  
echo:; Power-Loss Recovery:
echo:  M413 S1
echo:; Stepper driver current:
echo:  M906 X500 Y500 Z700
echo:  M906 T0 E500

echo:; Driver stepping mode:
echo:  M569 S1 X Y Z
echo:  M569 S1 T0 E
ok
>

M503 Dump for Ashtar C

Ashtar C with 400×400 bed, 3 extruders with single nozzle:

> M503
-----
echo:  G21    ; Units in mm (mm)
echo:  M149 C ; Units in Celsius

echo:; Filament settings: Disabled
echo:  M200 T0 D1.75
echo:  M200 T1 D1.75
echo:  M200 T2 D1.75
echo:  M200 S0
echo:; Steps per unit:
echo: M92 X100.00 Y100.00 Z3200.00 E102.00
echo:; Maximum feedrates (units/s):
echo:  M203 X500.00 Y500.00 Z2.00 E120.00
echo:; Maximum Acceleration (units/s2):
echo:  M201 X9000.00 Y9000.00 Z50.00 E10000.00
echo:; Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>
echo:  M204 P1500.00 R1500.00 T1500.00
echo:; Advanced: B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate> X<max_x_jerk> Y<max_y_jerk> Z<max_z_jerk> E<max_e_jerk>
echo:  M205 B20000.00 S0.00 T0.00 X10.00 Y10.00 Z0.20 E2.50
echo:; Home offset:
echo:  M206 X0.00 Y-5.00 Z0.15
echo:; Material heatup parameters:
echo:  M145 S0 H180.00 B70.00 F0
echo:  M145 S1 H240.00 B110.00 F0
echo:; PID settings:
echo:  M301 P22.20 I1.08 D114.00
echo:; LCD Contrast:
echo:  M250 C255
echo:; Power-Loss Recovery:
echo:  M413 S1
echo:; Stepper driver current:
echo:  M906 X700 Y700 Z1000
echo:  M906 T0 E700
echo:  M906 T1 E700
echo:  M906 T2 E700

echo:; Driver stepping mode:
echo:  M569 S1 X Y Z
echo:  M569 S1 T0 E
echo:  M569 S1 T1 E
echo:  M569 S1 T2 E
echo:; Tool-changing:
echo: Z2.00
ok
>

Fans

Part cooler fan is plugged into FAN0/J11, and if you enabled extruder fan (temperature dependent), plug it in FAN1/J12.

Part Cooler Fan (FAN0/J11) and Extruder Fan (temperature sensitive) FAN1/J12
  • Part Cooler Fan (FAN0): cools the extruded filament, the filament which becomes the part you print
  • Extruder Fan (FAN1): cools the heatsink near the heatbreak, when attached to FAN1/J12 it only runs when the hotend is hotter than 50C° as defined in Marlin.

The jumpers are needed next to the fan connectors to define the voltage, either Vin (left) which is 12V-24V depending on the power input of the board, or 12V (middle) or 5V (right).

MKS Monster8 V1.0 Pins
MKS Monster8 V2.0 Pins

Multiple Materials/Colors

With 8 stepper drivers one is able to run:

  • 3+1x motors for X, Y, Z(2)
  • 5x extruders (colors or materials), the board supports 3 hotends (3 different temperatures)

Monster8 V1.0 vs V2.0

The boards differ in physical layout such as connectors, but the firmware is the same, incl. the pin for the hotend cooler fan (which switches on conditionally when hotend heats up).

Update V2.0

Board Comparison 2022

As of 2022 (I intend to update this) following boards are suitable for my cases:

MKS Monster8 V1.0/V2.0 & 12864 displayMellow Fly Super8 V1.2 & 12864 displayDuet 3 Mini 5+ & Duet 3 Mini 2+Duet 3 MB 6HC & Duet 3 Expansion 3HC
Price55 EUR80 EUR155 EUR (120+35)385 EUR (255+130)
Stepper Drivers887 (5+2)9 (6+3)
Stepper Connectors9 (dual Z)879
Hotends345 (2+3)6 (3+3)
USBYES (USB-C)YES (USB-C)YES (MicroUSB)YES (MicroUSB)
WIFI– / YES3)YESYES1)YES1)
EthernetYES1)YES1)
FirmwareMarlin 2.xMarlin 2.x
RepRapFirmware 3.4.x
RepRapFirmwareRepRapFirmware

Alternatively, there are Duet 2 & 3 clones available on the market:

Duet 2 WIFI CloneDuet 2 WIFI OriginalDuet 3 6HC FYSETC Clone with Duet 3 3HCDuet 3 6HC Original with Duet 3 3HC
Price30-50 EUR2)175-185 EUR1) 225 EUR (150+75)385 EUR (255+130)
Stepper Drivers559 (6+3)9 (6+3)
Stepper Connectors6699
Hotends227 (4+3)6 (3+3)
USBYES (MicroUSB)YES (MicroUSB)YES (MicroUSB)YES (MicroUSB)
WIFIYESYES1)YES1)
EthernetYES1)
YES

YES1)
FirmwareRepRapFirmwareRepRapFirmwareRepRapFirmwareRepRapFirmware
  1. either WIFI or Ethernet
  2. without or with display
  3. MKS Monster8 V2.0 has Wifi module option

As of 2022, RepRapFirmware has become quasi standard in professional level 3D printing; while a lot of people run Klipper & Marlin together I can’t see the point doing this*) but rather have a more capable microcontroller like the Duet boards have to run the printer and manage WIFI / Ethernet at the same time. The only reason to run Klipper on a Single Board Computer (SBC) setup like Raspberry Pi is cost and enhance simple microcontrollers functionality this way.

MarlinKlipper & MarlinRepRapFirmware with Duet
CPUs1x Simple Microntroller1x SBC + 1x Simple Microcontroller1x Capable Microcontroller
ConnectivityUSB onlyUSB, Ethernet and/or WIFIUSB and Ethernet or WIFI
Configuration3x .h files, recompiling requiredsingle .cfg filesingle .g file**)
Boot Time3sKlipper 30s, Marlin 3s3s

*) running different kinematics on the SBC converting G-code on the fly might be a reason
**) multiple .g file can be used optionally

If you are cheap, buy the Duet clones, if you want to support Open Source and Open Hardware community, buy from Duet3d.com direct, pricing is +45% of the clone prices, whereas the Duet resellers add another +15% (Clone: EUR 150, Duet3d.com: 220 EUR, Reseller 255 EUR)

RepRapFirmware: Mind the SD Card

Whether to run an original Duet board or a clone, one thing though one might pay attention to is the SD card, it is the weakest link as far I can tell:

  • SD card needs to be present at all time to provide configuration
  • SD card is not written regularly to unless the logging is enabled

After power-cycling the board, as it was in a strange state no longer responding to G-code properly, the display remained blank, no response to G0/G1 – after investigation it turned out, a single file vanished from the SD card: config.g – the main configuration file, and that is bizarre. The board appeared to be broken, when in truth, the SD card came to its end of life of operating reliably already after only ~1.5 years. The SD card was the one originally shipped with. In this light, a Marlin-based board requiring no SD card being present operates more reliable, unless one uses an industrial grade SD card.

References

Misc: Mellow Fly Super8 V1.2 with RepRapFirmware for Ashtar C & D

Updates:

  • 2022/08/25: extending for more details of config.g limit switches
  • 2022/08/16: starting notes

Introduction

Fly Super8 V1.2 board

I have become a big fan of Duet3 boards running RepRapFirmware, and as I was looking for a suitable board, and I came across Mellow Fly Super8 V1.2 board, 8 steppers TMC 2209, and 4 possible hotends.

  • STM42F407ZGT6 (ARM Cortex-M4), 168MHz, 1MB Flash, 192KB RAM
  • 8 stepper drivers TMC2209, configured in UART mode
    • 3x X, Y, Z(2 using splitter)
    • 5x extruders
  • Fly MINI 12864 display
  • 12V power in/out
  • 4 hotends & bed heating
  • Price ~EUR 80 (2022/08) incl. 8 stepper drivers TMC 2209 and 12864 display

Pros:

  • cost effective, EUR 80 (2022/08) with 8x stepper drivers TMC 2209 and 12864 display
  • runs RepRapFirmware
    • most configuration is done with .g files using G-code notion
    • only new non-supported kinematics require recompiling
  • USB & Wifi connectivity (both simultaneously possible)
  • relative simple configuration (compared to Marlin firmware)

Cons:

  • no Ethernet (Wifi is less reliable)

Software Configuration

Majority of configuration is done via a file-system on a SD card which contains a bunch of .g files which define basic settings of the board and machine it operates:

I operate the board direct with USB and Wifi, not in SBC (Single Board Computer) setup.

  • download firmware, single .bin file from (e.g. firmware-stm32f4-wifi-3.4.1_102.bin) and put it into / (root) folder and rename to firmware.bin – it will vanish once installed on the board
  • download web GUI (e.g. DuetWebControl-SD.zip) and then unzip on the SD card, rename folder name as www/
  • run online configurator to get basic configuration config.g, board.txt and multiple other files (all zipped together)
    • enable Wifi: enter your Wifi Name and Wifi Password
    • you get a single zip file, unzip in the / (root) folder
  • insert SD card into the board, restart board
    • eventually the board will join your Wifi network, scan the network to find out which IP it has, then access the board via web-browser, e.g. http://192.168.1.174/
RepRapFirmware Web-GUI

I operate my 3D printers (3x Ashtar K, 1x Ashtar C, 1x CTC DIY I3 Pro) which use different controller boards all accessed via USB cables and Print3r as main interface (CLI) – having an additional Web-GUI aside allows to operate in parallel beside the USB connectivity.

  • 12864 display with knob to configure on the printer
  • USB connectivity to deliver print job
  • Wifi connectivity to access printer via Web-GUI (simultaneously to USB connectivity)

Hardware Configuration

Important is to put the fuses first, otherwise the board won’t operate, further the stepper driver settings, pluggeable fan MOS, limit switches:

Fly Super8 Pins

I configured the board first using simple USB power delivery, later when the 12V power supply is attached I remove the small jumper to avoid the USB powers the board.

Limit Switches / Endstops

In config.g following lines define the limit switches / endstops:

; Endstops
M574 X1 S1 P"io0"                            ; configure switch-type (e.g. microswitch) endstop for low end on X via pin io0
M574 Y1 S1 P"io1"                            ; configure switch-type (e.g. microswitch) endstop for low end on Y via pin io1
M574 Z1 S1 P"io2"                            ; configure switch-type (e.g. microswitch) endstop for low end on Z via pin io2

therefore the endstops are laid out as such:

Attention: the limit switch with three wires must be inserted correctly, otherwise you short GND with 5V when pushing the switch. The proper layout of io[012] pins (left-to-right):

  • Signal
  • GND
  • 5V
Makerbot Endstop V1.2: Pin 1: Signal, Pin 2&3: GND, Pin 4: 5V

Bed Heating & Hotends

Given the config.g defines the heaters as such:

; Heaters
M308 S0 P"ADC_0" Y"thermistor" T100000 B4092 ; configure sensor 0 as thermistor on pin ADC_0
M950 H0 C"bed" T0                            ; create bed heater output on bed and map it to sensor 0
M307 H0 B0 S1.00                             ; disable bang-bang mode for the bed heater and set PWM limit
M140 H0                                      ; map heated bed to heater 0
M143 H0 S120                                 ; set temperature limit for heater 0 to 120C
M143 H0 S120                                 ; set temperature limit for heater 0 to 120C
M308 S1 P"ADC_1" Y"thermistor" T100000 B4092 ; configure sensor 1 as thermistor on pin ADC_1
M950 H1 C"heat0" T1                          ; create nozzle heater output on heat0 and map it to sensor 1
M307 H1 B0 S1.00                             ; disable bang-bang mode for heater  and set PWM limit
M143 H1 S280                                 ; set temperature limit for heater 1 to 280C

; Fans
M950 F0 C"fan0" Q500                         ; create fan 0 on pin fan0 and set its frequency
M106 P0 S0 H-1                               ; set fan 0 value. Thermostatic control is turned off

therefore the connections are:

  • Bed Temperature Sensor ADC0
  • Bed Heater BED_OUT
  • Hotend 1 Temperature Sensor ADC1
  • Hotend 1 Heater HEAT0
  • Part Cooler FAN0

M503 Dump for Ashtar D

M503 dump for Ashtar D (Classic XY) with 400×400 bed, single extruder:

> M503
; Configuration file for Fly Super8 (firmware version 3)
; executed by the firmware on start-up
;
; generated by RepRapFirmware Configuration Tool v3.4.0-LPC-STM32+4 on Tue Aug 16 2022 20:32:44 GMT+0200 (Central European Summer Time)

; General preferences
G90                                          ; send absolute coordinates...
M83                                          ; ...but relative extruder moves
M550 P"Ashtar D1"                            ; set printer name
;M669 K1                                      ; select CoreXY mode

; Network
M552 S1                                      ; enable network
M586 P0 S1                                   ; enable HTTP
M586 P1 S0                                   ; disable FTP
M586 P2 S0                                   ; disable Telnet

; Drives
M569 P0 S1                                   ; physical drive 0 goes forwards using default driver timings
M569 P1 S1                                   ; physical drive 1 goes forwards using default driver timings
M569 P2 S1                                   ; physical drive 2 goes forwards using default driver timings
M569 P3 S1                                   ; physical drive 3 goes forwards using default driver timings
M569 P4 S1                                   ; physical drive 4 goes forwards using default driver timings
M584 X0 Y1 Z2:3 E4:5                         ; set drive mapping: Z drivers port 3&4, E drives 4&5
M350 X16 Y16 Z16 E16 I1                      ; configure microstepping with interpolation
M92 X80.00 Y80.00 Z3200.00 E420.00            ; set steps per mm
M566 X900.00 Y900.00 Z30.00 E120.00          ; set maximum instantaneous speed changes (mm/min)
M203 X6000.00 Y6000.00 Z150.00 E1200.00      ; set maximum speeds (mm/min)
M201 X500.00 Y500.00 Z20.00 E250.00          ; set accelerations (mm/s^2)
M906 X800 Y800 Z800 E800 I30                 ; set motor currents (mA) and motor idle factor in per cent
M84 S30                                      ; Set idle timeout

; Axis Limits
M208 X0 Y0 Z0 S1                             ; set axis minima
M208 X380 Y380 Z380 S0                       ; set axis maxima

; Endstops
M574 X1 S1 P"!io0"                            ; configure switch-type (e.g. microswitch) endstop for low end on X via pin io0
M574 Y1 S1 P"!io1"                            ; configure switch-type (e.g. microswitch) endstop for low end on Y via pin io1
M574 Z1 S1 P"!io2"                            ; configure switch-type (e.g. microswitch) endstop for low end on Z via pin io2

; Z-Probe
;M558 P0 H5 F120 T6000                        ; disable Z probe but set dive height, probe speed and travel speed
;M557 X15:215 Y15:195 S20                     ; define mesh grid

; Heaters
M308 S0 P"ADC_0" Y"thermistor" T100000 B4092 ; configure sensor 0 as thermistor on pin ADC_0
M950 H0 C"bed" T0                            ; create bed heater output on bed and map it to sensor 0
M307 H0 B0 S1.00                             ; disable bang-bang mode for the bed heater and set PWM limit
M140 H0                                      ; map heated bed to heater 0
M143 H0 S120                                 ; set temperature limit for heater 0 to 120C
M143 H0 S120                                 ; set temperature limit for heater 0 to 120C
M308 S1 P"ADC_1" Y"thermistor" T100000 B4092 ; configure sensor 1 as thermistor on pin ADC_1
M950 H1 C"heat0" T1                          ; create nozzle heater output on heat0 and map it to sensor 1
M307 H1 B0 S1.00                             ; disable bang-bang mode for heater  and set PWM limit
M143 H1 S280                                 ; set temperature limit for heater 1 to 280C

; Fans
M950 F0 C"fan0" Q500                         ; create fan 0 on pin fan0 and set its frequency
M106 P0 S0 H-1                               ; set fan 0 value. Thermostatic control is turned off

; Tools
M563 P0 D0 H1 F0                             ; define tool 0
G10 P0 X0 Y0 Z0                              ; set tool 0 axis offsets
G10 P0 R0 S0                                 ; set initial tool 0 active and standby temperatures to 0C

; Custom settings are not defined

; Miscellaneous
M501                                         ; load saved parameters from non-volatile memory

; 12864 Display                              ; https://teamgloomy.github.io/fly_super8_screen_12864.html
;M950 P1 C"LCD_D4"
;M42 P1 S0
;G4 P500
;M42 P1 S1
;M918 P2 C30 F100000 E4

; M918 P1 E-4 F2000000                        ; https://github.com/jadonmmiller/UltimateDuetMenuSystem

M950 P1 C"LCD_D4"
M42 P1 S0
G4 P500
M42 P1 S1
M918 P2 C30 F100000 E4

Multiple Materials/Colors

With 8 stepper drivers one is able to run:

  • 3x motors for X, Y, Z(2) – attach two Z stepper motors to one driver via splitter
  • 5x extruders (colors or materials), the board supports 4 hotends (4 different temperatures)

Gallery

Board Comparison 2022

As of 2022 (I intend to update this) following boards are suitable for my cases:

MKS Monster8 V1.0/V2.0 & 12864 displayMellow Fly Super8 V1.2 & 12864 displayDuet 3 Mini 5+ & Duet 3 Mini 2+Duet 3 MB 6HC & Duet 3 Expansion 3HC
Price55 EUR80 EUR155 EUR (120+35)385 EUR (255+130)
Stepper Drivers887 (5+2)9 (6+3)
Stepper Connectors9 (dual Z)879
Hotends345 (2+3)6 (3+3)
USBYES (USB-C)YES (USB-C)YES (MicroUSB)YES (MicroUSB)
WIFI– / YES3)YESYES1)YES1)
EthernetYES1)YES1)
FirmwareMarlin 2.xMarlin 2.x
RepRapFirmware 3.4.x
RepRapFirmwareRepRapFirmware

Alternatively, there are Duet 2 & 3 clones available on the market:

Duet 2 WIFI CloneDuet 2 WIFI OriginalDuet 3 6HC FYSETC Clone with Duet 3 3HCDuet 3 6HC Original with Duet 3 3HC
Price30-50 EUR2)175-185 EUR1) 225 EUR (150+75)385 EUR (255+130)
Stepper Drivers559 (6+3)9 (6+3)
Stepper Connectors6699
Hotends227 (4+3)6 (3+3)
USBYES (MicroUSB)YES (MicroUSB)YES (MicroUSB)YES (MicroUSB)
WIFIYESYES1)YES1)
EthernetYES1)
YES

YES1)
FirmwareRepRapFirmwareRepRapFirmwareRepRapFirmwareRepRapFirmware
  1. either WIFI or Ethernet
  2. without or with display
  3. MKS Monster8 V2.0 has Wifi module option

As of 2022, RepRapFirmware has become quasi standard in professional level 3D printing; while a lot of people run Klipper & Marlin together I can’t see the point doing this*) but rather have a more capable microcontroller like the Duet boards have to run the printer and manage WIFI / Ethernet at the same time. The only reason to run Klipper on a Single Board Computer (SBC) setup like Raspberry Pi is cost and enhance simple microcontrollers functionality this way.

MarlinKlipper & MarlinRepRapFirmware with Duet
CPUs1x Simple Microntroller1x SBC + 1x Simple Microcontroller1x Capable Microcontroller
ConnectivityUSB onlyUSB, Ethernet and/or WIFIUSB and Ethernet or WIFI
Configuration3x .h files, recompiling requiredsingle .cfg filesingle .g file**)
Boot Time3sKlipper 30s, Marlin 3s3s

*) running different kinematics on the SBC converting G-code on the fly might be a reason
**) multiple .g file can be used optionally

If you are cheap, buy the Duet clones, if you want to support Open Source and Open Hardware community, buy from Duet3d.com direct, pricing is +45% of the clone prices, whereas the Duet resellers add another +15% (Clone: EUR 150, Duet3d.com: 220 EUR, Reseller 255 EUR)

RepRapFirmware: Mind the SD Card

Whether to run an original Duet board or a clone, one thing though one might pay attention to is the SD card, it is the weakest link as far I can tell:

  • SD card needs to be present at all time to provide configuration
  • SD card is not written regularly to unless the logging is enabled

After power-cycling the board, as it was in a strange state no longer responding to G-code properly, the display remained blank, no response to G0/G1 – after investigation it turned out, a single file vanished from the SD card: config.g – the main configuration file, and that is bizarre. The board appeared to be broken, when in truth, the SD card came to its end of life of operating reliably already after only ~1.5 years. The SD card was the one originally shipped with. In this light, a Marlin-based board requiring no SD card being present operates more reliable, unless one uses an industrial grade SD card.

References

3D Printing: Slicing with Non-Planar Geometries

Updates:

  • 2022/04/25: added single photo with various 20mm cube prints
  • 2022/04/01: rewording to avoid confusion of “planar slicing” with non-planar geometries
  • 2022/03/26: finally published
  • 2022/03/25: adding “Benefits of Non-Planar Printing” and “Blind Spots of CAD Systems” and “Scale and Functional Quality”
  • 2022/02/18: getting ready to publish
  • 2022/02/15: adding different slicing geometries and the resulting G-code
  • 2022/02/12: starting write-up

Introduction

After researching non-planar slicing using planar slicers it was obvious to find a way to slice with any kind of geometry, and it meant to step back and formalize slicing procedure in a general manner like “Universal Slicing” – and look at the procedure of slicing itself.

Two classes were defined:

  • Class 1: using a geometry, either planar or non-planar, and slicing with a static slicing path
  • Class 2: slicing with variable slicing path and/or variable slicing geometry while slicing

This document/blog-post features a solution for Class 1 Universal Slicing.

My video Non-Planar 3D Printing: Slicing with Non-Planar Geometries goes through this information in an animated form, this is the textual form.

Slicing with Non-Planar Geometry (Class 1 Universal Slicing)

When using a static planar slicing vector one usually uses a plane, hence the term “planar slicing”, yet, there is also the possibility to use a non-planar geometry and slice in a planar direction (introducing ambiguity what planar and non-planar slicing actually mean). Regardless which slicing geometry is used in this procedure, the thickness of the sliced layer stays the same.

Slicing 20mm cube with wave-like geometry

In order to explore non-planar slices, using a wave-like geometry composed by Bezier curves and slice a 20mm cube:

Note: OpenSCAD is used solely used as 3D viewer, the slicing itself is performed by an experimental slicer.

Routing a single non-planar slice

A single slice is routed to wall/perimeter and infill extrusion:

There are several approaches to achieve this:

  • slice non-planar, map single slice 3d to 2d, route with 2d offsetting, and map back to 3d space (MetatronSlicer)
  • map entire mesh and slice planar, and map routes or resulting G-code back again (EnochSlicer)

and likely other more complex means.

Non-planar Printed Wave-like Sliced 20mm Cube

Preview of the complete G-code:

Preview the non-planar G-code of 20mm cube sliced with wave-like geometry

and a brief and fast printing simulation showing the entire print:

The computed G-code printed with a 3D printer, e.g. an ordinary 3-axis FDM:

Non-Planar 3D Printing: 20mm cube sliced with wave-like geometry (1x speed with a few skips)

and produces output like this:

left-to-right: wave-like geometry itself, progressive state of 20mm cube sliced with wave-like geometry at 0.25mm layer height

Implementing Non-Planar Slicing Geometries Slicer

The illustrations and actual G-code above were produced by two new in-house slicers which are in early development (2022/03):

20mm cube sliced with wave-like geometry
left-to-right: MetatronSlicer (0.0.7), EnochSlicer (0.0.2)
  • MetatronSlicer: boundary-based (BREP / OpenCASCADE) and voxel-based (OpenVDB) geometry engine, performing true non-planar slicing, and LabSlicer performing routing and G-code creation; slower slicing yet precise G-code
  • EnochSlicer: mesh and G-code transformation approach, fast slicing yet less accurate G-code

The extrusion precision is still rough, but overall concept and algorithms have been proven to work.

Results & Achievement

This work as presented here resolves a long pending issue of slicing meshs “non-planar”, or general “non-planar slicing” with all its inherent ambiguity – consider it as given that

one can use any 3D geometry with sufficient upper “surface” to slice a mesh with

and create printable G-code for 3- and 5-axis FDM:

  1. using a block as planar blueprint
  2. hemisphere, convex
  3. hemisphere reverse, concave
  4. cone, slicing conical like for Rotating Tilted Nozzle
  5. wave-like defined via Bezier curves
  6. wave-like defined via NURBS (Non-Uniform Rational B-Splines) curves
  7. tilted plane, slicing for belt printer with 45° tilted XY frame toward Z belt
  8. pimple-like

Along with volume segmentation as presented previously and conical, cylindrical and spherical slicing now any kind of slicing geometry can be used.

As pointed out in Universal Slicing, this “Planar Slicing with Non-Planar Geometries” is Class 1 of Universal Slicing whereas Class 2 covers changing slicing geometry and/or flexible slicing path along the slicing.

Limiting Non-Planar Height for 3-axis FDM

When using non-planar geometries to slice a model also non-planar G-code is produced and possibly significant Z motion occurs, and when printing with an ordinary 3-axis FDM 3D printer it may be suitable to limit the Z motion aka Z amplitude to 2-3mm in order to avoid part-cooler or other parts of the print head to collide with the already printed part:

left column: wave-like slicing, right column: hemisphere slicing
top row: full range, bottom row: limited to ~3mm Z amplitude

Future blog-posts will go into further details implementing Universal Slicing using those two slicers MetatronSlicer and EnochSlicer.

Regarding naming the slicers: Metatron is an archangel in jewish mythology – consider an “angel” as a fundamental intelligence, and in esoteric context Metatron is the being responsible for Form or Geometry itself – separating one into many in a spatial manner; whereas Enoch as a human, who ascended to become the archangel Metatron. I use those names in deep reverence for these two projects.

Blind Spot of CAD Systems

Current CAD systems (2022) neglect or actually are unaware of the inner vs outer structure – because only one kind of the “structure” is known, e.g. a piece is designed because of a certain function, which defines its outer form, e.g. a wrench to use a simple example – but how about the inner structure? This isn’t defined in the CAD, it is defined at the manufacturing stage, yet with 3D printing this can be described and designed even in a parametric way as well, the slicing or general 3D printing stage with different materials.

We require 2 or 3 abstraction layers to design a functional piece:

  1. the functional description (doesn’t exist yet)
  2. the inner structure (description how material is deposited in Additive Manufacturing, e.g. the infill geometry as of with FDM, incl. non-planar printing, or lattice structures as with SLA or SLS)
  3. the outer structure (e.g. mesh, boundaries)

So far CAD systems only covers the 3rd point, the outer structure.

The functional description is almost non-existent in the CAD world, and only becomes some attention when Finite Element Analysis is made and the form is changed, it is kind of hidden in plain sight.

In future blog-posts I will address and elaborate on these issues further.

Scale and Functional Qualities

To put the flexible slicing geometry in the grander context of 3D printing engineering:

3D printing engineering starts at nanometer scale (10-6mm) with material science level, over to filament composition at 1 to 10 micrometer scale (10-2mm) such as fibers, inner geometry where slicing geometry & procedure and infill geometry define strength properties at millimeter scale (100mm), and outer geometry with the shape of the object itself provide the final stage of mechanical properties.

This entire “scale chain” as a whole defines the mechanical property of the final 3D printed object.

That’s it.

References

EnochSlicer

Status: early development, not available yet

Updates:

  • 2022/03/26: published with little information
  • 2022/02/28: starting write-up

Introduction

EnochSlicer is aiming to be a fast Universal Slicer by taking research results from development of MetatronSlicer.

MetatronSlicer vs EnochSlicer

MetatronSlicer implements true non-planar slicing and routes each slice exact, whereas EnochSlicer using pre- and post transformation of mesh and routes (pre g-code).

As development of an Universal Slicer is in early stage (2022/03), both projects are pushed forward to see which one is more fit and suitable and cross-fertilize each other.

MetatronSlicerEnochSlicer
meshplaintransformation
slicingnon-planarplanar
routededicated 1)
gcodededicated 1)native 2)
post processingplaintransformation

Footnotes:

  1. utilizing LabSlicerCore library
  2. native via planar slicer (direct mesh to gcode) like CuraEngine

In-House Slicers

LabSlicerVox3lSlicerVoxGLSlicerMetatronSlicerEnochSlicer
– full planar slicer
– 4 stages: mesh, slice, route, gcode
– experimental
– API defined
– LabSlicerCore library
– import/export data of each stage
– voxel-based planar slicer
– fast slicing
– uses LabSlicerCore library for route and gcode stage
– OpenGL based planar slicer
– fast slicing
– uses LabSlicerCore library for route and g-code stage
– non-planar slicer
– implements Class 1 + 21) Universal Slicing
– uses OpenZCAD2) engine to slice non-planar
– non-planar slicer
– implements Class 1 + 21) Universal Slicing
– uses mesh & gcode transformation

Footnotes:

  1. Class 2 Universal Slicing only partially implemented (status 2022/03)
  2. OpenZCAD is alike OpenSCAD but with Python as base-language with multiple backends (OpenCASCADE, LibFive, Fogleman’s SDF)

Availability

See MetatronSlicer

References

MetatronSlicer

Status: early development, not yet available

Updates:

  • 2022/04/01: bringing terms/wording in-sync with Universal Slicing
  • 2022/02/26: published finally with basic information
  • 2022/02/18: copying content from “Universal Slicing” page start to focus on the slicer itself

Introduction

MetatronSlicer aims to become full functional Universal Slicer:

Universal slicing means free slicing geometry along a free path.

“free (definable) slicing geometry”: any kind of geometry, may it may a solid or just a surface defining the slicing geometry.

“free (definable) path”: the slicing procedure can go in any direction, curvature and steps.

See Universal Slicing for more thorough description and theoretical examples.

Implementing Universal Slicing

As I was proposing the concept of “Universal Slicing”, I had the impulse to start an implementation right away in order to produce illustrations for the concept.

  • MetatronSlicer aims to become full Universal Slicer, it’s not optimized for speed but to be capable as of completeness.
  • EnochSlicer is a sister project which takes research results from development of MetatronSlicer and tries to find a more efficient way to achieve the same or a subset.

Universal Slicer: MetatronSlicer

MetatronSlicer is the first attempt of an Universal Slicer (2022/02), which implements for a start planar-slicing of non-planar slicing geometries, for example a wave-like geometry:

The wave-like geometry was defined via Bezier curves.

Via some transformations back and forth the in-house LabSlicer and g-code produced non-planar slice:

  • the green represents the ideal 3D slice,
  • the yellow/golden are the extrusions,
  • the red dots indicate the start of a G1 extrusion segment.

As of MetatronSlicer 0.0.8 (still very experimental as of 2022/02) it was possible to produce printable G-code:

and then printed on a 3-axis FDM (Ashtar K #2 Prusa-Mendel style) machine with apprx. 3mm vertical nozzle spacing 2), the wave-like reference geometry was slighted scaled in Z to comply to this physical contraint:

full print at 1x speed with a few skips
MetatronSlicer: toward implementing Universal Slicing capabilities

A few samples of non-planar geometries slicing 20mm cube:

Class 1 Universal Slicing: Planar Slicing with Non-Planar Geometries: cube (planar), hemisphere (convex), hemisphere inverse (concave), conic, wave-like, nurbs, tilted, pimple-like

Convex hemispherical slice geometry slicing 20mm cube:

Concave hemispherical slice geometry slicing 20mm cube:

Conic slice geometry slicing 20mm cube:

which essentially replaces Slicer4RTN.

As of 2022/02 MetatronSlicer is still in very early development, but eventually aims to implement also variable slicing geometries and variable slicing vector such as:

Class 2 Universal Slicing: Variable Slice Geometry / Variable Slicing Path

MetatronSlicer vs EnochSlicer

MetatronSlicer implements true non-planar slicing and routes each slice exact, whereas EnochSlicer using pre- and post transformation of mesh and routes (pre g-code).

As development of an Universal Slicer is in early stage (2022/03), both projects are pushed forward to see which one is more fit and suitable and cross-fertilize each other.

MetatronSlicerEnochSlicer
meshplaintransformation
slicingnon-planarplanar
routededicated 1)
gcodededicated 1)native 2)
post processingplaintransformation

Footnotes:

  1. utilizing LabSlicerCore library
  2. native via planar slicer (direct mesh to gcode) like CuraEngine

Availability

MetatronSlicer and alike EnochSlicer are in early development, and will be tuned for industrial 3D printing applications for 3- and 5-axis FDM.

Sometime during 2022 one or both might become available as commercial products in order to fund future development, unless I find another way to fund the research and development – in that case an open source “community edition” is possible.

References

In-House Slicers

LabSlicerVox3lSlicerVoxGLSlicerMetatronSlicerEnochSlicer
– full planar slicer
– 4 stages: mesh, slice, route, gcode
– experimental
– API defined
– LabSlicerCore library
– import/export data of each stage
– voxel-based planar slicer
– fast slicing
– uses LabSlicerCore library for route and gcode stage
– OpenGL based planar slicer
– fast slicing
– uses LabSlicerCore library for route and g-code stage
– non-planar slicer
– implements Class 1 + 21) Universal Slicing
– uses OpenZCAD2) engine to slice non-planar
– non-planar slicer
– implements Class 1 + 21) Universal Slicing
– uses mesh & gcode transformation

Footnotes:

  1. Class 2 Universal Slicing only partially implemented (status 2022/03)
  2. OpenZCAD is alike OpenSCAD but with Python as base-language with multiple backends (OpenCASCADE, LibFive, Fogleman’s SDF)

LabSlicer, Vox3lSlicer, VoxGLSlicer

Updates:

  • 2022/03/26: published
  • 2022/03/03: starting write-up, based on internal documentation

Introduction

As part of getting to know the inner working of a slicer and have a toolkit for advanced non-planar slicer I had in mind, I started to code my own “laboratory slicer” or simply “LabSlicer” as an in-house project.

Its main features are:

  • Python-based, it’s slow for production but good enough to test new algorithms
  • PyClipper as offsetting & clipping engine
  • four stages clearly defined with API and file-format export/import:
    • mesh: import & export meshs
    • slice: slices 3d objects into 2d slices/polygons
    • route: routes polygons with wall/perimeter and infills, bottom/top layers, skirts/brims
    • gcode: takes routes and converts into G-code
  • LabSlicerCore: slicer available as library, with clear defined & simple API
  • easy to extend to non-planar slicing/routing/g-code, incl. 5-axis FDM

Motivation

It may look like redundant to code another slicer and define those rather simple steps as such, but the benefits came days after I finished the basic layout and was able to exchange the mesh and slicing stage with voxel-based engine, or use OpenGL screenbuffer to slice and then hand over polygons to route and gcode stage – within 2-3 weeks I had 3 working slicers with different slicing engines.

By having a clear API the integration into various in-house projects was truly swift and the cross-fertilization paid off quickly and immensely. I might have taken me more time to learn to memorize Slic3r or CuraEngine API than writing a basic slicer myself. Granted that coding a slicer in Python limits its overall performance, compared to an optimized slicer like Cura; but to research and develop new slicing and routing algorithm coding with Python is fast, a couple of hundred lines in Python can represent ten thousands of lines of C++ code, not to mention wait time for compiling.

Four Stages of Slicing

It may appear to be simplistic at first sight, but it’s worth to clearly layout the main stages of slicing:

Mesh

One has to import the geometry such as a mesh which circumscribes a volume.

Slice

The slicing stage takes the geometry and slices it into slices, which are a set of polygons which also describe holes – essentially an array of arrays of polygons.

Route

The real work of the slicer is actually the routing, which means to plan extrusion paths:

  • walls or perimeters: offsetting or rather insetting 2D polygons
  • infill pattern: offsetting and clipping of 2D polylines
  • skirts and brims: offsetting at bottom via 2D polygons
  • bottom and top layers, also intermediary: difference & intersecting previous and next layers to determine delta areas (polygons) were, are or becoming bottom/top layers
  • support structures (not yet implemented)

Routes are held in an array of arrays of routes (polylines).

Off- and Insetting Polygons

At first sight it looks trivial, but in the details this isn’t trivial at all as offsetting or insetting can clash with itself or other polygons and fork into two or more polygons. Clipper as developed Angus Johnson has laid the ground for many slicers and does the heavy lifting and therefore unloads some of the burden and one can focus on higher level algorithms.

Gcode

At this stage now all the slicing settings like travel and extrusion speeds, retraction and so on are factored in and further optimizations are done, given we know now all routes at a given (planar-)layer.

It’s easier to separate routing and actual creation of G-code as transforming routing, like for non-planar slicing, is more efficient than parsing G-code with more overhead.

From a development point of view the routing results is the most precious and worthwhile data; the other stages are rather simple, but routing is where the magick happens.

History

To give you a bit insight to how I coded it, I started with the API in mind, defined the 4 stages roughly, then the parameters and the data-structures and import/export file-formats, essentially all is encoded in JSON to keep things simple.

Within 2 days I had basic wall routing coded using PyClipper – I had some experience with coding with it at Mandoline (fork) but felt to start from scratch anyway – and I did not even try to slice yet but had a simple function returning the same square (polygon) no matter which slicing height – yes, starting with the simple 20mm cube.

Once I had the routing done, I coded the gcode stage, to create basic extrusion and preview the gcode with a G-code viewer – and added support start- and end-gcode with some sane defaults and sent it to my 3D printer – and the first print outs were bad, no retraction, no infill, single wall, no path/routing optimization.

After I matured routing and gcode stage, I focused on the slicing from mesh to polygons, which took most of the time, as I had to decide on the notion how holes are defined in a set of polygons, using clock-wise (CW) and counter-clock-wise (CCW) notion – the code grew quickly complex as I coded those polygon processing from scratch instead to use shapely library right away; but it was good to look so closely at the details, as when one wants to carry metadata of facets of the mesh to the polygon slice and routing stage to the final gcode, e.g. changing color, material or other special G-code, this chain or pipe to hand over metadata had to be possible.

I also kept the file format of routing somewhat open to support easily also non-planar routes, means, the coordinate could be more than x, y, z but also u, v, w (nozzle vector for 4-, 5- or 6-axis FDM) and layer thickness for non-planar slicing.

Cross-Fertilization

  • Vox3lSlicer: as I experimented with voxel-based geometries, such as reliable CSG operations when slicing with voxels, I replaced the mesh– and slice-stage with voxel-based functions, and then use the next two stages of route and gcode to create G-code; it was truly a matter of a couple of hours
  • VoxGLSlicer: utilizing OpenGL screenbuffer to “render” volume and easily slice within the GL engine, vectorize and feed the polygons into LabSlicerCore; the same, after a few hours I had another slicer

Examples

In-House Slicers

LabSlicerVox3lSlicerVoxGLSlicerMetatronSlicerEnochSlicer
– full planar slicer
– 4 stages: mesh, slice, route, gcode
– experimental
– API defined
– LabSlicerCore library
– import/export data of each stage
– voxel-based planar slicer
– fast slicing
– uses LabSlicerCore library for route and gcode stage
– OpenGL based planar slicer
– fast slicing
– uses LabSlicerCore library for route and g-code stage
– non-planar slicer
– implements Class 1 + 21) Universal Slicing
– uses OpenZCAD2) engine to slice non-planar
– non-planar slicer
– implements Class 1 + 21) Universal Slicing
– uses mesh & gcode transformation

Footnotes:

  1. Class 2 Universal Slicing only partially implemented (status 2022/03)
  2. OpenZCAD is alike OpenSCAD but with Python as base-language with multiple backends (OpenCASCADE, LibFive, Fogleman’s SDF)

Availability

All three slicers are in-house slicers where I do a lot of experimenting, changing rapidly and testing new algorithms, such as mapping coordinate systems and new routing procedures – for now there are no plans to publish them.

I recommend to look at my fork of Mandoline to learn about slicing, which is available at github but I have stopped to work on, it actually produces printable G-code unlike the original code of it.

References

Universal Slicing

Updates:

  • 2022/04/01: changing wording of “non-planar” vs “planar” slicing but describe actual slicing vector and geometry
  • 2022/03/26: published finally
  • 2022/03/24: added “Tensile & Shearing Force” illustration
  • 2022/03/10: added “Scale & Functional Qualities”
  • 2022/02/27: added Class 2 example
  • 2022/02/18: removed MetatronSlicer example and move to new page, keeping page focused on general and theoretical aspect of Universal Slicing
  • 2022/02/12: adding MetatronSlicer example as first attempt of an Universal Slicer
  • 2022/01/28: separating from another blog-post, solely focusing on Universal Slicing
  • 2022/01/16: starting write-up

Introduction

While conceptualizing the in-house LabSlicer (2021/2022) and the two subsequent slicers afterwards (Vox3lSlicer & VoxGLSlicer), I realized it would be useful to formulate a general or universal description of slicing, hence I propose an universal definition of slicing as such:

Universal slicing means free slicing geometry along a free path.

“free (definable) slicing geometry”: any kind of geometry, may it be a solid or just a surface defining the slicing geometry.

“free (definable) path”: the slicing procedure can go in any direction, curvature and steps.

To put this in context:

  • “planar slicing” is plane or quasi box geometry with layer height thickness, sliced along a static 3D path vector of [ 0, 0, 1 ], aka “planar” or “Z-planar” with vector steps of [ 0, 0, layer height ], whereas layer height can change in that case it’s “variable” or “adaptive layer height”
  • “conic slicing” is a cone geometry with layer height thickness, sliced along a static path vector of [ 0, 0, 1 ] with vector steps of [ 0, 0, cos( layer height )] or scaling a stationary conic to match layer height
  • “cylindrical slicing” is a cylinder which stays positioned static at [ 0, 0, 0 ] and variable scaled to match layer height with [ s, s, 1 ], slicing pipe-like layers
  • “spherical slicing” is a sphere geometry with scales in size to match layer height, the position stays [ 0, 0, 0 ], whereas the geometry is scaled by [ s, s, s ], slicing thin sphere layers
SlicingSlicing GeometrySlicing VectorVector StepsGeometry Scale
planarplane[ 0, 0, 1 ][ 0, 0, t ][ 1, 1, 1 ]
coniccone[ 0, 0, 1 ][ 0, 0, t ][ 1, 1, 1 ]
cone[ 0, 0, 0 ][ 0, 0, 0 ][ s, s, s ]
cylindricalcylinder[ 0, 0, 0 ][ 0, 0, 0 ][ s, s, 1 ]
sphericalsphere[ 0, 0, 0 ][ 0, 0, 0 ][ s, s, s ]

The actual implementation, how slices are routed and then G-code is created, is up to the slicer; an Universal Slicer is a slicer which implements Universal Slicing paradigm.

Class 1: Static Slicing Vector, Static Slicing Geometry

There are two distinct cases of class 1 slicing:

  • slicing with planar geometry, a plane – also known as “planar slicing”
  • slicing with non-planar geometry, like a wave, a hemisphere, a cone, etc.

Static slicing vector means here, there is an equal distance among all points of a slice to the next or previous slice at the same [ x, y ] position according the slicing vector:

Class 1 Universal Slicing: Static Slicing Vector with Planar and Non-Planar Geometries

Regardless of the slicing geometry, the layer height or thickness remains the same along the slice or layer itself.

The layer height or thickness may vary from layer to layer, this is known as “variable layer height” or “adaptive layer height” but only means among layers or slices, but not within a single layer or slice.

Class 1 Examples

Examples of Class 1 Universal Slicing with planar and non-planar geometries and the respective G-code outputs (produced by MetatronSlicer and EnochSlicer):

Class 1 Universal Slicing: Planar Slicing with Non-Planar Geometries: planar, hemisphere convex, hemisphere concave, conic, wave-like Bezier & NURBS, tilted, pimple-like
  1. using a block as planar blueprint
  2. hemisphere, convex
  3. hemisphere reverse, concave
  4. cone, slicing conical like for Rotating Tilted Nozzle
  5. wave-like defined via Bezier curves
  6. wave-like defined via NURBS (Non-Uniform Rational B-Splines) curves
  7. tilted plane, slicing for belt printer with 45° tilted XY frame toward Z belt
  8. pimple-like

Class 2: Variable Slicing Vector or Variable Slicing Geometry

Variable slicing vector or changing slicing geometry (often refered as “non-planar slicing” without the specifics) means the slice itself has variable layer height or thickness – to be more precise:

  • change of slicing geometry, e.g. transitioning from one slicing geometry to another
  • change of slicing vector, e.g. change in steps, or curvature
Class 2 Universal Slicing: Variable Slicing Geometry, Variable Slicing Vector

It may not be always clear at first sight whether there is a transition of a slicing geometry or a change of slicing vector, as the changed slicing vector can also be looked as another slicing geometry – yet I think it makes more sense to differentiate between a slicing vector and slicing geometry when laying out a slicing procedure.

Class 2 Examples

Example of Class 2 of Universal Slicing (produced by EnochSlicer):

It is important to realize, that change of slicing geometry and/or slicing vector implies the slice or layer has variable thickness, hence, might have to comply with physical limits like maximum layer height printable with FDM and a given nozzle diameter – the actual implementation of an Universal Slicer has to adhere this.

Slicing Vector vs Slicing Geometry

Slicing VectorSlicing GeometrySlices / 3D PrintingSlice Thickness
staticplanarplanarstatic
non-planarnon-planarstatic
variableplanarnon-planarvariable
non-planarnon-planarvariable

Implementing Universal Slicing

The implementation of such Universal Slicing can be achieved in many ways and procedures. It is important to name features and describe what it they mean, such as:

  • Universal Slicing: is the ability to choose slice geometry and slice path freely
  • Universal Slicer: slicer which implements Universal Slicing in parts or fully – if it only implements part it shall be declared so
  • Class 1 Universal Slicing: static slicing path of [ 0, 0, 1 ], but with any kind of slicing geometry, static planar or static non-planar
  • Class 2 Universal Slicing: flexible slicing path, ability to change slicing geometry while slicing
ClassSlicing PathSlicing Geometry
Class 1staticstatic (planar or non-planar)
Class 2flexibleflexible (planar or non-planar)

Universal Slicers

  • MetatronSlicer (in-house XYZdims, status 2022/03):
    • slicing with (non-)planar geometries (Class 1)
    • partial support for slicing with change of slicing geometry (Class 2)
  • EnochSlicer (in-house XYZdims, status 2022/03):
    • slicing with (non-)planar geometries (Class 1)
    • partial support for slicing with change of slicing path & geometry (Class 2)
  • DotXControl 5-Axis Slicer (status 2022/03): supposedly supports Class 1 + 2 based on illustrations on the web-site
  • AI-Build (AI Build): requires NDA to even see a demo (!!) therefore difficult to conclude capabilities, might supports Class 1 + 2 based on illustrations and brief videos
MetatronSlicer: slicing with wave-like geometry a 20mm cube, printed with 3-axis FDM

Benefits of Non-Planar 3D Printing FDM

Layer adhesion tensile and shearing forces of planar and non-planar FDM
Fa = attacking force; Ft = tensile component of Fa; Fs = shearing component of Fa; β = tangent angle

One advantage resides in the ability to address FDM Z-layer adhesion issues by distributing force or stress vectors along any kind of trajectory and optimize material vs strength of the overall printed piece, e.g. when using continuous fiber filament and lay it along most stressed locations.

Further, the ability to have top layers align to object’s surface directly, no more layer lines. Essentially being able to define and manufacture a piece based on inner structure requirements and its outer form requirements.

References

Misc: XYZdims State 2022/02

Updates:

  • 2022/02/20: finally published
  • 2022/02/08: ready to publish finally with some delay
  • 2022/01/28: not yet published, removed Universal Slicing details for future blog-post, added more photos and illustrations
  • 2022/01/16: starting write-up

Introduction

Aside of the technical detailed filled blog-posts I like to start to post about the larger context of my inner motivations doing XYZdims.com – this is the first post “XYZdims State 2022/02”:

More Slicers

Recent in-house developments having more slicers to experiment with, in regards of slicing techniques as well lay the ground for more complex slicing and mapping/transformation operations to support arbitrary non-planar slicing (coming soon).

LabSlicer: The Mother

Big Picture of XYZdims – State 2022/02
(click on it and then zoom in, it’s a large image)

As I was working with Slicer4RTN and wrappers like Cura-CLI-Wrapper and Kiri:Moto Slicer (CLI wrapper), and adopting Mandoline fork – I realized I need to have my own slicer, so in November 2021 I started from scratch, as I thought I need to know every detail and so I exposed each step or stage:

  • mesh: load mesh, vertices & faces
  • slice: slice layers into sets of polygons
  • route: route the layer polygons with walls, infills etc
  • gcode: convert routes to G-code

A “lab(oratory) slicer” or simply LabSlicer was born – I defined each stage: API and file-format it takes in and spits out.

After a couple of weeks I had slicing into polygons, and routing of walls, basic infills, skirts, brims and eventually intermediary top & bottom layers resolved, and I was able to generate printable gcode:

Meanwhile LabSlicer as of version 0.1.5 has matured to print complex models reliably but rather performs slow compared to Slic3r or Cura.

As of 2022/02 I’m even use LabSlicer and its relatives (featured below) for productive 3D prints.

Vox3lSlicer: Voxels

Aside of LabSlicer I began to develop Vox3lSlicer which utilizes internally the OpenVDB voxel library, in order to slice planar and in the future non-planar as well, and also permit to slice voxel-based models efficiently.

A few tests with OpenSCAD Logo model (~20mm height) with various amount voxel samples, from low resolution to high resolution:

and with defined voxel sizes:

As LabSlicer matured and LabSlicerCore library came to life, Vox3lSlicer (2011/11) utilizes the stage route and gcode of LabSlicerCore to actually produce printable G-code.

Testing the retraction code and settings of Vox3lSlicer, rotating the model in order to avoid support structure altogether:

VoxGLSlicer: OpenGL Slicing

Early VoxGLSlicer tests

As I was looking for other slicing procedures I came across OpenGL-ST-Slicer, which utilizes a clever OpenGL setup with GLSL (Shader Language) to render a mesh to a framebuffer with the volume information, and so slicing is done solely in the GPU almost instantly – I extended this approach and glued it together with LabSlicerCore and I was able to produce also printable G-code – VoxGLSlicer was born (2022/01).

Due the limitation of the internal framebuffer width & height the resolution of the slicing changes with the size of the model aka “relative resolution”:

model width [mm]pixel size [mm] @ 2560 pixels
200.008 or 8 μm
500.019 or 19 μm
1000.039 or 39 μm
2000.078 or 78 μm
5000.19 or 195 μm
10000.39 or 390 μm

and just for illustration about “pixel size” related to a ~20mm model:

3 Slicers

After a few weeks coding (2021/11-2022/01), I was able to raise 3 slicers, each with their unique slicing approaches to create printable G-code, by having a common API and use symbiotic advantage of each other:

LabSlicerVox3lSlicerVoxGLSlicer
meshmesh.py1) multi-format mesh importeropenvdb STL importermesh.py1) multi-format mesh importer
sliceslicing mesh to polygons (vectorizing)slice voxels into polygons (vectorizing)screenbuffer into polygons (vectorizing)
routeroute polygons to routesLabSlicerCore’s routeLabSlicerCore’s route
gcodeconvert routes to G-codeLabSlicerCore’s gcodeLabSlicerCore’s gcode
+ traditional slicer with polygons
+ all stages fully implemented
– slow slicing2)
+ fast slicing
+ flexible resolution
+ reliable
+ fast slicing
– fixed screenbuffer size
– relative resolution

All three slicers are very experimental and play a significant role for the next step – Universal Slicing.

Footnotes:

  1. mesh.py is loading/saving 3d meshs/models and some simple manipulations tuned toward my use cases
  2. mesh slicing not yet optimized

So any optimizing of routing (wall, infill, intermediary top/bottom layers etc) and gcode optimizing all three slicers benefit from.

YAGV & Nautilus Thumbnailer Supporting ArcWelder

After the implementing G2/G3 emulation for gcode2png as part of the G-code thumbnailer, I also added it to G-code viewer yagv fork of mine:

Print3r

And just for sake of giving a bit of context, adding ArcWelderLib in the pipeline of Print3r via the configuration:

# first declare new post-processor named "arcwelder":
post_arcwelder = ArcWelder %i %o
# optionally, define it to be active (all the time):
post = arcwelder

or optionally enable it on the command-line:

% print3r print cube.stl --post=arcwelder

That’s it for now.

References