Prynt3r

Updates

  • 2023/01/22: published, adding machine_uuid details
  • 2023/01/09: keeping in sync with actual development
  • 2022/12/28: starting writeup

Introduction

Prynt3r (prynt3r) is the Python reimplementation (2022) of my own Print3r (print3r) which was written in Perl back in ~2017.

Features

  • print, slice or preview 3D print jobs (gcode, stl, obj, 3mf, svg, scad, etc)
  • pure command-line interface (CLI)
  • multiple slicers are supported (slic3r, prusa, cura, kirimoto, mandoline, etc), yet, with common slicer agnostic settings
  • multiple printer profiles
  • remote/network printing built-in (tcp, rrf)
  • all prints are logged with all settings incl. unique identifier per print job1)
  1. ability to uniquely identify parts by attaching QR codes of RFID stickers with print UID to tie physical part with print job

Download

After download and installation, you can start to configure and use it:

Usage

          ____    .              __ _____         .
     *   / __ \_______* ______  / /|__  /_____                 *
        / /_/ / ___/ / / / __ \/ __//_ </ ___/  .         |             *
   .   / ____/ /  / /_/ / / / / /____/ / /              -=*=-      .
      /_/   /_/   \__, /_/ /_/\__/____/_/        *   .    |
                 /____/                     V0.0.8           *          .
      https://github.com/Spiritdude/Prynt3r

Prynt3r 0.0.8 USAGE: [<opts>] <cmd> <arg1> ...

   commands:
      slice <file1> ...    slice file(s) into single gcode, e.g. use -o <fn> or --output=<fn>
      print <file1> ...    slice and send gcode to printer local or remote, e.g. define -d <dev> or --device=<dev>
      preview <file1> ...  slice file(s) into single gcode and launch gcode viewer
      gconsole             starts interactive g-code console
      log [<s>] [#<n>]     list log, query term <s> or list log entry '#<n>', with --output or -o you can list only particul
ars
      client               start client process, so remote prynt3r can access it

   file-formats:
      stl, obj, off, 3mf, ply, scad, jscad, zcad, vdb, svg

   options:
      --help               print this message
      --version            print version and exit

      --device=<dev>       set device (default: /dev/ttyUSB0)
        -d <dev>

      --printer=<name>     set printer name (default: default)
        -p <name>

      --slicer=<slicer>    set slicer: cura, cura-legacy, cura4, cura5, curax, prusa, slic3r, slic3r-pe, slicer4rtn, cura-slicer, super, mandoline, 5dmaker, kirimoto, zplus, lab, vox3l, voxgl, metatron, enoch, goslice, (default: slic3r)
        -s <slicer>

      --gcode-viewer=<cmd> set gcode previewer (default: yagv)

      --verbose=<n>        increase verbosity
         -vvv
      --extended or -x     extended output, e.g. for 'log' command
      --quiet or -q        stay quiet, only output warnings or errors

      --output=<fn>        slice: slicing into a particular file 'prynt3r slice cube.stl -o test.gcode' or
         -o <fn>              log: 'prynt3r log -o uid,files,args' to list particular fields of the log file

      --placement=<loc>    set location: 'none', 'center', 'random' (default: none)

      --rotate=<x>,<y>,<z> rotate model(s)
      --scale=<f>          scale model(s) uniformly
      --scale=<x>,<y>,<z>  scale model(s), if value has 'mm' appended, then axis is set absolute
                              e.g. "0,0,20mm" scales model(s) to 20mm Z height, all axes with 0 scales
                              proportionally

      --multiply-part=<n>  multiply model(s)

      --recenter=<s>       recenter models (default: 1), recommended when rotating
      --relevel=<s>        relevel models (default: 1), recommended when rotating

      --uid=<uid>          set uid for print process (otherwise unique will be generated)
      --keep               keep all temporary files (for debugging)

      --scad               treat arguments as OpenSCAD code, e.g. --scad 'cube(20)'
         --scadlib=<lib>[,<lib2>]   consider libraries as well, e.g. --scadlib=parts.scad
      --zcad               treat arguments as OpenZCAD code
      --jscad              treat arguments as OpenJSCAD code

  slicing options (slicer independent):
      --machine-name=<v>         set machine name (default: "Unknown")
      --machine-uuid=<v>         set machine uuid (default: "")
      --machine-width=<v>        set machine width (default: 200.0)
      --machine-depth=<v>        set machine depth (default: 200.0)
      --machine-height=<v>       set machine height (default: 180.0)
      --nozzle-diameter=<v>      set nozzle diameter (default: "0.4")
      --line-width=<v>           set line width (default: 0.4)
      --layer-height=<v>         set layer height (default: "0.3")
      --filament-diameter=<v>    set filament diameter (default: "1.75")
      --fill-density=<v>         set fill density (default: "20")
      --temperature=<v>          set temperature (default: "200")
      --first-layer-temperature=<v> set first layer temperature (default: "210")
      --bed-temperature=<v>      set bed temperature (default: "45")
      --first-layer-height=<v>   set first layer height (default: "0.25")
      --first-layer-speed=<v>    set first layer speed (default: "20")
      --skirts=<v>               set skirts (default: "2")
      --brims=<v>                set brims (default: "0")
      --rafts=<v>                set rafts (default: "0")
      --support=<v>              set support (default: "none")
      --support-angle=<v>        set support angle (default: "60")
      --seam=<v>                 set seam (default: "aligned")
      --top-thickness=<v>        set top thickness (default: "0")
      --bottom-thickness=<v>     set bottom thickness (default: "0")
      --wall-thickness=<v>       set wall thickness (default: "0")
      --perimeters=<v>           set perimeters (default: "2")
      --top-layers=<v>           set top layers (default: "2")
      --bottom-layers=<v>        set bottom layers (default: "2")
      --start-gcode=<v>          set start gcode (default: "G28 X0 Y0\\nG1 X100 F6000\\nG28 Z0\\nM206 X0 Y-25 Z0.15\\n\n")
      --end-gcode=<v>            set end gcode (default: "G1 Y290 F6000\\nM104 S0\\nM140 S0\\nM84\\n")
      --abort-gcode=<v>          set abort gcode (default: "M104 S0 ; extruder heater off\\nM140 S0 ; heated bed heater off (if you have it)\\nG1 X10 F9000 ; go way to the left\\nM84     ; motors off\\n")
      --prepend-gcode=<v>        set prepend gcode (default: "")
      --retraction-length=<v>    set retraction length (default: "2")
      --retraction-speed=<v>     set retraction speed (default: "70")
      --print-speed=<v>          set print speed (default: "60")
      --travel-speed=<v>         set travel speed (default: "130")
      --perimeter-speed=<v>      set perimeter speed (default: "60")
      --small-perimeter-speed=<v> set small perimeter speed (default: "15")
      --infill-speed=<v>         set infill speed (default: "80")
      --bridge-speed=<v>         set bridge speed (default: "60")
      --extruders-count=<v>      set extruders count (default: "1")
      --cool-fan-speed=<v>       set cool fan speed (default: "100")
      --cool-fan-speed-min=<v>   set cool fan speed min (default: "30")
      --cool-fan-speed-max=<v>   set cool fan speed max (default: "100")

   examples:
      prynt3r print cube.stl
      prynt3r print cube.scad
      prynt3r -p prusa-i3 print --scad 'cube(20)'
      prynt3r -p ashtar-k-1 -s cura5 slice cube.3mf
      prynt3r -p ashtar-k-1 -s cura5 print structure.vdb -d tcp:192.168.1.32:0
      prynt3r -s prusa slice cube.stl -o a.gcode
      prynt3r preview cube.stl
      prynt3r log
      prynt3r log cube.stl -v
      prynt3r log '#100' -xv
      prynt3r log -o uid,args,files
      prynt3r -d /dev/ttyACM0 client &
      prynt3r -d /dev/ttyACM1 gconsole
      > M115

Setup

First you need to adjust the profile for your 3D printer(s):

% cd ~/.config/prynt3r/printer
% cp /usr/share/prynt3r/printer/default.ini myprinter.ini

as next edit myprinter.ini according the specifications of your printer, after that your profile is available as -p myprinter or --printer=myprinter when calling prynt3r:

% prynt3r -p myprinter print --scad 'cube(20)' --fill-density=0

Machine UUID

Optionally, if you run a bunch of 3D printers, define machine_uuid in your .ini file, which references the Marlin’s UUID or RepRapFirmware’s Board ID or as fallback the MAC of the Wi-Fi – this is what the machine_uuid is verified with on serial or remote connection.

Retrieve the UUID with

% prynt3r -d /dev/ttyACM0 gconsole

and then send M115 and M122, like:

Marlin M115

% FIRMWARE_NAME:Marlin 2.0.9.1 (Sep 23 2022 16:48:31) SOURCE_CODE_URL:github.com/MarlinFirmware/Marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:Ashtar K E3 #3 L8 EXTRUDER_COUNT:3 UUID:8309209b-1c20-11ed-861d-0122ac4e0002
Cap:SERIAL_XON_XOFF:0
Cap:BINARY_FILE_TRANSFER:0
Cap:EEPROM:1
Cap:VOLUMETRIC:1
Cap:AUTOREPORT_POS:0
Cap:AUTOREPORT_TEMP:1
Cap:PROGRESS:0
Cap:PRINT_JOB:1
Cap:AUTOLEVEL:0
Cap:RUNOUT:0
....

RepRapFirmware M122

RepRapFirmware for Duet 3 Mini 5+ version 3.4.0alpha (2021-07-09 08:59:45) running on Duet 3 Mini5plus Ethernet (standalone mode)
Board ID: ABR3A-KA67A-J03J0-40TFS-21D0Z-RTDXU
Used output buffers: 1 of 40 (2 max)
=== RTOS ===
Static ram: 102768
Dynamic ram: 105632 of which 0 recycled
Never used RAM 35304, free system stack 155 words
Tasks: NETWORK(ready,25.8%,546) ETHERNET(notifyWait,0.0%,662) HEAT(notifyWait,0.0%,361) Move(notifyWait,0.1%,302) CanReceiv(notifyWait,0.0%,939) CanSender(notifyWait,0.0%,371) CanClock(delaying,0.0%,340) TMC(notifyWait,1.1%,112) MAIN(running,72.1%,438) IDLE(ready,0.1%,29) AIN(delaying,0.8%,262), total 100.0%
Owned mutexes: USB(MAIN)
...

without Board ID, checking the WiFi MAC:

- WiFi -
Network state is active
WiFi module is connected to access point
Failed messages: pending 0, notready 0, noresp 0
Bad header: 0/0
WiFi firmware version 1.26-08S32-D
WiFi MAC address ad:15:a3:15:6c:95
WiFi Vcc 0.00, reset reason Power up
WiFi flash size 0, free heap 151828

A printer is identified with:

  • CLI: printer nickname with --printer=<nick> or -p <nick>
  • <nick>.ini: machine_name=“Full Name” where you write it out exactly, e.g. “Ashtar K #3 PAX”, which means it’s Ashtar K number 3 with PAX extension
  • <nick>.ini: machine_uuid=<uid> where you ensure the actual identity with the hardware at time of connecting

Networked Printing

You can print to a computer which has 3D printers connected to, if you run

prynt3r -d /dev/ttyACM0 client &
prynt3r -d /dev/ttyACM1 client &

on the host which has the printer(s) attached, and then on your main computer:

prynt3r -d tcp:host:0 -p myprinter1 print --scad 'cube(20)'
prynt3r -d tcp:host:1 -p myprinter2 print --scad 'cube(20)'

RepRapFirmware Wi-Fi/Ethernet

[Coming Soon] If you run RepRapFirmware like on Duet3D boards, then you can reference them as such:

% prynt3r -d rrf:192.168.0.100 -p myprinter1 print --scad 'cube(20)'

it will upload the .gcode and run it, yet, prynt3r will wait until the print is finished.

Prynt3r vs Print3r

So far the slicer independent settings of Print3r are the same as for Prynt3r, so you can migrate the ~./config/print3r/printer/* into ~/.config/prynt3r/printer/* simply, the same with the macros.

Migrate from Print3r to Prynt3r

cd ~
mkdir .config/prynt3r
cp -rp .config/print3r/* .config/prynt3r/

The same as print3r:

  • printer profiles
  • slicer profiles incl. mapping
  • macro profiles
  • protocol for remote printing

The differences as print3r:

  • new: better usage output with actual list of slicer independent settings
  • new: written in Python
  • new: smaller code-base (Py ~1.2K lines vs Perl 4.1K lines)
    • one main reason is using trimesh doing import/export/manipulation of meshs incl. diverse mesh formats
  • removed: no gcode rendering into PNG

References