From 7c9b81a0c4de5a7f610685d8c7da8beaf784461f Mon Sep 17 00:00:00 2001
From: GatCode
Date: Tue, 17 Dec 2019 15:56:17 +0100
Subject: [PATCH 1/3] Add Python3 Support and Rename Project
---
README | 145 +++++++++++++++++++++++--------
file2graphtec | 2 +-
g2g_gui.py | 36 ++++----
gerber2graphtec | 48 +++++-----
logo.png | Bin 0 -> 19276 bytes
tests/test_array.py | 2 +
tests/test_array_antibacklash.py | 2 +
tests/test_calibrate.py | 2 +
tests/test_forces.py | 2 +
9 files changed, 157 insertions(+), 82 deletions(-)
create mode 100644 logo.png
diff --git a/README b/README
index d3aafea..f6b7d66 100644
--- a/README
+++ b/README
@@ -1,74 +1,143 @@
-Tool for cutting accurate SMT stencils on a Graphtec cutter (e.g. Silhouette Cameo or Portrait) from gerber files. Techniques include separately drawn line segments (no complex paths), antibacklash, drag-knife-angle "training", and multiple passes. This produces stencils usable down to approximately 0.5 mm pitch (QFP/QFN) and 0201 discrete components, or perhaps even slightly better; but it is slower than normal cutting.
+
+
+
cut SMT stencils from Gerber files
+
+
+[](https://github.com/pmonta/gerber2graphtec/blob/master/LICENSE)
+[](https://www.python.org)
+[](https://github.com/pmonta/gerber2graphtec/releases)
+## About
-Usage:
+SMTCut, previously called **gerber2graphtec**, is a tool for cutting accurate SMT stencils on a **Graphtec** or **Silhouette** vinyl cutter from Gerber files.
-A solderpaste gerber file, paste.gbr, and default settings:
+Techniques include separately drawn line segments (no complex paths), antibacklash, drag-knife-angle "training", and multiple passes.
- gerber2graphtec paste.gbr >/dev/usb/lp0
+This produces stencils usable down to approximately **0.5 mm pitch** (QFP/QFN) and **0201** discrete components, or perhaps even slightly better; but it is slower than normal cutting.
-A more elaborate command line with linear map (to correct spatial miscalibration) and multiple passes with different speeds and forces:
- gerber2graphtec --offset 3,4 --matrix 1.001,0,-0.0005,0.9985 --speed 2,1 --force 5,25 paste.gbr >/dev/usb/lp0
+## Getting Started
-You may want to have your CAM tool shrink the paste features by about 2 mils before exporting to gerber. The craft-cutter knife, when cutting thin mylar, seems to spread out the geometry by about this amount. I'd suggest using mylar with thickness between about 3 and 5 mils; the IPC-recommended thicknesses for fine-pitch stencils are approximately in this range. (Typical inexpensive laser-transparency sheets happen to be just right, being somewhere between 3.5 and 4.3 mils.) You may have to experiment with the cutting speeds and forces for best quality with your materials.
+To be able to run this software, make sure that you have installed the following dependencies:
-With Mac OS X or Windows, the file2graphtec script can take the place of /dev/usb/lp0. Write gerber2graphtec's output to a temporary file (gerber2graphtec ... >foo), then send it to the cutter (file2graphtec foo). I've tested file2graphtec on Mac OS X but not on Windows. For Mac OS X, install XCode and macports, then install the dependencies with
+- [gerbv](http://gerbv.geda-project.org)
+- [pstoedit](http://www.calvina.de/pstoedit/)
+- [libusb](https://libusb.info)
-port install gerbv
-port install pstoedit
-port install libusb
+#### Install on Mac OSX:
+Make sure you already have installed [Homebrew](https://brew.sh/) and simply run the following commands:
-These will take some time to build.
+```
+brew install gerbv
+```
+```
+brew install pstoedit
+```
+```
+brew install libusb
+```
+Also make sure that you've installed the libusb1 python package or install it via
+```
+pip3 install libusb1
+```
-To run file2graphtec, you will also need the Python bindings for libusb-1.0. Download and install this package:
+## Usage
-http://pypi.python.org/pypi/libusb1
+In general there are two different cases to distinguish depending on your operating system. Please note that this process can take a few minutes before the cutter starts to cut!
-with the usual "python setup.py install" installation method (as the root user). If you don't need file2graphtec (perhaps you're on Linux and can just use the device node directly), this Python package isn't needed.
+### Linux
+E.g. a solderpaste gerber file (paste.gbr), and default settings:
-Ubuntu users may need to check their version of gerbv. Several users have reported that versions prior to 2.6.0 (such as 2.5.0) apparently have a bug related to omitting small apertures/pads. If your Linux distribution still has the old gerbv-2.5.0, please delete the package and instead build from source for the latest stable version:
+```
+gerber2graphtec paste.gbr >/dev/usb/lp0
+```
-http://gerbv.geda-project.org/
+Or a more elaborate command line with linear map (to correct spatial miscalibration) and multiple passes with different speeds and forces:
-Fedora 17 has gerbv-2.6.0 in its supplied package list, so no issue there. For Fedora-like systems, "yum install gerbv pstoedit tkinter".
+```
+gerber2graphtec --offset 3,4 --matrix 1.001,0,-0.0005,0.9985 --speed 2,1 --force 5,25 paste.gbr >/dev/usb/lp0
+```
-On some Linux distributions, permissions on /dev/usb/lp0 are restricted by default. To fix this, add yourself to the lp group and then log out and log back in:
+### Mac OSX and Windows
+With Mac OS X or Windows, the file2graphtec script can take the place of /dev/usb/lp0. But keep in mind that the software is tested on Mac OS X but not on Windows!
-sudo usermod -a --group lp your_userid
+E.g. a solderpaste gerber file (paste.gbr), and default settings:
+```
+python3 gerber2graphtec paste.gbr > tmpfile
+python3 file2graphtec tmpfile
+```
-Links:
+Or a more elaborate command line with linear map (to correct spatial miscalibration) and multiple passes with different speeds and forces:
-These pages have hints on usage (e.g. on Windows), materials, performance, calibration, etc:
+```
+python3 gerber2graphtec --offset 3,4 --matrix 1.001,0,-0.0005,0.9985 --speed 2,1 --force 5,25 paste.gbr > tmpfile
+python3 file2graphtec tmpfile
+```
+
+## Known issues
+Due to a bug inside ghostscript, you may need to downgrade to version < 9.26 or you might encounter repeating output --> [Issue17](https://github.com/pmonta/gerber2graphtec/issues/17)
+
+On Mac OSX this can be done by uninstalling ghostscript with:
+
+```
+brew uninstall --ignore-dependencies ghostscript
+```
+
+and reinstalling the version 9.25
+
+```
+brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/b0b6b9495113b0ac5325e07d5427dc89170f690f/Formula/ghostscript.rb
+```
+
+## Calibration
+To achieve the best results, one should run different calibrations, which can be found in the test folder after the blade is set. The following example shows how to calibrate the cutter on Mac OSX but the commands are also applicable to other operating systems (make sure you run these files from the main folder).
-http://pmonta.com/blog/2012/12/25/smt-stencil-cutting/
-http://dangerousprototypes.com/forum/viewtopic.php?f=68&t=5341
-http://hackeda.com/blog/start-printing-pcb-stencils-for-about-200/
-http://hackaday.com/2012/12/27/diy-smd-stencils-made-with-a-craft-cutter/
+```
+python3 tests/test_forces.py > tmpfile
+python3 file2graphtec python3 file2graphtec tmpfile
+```
+## GUI
-GUI:
+An optional GUI has been provided by [jesuscf](https://github.com/jesuscfv). It allows interactive selection of the input Gerber file, parameters, and cutting operations.
-An optional GUI has been provided by jesuscf (see the dangerousprototypes.com thread linked above). It allows interactive selection of the input Gerber file, parameters, and cutting operations. To use it, run the file g2g_gui.py.
+To use it, run the following command:
+```
+python3 g2g_gui.py
+```
-Dependencies:
+## Tips & Tricks
+You may want to have your CAM tool shrink the paste features by about 2 mils before exporting to gerber. The craft-cutter knife, when cutting thin mylar, seems to spread out the geometry by about this amount. I'd suggest using mylar with thickness between about 3 and 5 mils; the IPC-recommended thicknesses for fine-pitch stencils are approximately in this range. (Typical inexpensive laser-transparency sheets happen to be just right, being somewhere between 3.5 and 4.3 mils.) You may have to experiment with the cutting speeds and forces for best quality with your materials.
+
+Fedora 17 has gerbv-2.6.0 in its supplied package list, so no issue there. For Fedora-like systems, "yum install gerbv pstoedit tkinter".
+
+On some Linux distributions, permissions on /dev/usb/lp0 are restricted by default. To fix this, add yourself to the lp group and then log out and log back in:
+
+```
+sudo usermod -a --group lp your_userid
+```
+
+## Additional Information
+
+These pages have hints on usage (e.g. on Windows), materials, performance, calibration, etc:
-gerbv (>= 2.6.0)
-pstoedit
-Tkinter (when using g2g_gui)
+- [pmonta.com](http://pmonta.com/blog/2012/12/25/smt-stencil-cutting/)
+- [dangerousprototypes.com](http://dangerousprototypes.com/forum/viewtopic.php?f=68&t=5341)
+- [hackaday.com](http://hackaday.com/2012/12/27/diy-smd-stencils-made-with-a-craft-cutter/)
-Credits:
+## Credits
Thanks to the authors of robocut and graphtecprint for protocol documentation:
-http://gitorious.org/robocut
-http://vidar.botfu.org/graphtecprint
-https://github.com/jnweiger/graphtecprint
+- [robocut](http://gitorious.org/robocut)
+- [graphtecprint](http://vidar.botfu.org/graphtecprint)
+- [graphtecprint](https://github.com/jnweiger/graphtecprint)
Also thanks to this web page (Cathy Sexton) for inspiration:
-http://www.idleloop.com/robotics/cutter/index.php
+- [idleloop.com](http://www.idleloop.com/robotics/cutter/index.php)
-Her cutter seems to be quite a bit better than mine was out of the box. With Silhouette's default software my 0.5 mm pitch pads were distorted to the point of unusability.
+Her cutter seems to be quite a bit better than mine was out of the box.
+With Silhouette's default software my 0.5 mm pitch pads were distorted to the point of unusability.
diff --git a/file2graphtec b/file2graphtec
index a1d3be1..027d37e 100755
--- a/file2graphtec
+++ b/file2graphtec
@@ -37,7 +37,7 @@ if len(sys.argv)==2:
elif len(sys.argv)==1:
f = sys.stdin
else:
- print 'usage: file2graphtec [filename]'
+ print('usage: file2graphtec [filename]')
sys.exit(1)
endpoint = 1
diff --git a/g2g_gui.py b/g2g_gui.py
index 482fa00..cfb0b9d 100755
--- a/g2g_gui.py
+++ b/g2g_gui.py
@@ -1,15 +1,13 @@
#!/usr/bin/env python
-import Tkinter
-import tkMessageBox
-import tkFileDialog
+import tkinter
import sys
import os
import string
-from Tkinter import *
+from tkinter import *
from os import path, access, R_OK, W_OK
-top = Tkinter.Tk()
+top = tkinter.Tk()
top.title("Gerber to Graphtec")
Gerber_name = StringVar()
@@ -234,44 +232,44 @@ def default_cut_mode_str():
Label(top, text="Gerber File ").grid(row=1, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=Gerber_name).grid(row=1, column=1)
-Tkinter.Button(top, width=9, text = "Browse", command = get_input_filename).grid(row=1, column=2)
+tkinter.Button(top, width=9, text = "Browse", command = get_input_filename).grid(row=1, column=2)
Label(top, text="Output File ").grid(row=2, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=Output_name).grid(row=2, column=1)
-Tkinter.Button(top, width=9, text = "Browse", command = get_output_filename).grid(row=2, column=2)
+tkinter.Button(top, width=9, text = "Browse", command = get_output_filename).grid(row=2, column=2)
if os.name=='nt':
Label(top, text="gerbv path ").grid(row=3, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=gerbv_path).grid(row=3, column=1)
- Tkinter.Button(top, width=9, text = "Browse", command = get_gerbv_path).grid(row=3, column=2)
+ tkinter.Button(top, width=9, text = "Browse", command = get_gerbv_path).grid(row=3, column=2)
Label(top, text="pstoedit path ").grid(row=4, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=pstoedit_path).grid(row=4, column=1)
- Tkinter.Button(top, width=9, text = "Browse", command = get_pstoedit_path).grid(row=4, column=2)
+ tkinter.Button(top, width=9, text = "Browse", command = get_pstoedit_path).grid(row=4, column=2)
Label(top, text="Offset ").grid(row=5, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=offset_str).grid(row=5, column=1)
-Tkinter.Button(top, width=9, text = "Default", command = default_offset_str).grid(row=5, column=2)
+tkinter.Button(top, width=9, text = "Default", command = default_offset_str).grid(row=5, column=2)
Label(top, text="Border ").grid(row=6, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=border_str).grid(row=6, column=1)
-Tkinter.Button(top, width=9, text = "Default", command = default_border_str).grid(row=6, column=2)
+tkinter.Button(top, width=9, text = "Default", command = default_border_str).grid(row=6, column=2)
Label(top, text="Matrix ").grid(row=7, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=matrix_str).grid(row=7, column=1)
-Tkinter.Button(top, width=9, text = "Default", command = default_matrix_str).grid(row=7, column=2)
+tkinter.Button(top, width=9, text = "Default", command = default_matrix_str).grid(row=7, column=2)
Label(top, text="Speed ").grid(row=8, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=speed_str).grid(row=8, column=1)
-Tkinter.Button(top, width=9, text = "Default", command = default_speed_str).grid(row=8, column=2)
+tkinter.Button(top, width=9, text = "Default", command = default_speed_str).grid(row=8, column=2)
Label(top, text="Force ").grid(row=9, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=force_str).grid(row=9, column=1)
-Tkinter.Button(top, width=9, text = "Default", command = default_force_str).grid(row=9, column=2)
+tkinter.Button(top, width=9, text = "Default", command = default_force_str).grid(row=9, column=2)
Label(top, text="Cut Mode ").grid(row=10, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=cut_mode_str).grid(row=10, column=1)
-Tkinter.Button(top, width=9, text = "Default", command = default_cut_mode_str).grid(row=10, column=2)
+tkinter.Button(top, width=9, text = "Default", command = default_cut_mode_str).grid(row=10, column=2)
if os.name=='nt':
Label(top, text="Cutter Shared Name").grid(row=11, column=0, sticky=W)
@@ -279,10 +277,10 @@ def default_cut_mode_str():
Label(top, text="Cutter Device Name").grid(row=11, column=0, sticky=W)
Entry(top, bd =1, width=60, textvariable=cutter_shared_name_str).grid(row=11, column=1, sticky=E)
-Tkinter.Button(top, width=40, text = "Create Graphtec File", command = main_program).grid(row=12, column=1)
-Tkinter.Button(top, width=40, text = "Send Graphtec File to Silhouette Cutter", command = Send_to_Cutter).grid(row=13, column=1)
-Tkinter.Button(top, width=40, text = "Save Configuration", command = Save_Configuration).grid(row=14, column=1)
-Tkinter.Button(top, width=40, text = "Exit", command = Just_Exit).grid(row=15, column=1)
+tkinter.Button(top, width=40, text = "Create Graphtec File", command = main_program).grid(row=12, column=1)
+tkinter.Button(top, width=40, text = "Send Graphtec File to Silhouette Cutter", command = Send_to_Cutter).grid(row=13, column=1)
+tkinter.Button(top, width=40, text = "Save Configuration", command = Save_Configuration).grid(row=14, column=1)
+tkinter.Button(top, width=40, text = "Exit", command = Just_Exit).grid(row=15, column=1)
if path.isfile(CONFPATH) and access(CONFPATH, R_OK):
f = open(CONFPATH,'r')
diff --git a/gerber2graphtec b/gerber2graphtec
index c20be48..5f17f14 100755
--- a/gerber2graphtec
+++ b/gerber2graphtec
@@ -27,7 +27,7 @@ media_size = (12,11)
theta = 0
def floats(s):
- return map(float,string.split(s,','))
+ return list(map(float,str.split(s,',')))
argc = 1
while argc/dev/usb/lp0'
- print ''
- print 'options:'
- print ' --offset x,y translate to device coordinates x,y (inches)'
- print ' --border bx,by cut a border around the bounding box of the gerber file; 0,0 to disable'
- print ' --matrix a,b,c,d transform coordinates by [a b;c d]'
- print ' --speed s[,s2[,s3]] use speed s in device units; s2,s3 for multiple passes'
- print ' --force f[,f2[,f3]] use force f in device units; f2,f3 for multiple passes'
- print ' --cut_mode [0|1] 0 for highest accuracy (fine pitch), 1 for highest speed'
- print ' --media_size x,y size of media'
- print ' --rotate theta rotate counterclockwise by theta degrees'
- print ''
- print 'defaults:'
- print ' --offset 4.0,0.5 suitable for letter size (portrait) on the Cameo, fed as "media" not "mat"'
- print ' --border 1,1 1-inch border in x and y around gerber bounding box'
- print ' --matrix 1,0,0,1 identity linear transform for scale and skew calibration'
- print ' --speed 2,2 use two passes, speed 2 in each pass'
- print ' --force 8,30 use force 8 for first pass, force 30 for second pass'
- print ' --cut_mode 0 highest accuracy'
- print ' --media_size 12,11 use a media size of 12 inches in x, 11 inches in y'
- print ' --rotate 0 no rotation'
- print ''
+ print('usage: gerber2graphtec [options] paste.gbr >/dev/usb/lp0')
+ print('')
+ print('options:')
+ print(' --offset x,y translate to device coordinates x,y (inches)')
+ print(' --border bx,by cut a border around the bounding box of the gerber file; 0,0 to disable')
+ print(' --matrix a,b,c,d transform coordinates by [a b;c d]')
+ print(' --speed s[,s2[,s3]] use speed s in device units; s2,s3 for multiple passes')
+ print(' --force f[,f2[,f3]] use force f in device units; f2,f3 for multiple passes')
+ print(' --cut_mode [0|1] 0 for highest accuracy (fine pitch), 1 for highest speed')
+ print(' --media_size x,y size of media')
+ print(' --rotate theta rotate counterclockwise by theta degrees')
+ print('')
+ print('defaults:')
+ print(' --offset 4.0,0.5 suitable for letter size (portrait) on the Cameo, fed as "media" not "mat"')
+ print(' --border 1,1 1-inch border in x and y around gerber bounding box')
+ print(' --matrix 1,0,0,1 identity linear transform for scale and skew calibration')
+ print(' --speed 2,2 use two passes, speed 2 in each pass')
+ print(' --force 8,30 use force 8 for first pass, force 30 for second pass')
+ print(' --cut_mode 0 highest accuracy')
+ print(' --media_size 12,11 use a media size of 12 inches in x, 11 inches in y')
+ print(' --rotate 0 no rotation')
+ print('')
sys.exit(1)
#
@@ -92,7 +92,7 @@ if not input_filename:
temp_pdf = "_tmp_gerber.pdf"
temp_pic = "_tmp_gerber.pic"
-if string.lower(input_filename[-3:])=='pdf':
+if str.lower(input_filename[-3:])=='pdf':
os.system("pstoedit -f pic %s %s 2>/dev/null" % (input_filename,temp_pic))
else:
os.system("gerbv --export=pdf --output=%s --border=20 %s" % (temp_pdf,input_filename))
diff --git a/logo.png b/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..fc1d8036904b367e5325fdb711cb9fd81ed80507
GIT binary patch
literal 19276
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
literal 0
HcmV?d00001
diff --git a/tests/test_array.py b/tests/test_array.py
index a93b007..42cebe1 100644
--- a/tests/test_array.py
+++ b/tests/test_array.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+import sys
+sys.path.insert(0, '')
import random
import graphtec
diff --git a/tests/test_array_antibacklash.py b/tests/test_array_antibacklash.py
index 82e9022..95a0d8b 100644
--- a/tests/test_array_antibacklash.py
+++ b/tests/test_array_antibacklash.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+import sys
+sys.path.insert(0, '')
import random
import graphtec
diff --git a/tests/test_calibrate.py b/tests/test_calibrate.py
index 4c2446d..e825860 100644
--- a/tests/test_calibrate.py
+++ b/tests/test_calibrate.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+import sys
+sys.path.insert(0, '')
import graphtec
import math
diff --git a/tests/test_forces.py b/tests/test_forces.py
index 8918959..985dd78 100644
--- a/tests/test_forces.py
+++ b/tests/test_forces.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+import sys
+sys.path.insert(0, '')
import graphtec
offset = (5,1)
From 7dba7ecc9b4b6f6b4e6029ee7298d4367413429c Mon Sep 17 00:00:00 2001
From: GatCode
Date: Tue, 17 Dec 2019 15:58:18 +0100
Subject: [PATCH 2/3] Change to README.md
---
README => README.md | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename README => README.md (100%)
diff --git a/README b/README.md
similarity index 100%
rename from README
rename to README.md
From 85ea921f7ac584a8fc5fe71d9ad34b3bb48d7716 Mon Sep 17 00:00:00 2001
From: GatCode
Date: Tue, 17 Dec 2019 15:59:33 +0100
Subject: [PATCH 3/3] Fix badges
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index f6b7d66..9f8e928 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
cut SMT stencils from Gerber files
+
[](https://github.com/pmonta/gerber2graphtec/blob/master/LICENSE)
[](https://www.python.org)
[](https://github.com/pmonta/gerber2graphtec/releases)