AIoT: How To Build PCB Using CNC/3D Printer (Gerber Gcode python code converter)
PCB
KiCad
Gcode / 3D Printer
In this tutorial I will explain how to make a PCB boards from A to Z using a CNC or 3D printer, you will need: ¶
- PCB board
- Indelible pen
- Ferric chloride
- Acetone
- A 0.8 mm drill bit
The process will be as follows: ¶
- Draw your circuit (with KiCad for example) and generate gerber files (to draw tracks) and drill files (for drilling)
- Convert your file to GCode format ( source code below ) </span>
- Print the tracks on the map (with your cnc or modified 3D printer)
- Drill the holes (if cnc menu of a drilling head)
- Pass into Ferric chloride solution (10 to 15 min)
- Use Acetone to clean
- You can now solder your electronic components
1st step: Build the support of the indelible pen ¶
Attached are the 3D files (sketchup and stl) that I used for my cnc ¶
Once you atatch it to your cnc (or 3D ,Printer) it will look like below
I do not detail the steps for creating an electronic circuit in this tutorial, several sites allow you to do it easily online, I used KiCad 6, and I generated the manufacturing file (gerber) ¶
2nd step: ¶
To draw the tracks on the map we will use a cnc or a 3D printer with a modified head (see figures and files in step 1 ) ¶
The following source code makes it possible to generate two gcode files: one to draw the tracks, another to drill the holes of the electronic components. ¶
NB: This code works (and has been tested only) for tracks over 0.4 mm in diameter, square, oval or circular drill locations, and holes of 0.8 mm (well, for the drill diameter you can try d other strong) ¶
Let's see how to process a gerber file and how gcode works to draw equivalent tracks or drills (links for full details sites are below)¶
gerber file a text file with instruction to builds forms for tracks end drills¶
Now we have to translate gerber code to gcode code to draw the tracks ¶
NB : For my simple use case, I consider that everdy circle and square have to hold a drill on its center
G Codes Reminder
G00 = rapid movement
G01 = move at the specified feedrate*
G02 = clockwise arc or circle movement*
G03 = counter clockwise arc or circle movement*
G17 = X Y plane selection
G20 = coordinates in inches
G21 = coordinates in MM
G28 = home position return*
G40 = cutter compensation cancel
G41 = cutter compensation left
G42 = cutter compensation right
G43 = tool length compensation on
G53 = cancel work offsets
G54,G55,G56,G57,G58 and G59 = work offsets
G80 = cancel canned cycle
G81 = basic drilling canned cycle*
G83 = peck drilling canned cycle*
G90 = absolute programming
G91 = incremental programming
M Codes
M00 = program stop
M01 = optional stop
M03 = spindle on
M05 = spindle off
M06 = tool change
M30 = end of program, rewind and reset
M97 = subroutine call
M98 = subprogram call
M99 = subprogram end
Cnc Program Header
% (Identifies the start of the program)
ODRILL (program name)
G17 G20 G40 G49 G80 G90 (safety line establishing important G codes)
T1 M06 (Tool call and tool change commands)
G00 G54 X0. Y0. S2000 M03 (X and Y pre-position line)
G43 H1 Z1. (Tool length offset command and Z pre-position line)
Cnc Program Footer
G00 Z1. (move up in Z 1” above the Z datum)
M05 (stop the spindle)
G91 G28 X0. Y0. Z0. (rapid move to home position)
G90 (re-establish absolute programming mode)
M30 (finish program and rewind to the beginning and stop)
% (identifies the end of the program)
This simple example illustrates the how to mill a circle.¶
%
G00 Z0.5 (raise the tool to the clearance height)
G00 X-5 Y15 F50 (Tool movement to the point of beginning of milling Fast 50 )
G01 Z-1 (lower the tool to the desired cutting depth)
G02 I10
G00 Z0.5 (raise the tool to the clearance height)
G00 X0 Y0 (the movement the tool to the starting point)
M30
%
Cercle parfait¶
(CERCLE DE 40 mm)
G0 X0Y0 S0
F500
M3 S1000 (MOTOR START MAX)
G0 Y20 (monte à 2 cm = départ du cercle)
G2 X20 Y40 R20 S1000
X40 Y20 R20 (Seul G2 peut être omis)
X20 Y0 R20
X0 Y20 R20
G0 X0 Y0 S0 (Home MIN)
M5 (MOTOR END)
This simple example illustrates the how to mill a rectangle.¶
%
G00 Z0.5 (raise the tool to the clearance height)
G00 X0 Y0 (the movement of the tool to the start point of the milling (point 5))
G01 Z-1 F50 (lower the tool to the desired cutting depth)
G01 X0 Y20 F50 (milling side a)
G01 X30 Y20 (milling side b)
G01 X30 Y0 (milling side a)
G01 X0 Y0 (milling side b, return to the start point for milling) G00 Z0.5 F70 (raise the tool to the clearance height)
M30 (end of the control program)
%
So Let's draw gerber file on a canva (to be sure what we are dowing, and generate corresponding gcode in the same time) ¶
Parsing gerber file, draw on canvas, and generate matching gcode ¶
The pen has a 0.2 mm diamter, folllowing code will ignore customs forms on gerber file, but it will work for simple usage case for PCB mono or bi layer with +0.2 mm tracks ¶
In [5]:
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
from ipycanvas import Canvas
In [3]:
GRB="sonde_ailis-F_Cu.gbr"
ZW="-0.1"
ZOFF="2"
GOZFAR="G00 Z"+ZOFF
GOZW="G01 Z"+ZW+" F500"
pens={}
actualpen=None
fig, ax = plt.subplots()
print(GOZFAR);
print("G00 X0 Y0")
print(GOZW)
print(GOZFAR)
print("F500")
f = open(GRB)
#print(f.read())
for line in f:
if line[:3]=="G04":
#print("comment", " : ", line )
continue
if line[:3]=="%MO":
#print("MM or Inch", " : ", line )
continue
if line[:3]=="%TF" or line[:3]=="%TA" or line[:3]=="%TO" or line[:3]=="%TD":
#print("X2 Attribute ", " : ",line)
continue
if line[:5]=="%FSLA":
xl1=int(line[6])
xl2=int(line[7])
yl1=int(line[9])
yl2=int(line[10])
#print(xl1,xl2,yl1,yl2)
continue
if line[:3]=="%AD":
#print("Aperture Definition", " : ", line )
if line[3]=="D":
i=0
for c in line[4:]:
if not c.isdigit():
break
i+=1
#print("found ",line[4:4+i])
j=i+4
for c in line[j:]:
if c==",":
break;
j+=1
#print("D=",line[4:4+i], "Forme=", line[i+4:j], "Desc =", line[j+1:-3])
pens[line[4:4+i]]=[(line[i+4:j],line[j+1:-3])]
#print("3 ",line[j+1:-3])
if line[0]=="D":
numa=line[1:-2]
#print("found D=",numa, "pen form=", pens[numa][0][0]," desc=", pens[numa][0][1])
actualpen=pens[numa][0]
if line[0]=="X":
#X157480000Y-101600000D03*
#print("Drawing",line)
i1=1
for c in line[1:]:
if c=="Y":
break
i1+=1
x=line[1:i1]
i2=i1
for c in line[i1+1:]:
if c=="D":
break
i2+=1
y=line[i1+1:i2+1]
op=line[-3]
if x[0]=="-":
x=x[1:]
xx=-int(x[:-6])
xxf=int(x[-6])*10**(-1)
else:
xx=int(x[:-6])
xxf=int(x[-6])*10**(-1)
if y[0]=="-":
y=y[1:]
yy=-int(y[:-6])
yyf=-int(y[-6])*10**(-1)
else:
yy=int(y[:-6])
yyf=int(y[-6])*10**(-1)
xx=xx+xxf
yy=yy+yyf
xx=-xx #mirror
xx+=170 #center
yy+=130 #center
#print("drawing",xx,yy,op,line)
actualxx=xx
actualyy=yy
#print("actual",actualxx,actualyy)
if op=="3": #circle
if actualpen[0]=="C":
r=float(actualpen[1])/2
circle1 = plt.Circle((xx, yy), r, color='r')
ax.add_patch(circle1)
print(GOZFAR)
gc1="G00 X"+str(round(xx,1))+" Y"+str(round(yy,2))
print(gc1)
print(GOZW)
gc2="G2 X" +str(round(xx,1))+" Y"+str(round(yy,2))+ " I"+str(round(r,1))+ " J0"
print(gc2)
#print(GOZFAR)
if actualpen[0]=="O":
r=1
circle1 = plt.Circle((xx, yy), r, color='r')
ax.add_patch(circle1)
print(GOZFAR)
gc1="G00 X"+str(round(xx,1))+" Y"+str(round(yy,2))
print(gc1)
print(GOZW)
gc2="G2 X" +str(round(xx,1))+" Y"+str(round(yy,2))+ " I"+str(round(r,1))+ " J0"
print(gc2)
#print(GOZFAR)
if actualpen[0]=="RoundRect":
r=0.8
circle1 = plt.Circle((xx, yy), r, color='g')
ax.add_patch(circle1)
print(GOZFAR)
gc1="G00 X"+str(round(xx,1))+" Y"+str(round(yy,2))
print(gc1)
print(GOZW)
gc2="G2 X" +str(round(xx,1))+" Y"+str(round(yy,2))+ " I"+str(round(r,1))+ " J0"
print(gc2)
#print(GOZFAR)
if actualpen[0]=="R":
print(actualpen[1])
circle1 = plt.Circle((xx, yy), r, color='b')
ax.add_patch(circle1)
print(GOZFAR)
gc1="G00 X"+str(round(xx,1))+" Y"+str(round(yy,2))
print(gc1)
print(GOZW)
gc2="G2 X" +str(round(xx,1))+" Y"+str(round(yy,2))+ " I"+str(round(r,1))+ " J0"
print(gc2)
#print(GOZFAR)
if op=="2":
currentxx=xx
currentyy=yy
#print("current",currentxx,currentyy)
continue
if op=="1":
#draw from current to actual using actuel shape stored in actualpen
plt.plot([currentxx,actualxx], [currentyy,actualyy], linewidth=4, color='#4b0082')
print(GOZFAR)
gc1="G00 X"+str(round(currentxx,1))+" Y"+str(round(currentyy,2))
print(gc1)
print(GOZW)
gc2="G01 X"+str(round(actualxx,1))+" Y"+str(round(actualyy,2))+" F500"
print(gc2)
print(GOZFAR)
f.close()
#print(pens)
ax.set_aspect('equal', adjustable='datalim')
ax.plot() #Causes an autoscale update.
plt.show()
'''f = open(GRB)
#print(f.read())
for x in f:
print(x)
f.close()
'''
G00 Z2 G00 X0 Y0 G01 Z-0.1 F500 G00 Z2 F500 G00 Z2 G00 X12.6 Y28.4 G01 Z-0.1 F500 G2 X12.6 Y28.4 I0.8 J0 G00 Z2 G00 X10.0 Y28.4 G01 Z-0.1 F500 G2 X10.0 Y28.4 I0.8 J0 G00 Z2 G00 X7.5 Y28.4 G01 Z-0.1 F500 G2 X7.5 Y28.4 I0.8 J0 G00 Z2 G00 X4.9 Y28.4 G01 Z-0.1 F500 G2 X4.9 Y28.4 I0.8 J0 G00 Z2 G00 X30.3 Y15.7 G01 Z-0.1 F500 G2 X30.3 Y15.7 I1.2 J0 G00 Z2 G00 X30.3 Y36.1 G01 Z-0.1 F500 G2 X30.3 Y36.1 I1 J0 G00 Z2 G00 X10.0 Y53.8 G01 Z-0.1 F500 G2 X10.0 Y53.8 I0.8 J0 G00 Z2 G00 X10.0 Y51.3 G01 Z-0.1 F500 G2 X10.0 Y51.3 I0.8 J0 G00 Z2 G00 X10.0 Y48.8 G01 Z-0.1 F500 G2 X10.0 Y48.8 I0.8 J0 G00 Z2 G00 X64.6 Y55.8 G01 Z-0.1 F500 G2 X64.6 Y55.8 I0.8 J0 G00 Z2 G00 X64.6 Y53.3 G01 Z-0.1 F500 G2 X64.6 Y53.3 I0.8 J0 G00 Z2 G00 X64.6 Y50.8 G01 Z-0.1 F500 G2 X64.6 Y50.8 I0.8 J0 G00 Z2 G00 X64.6 Y48.2 G01 Z-0.1 F500 G2 X64.6 Y48.2 I0.8 J0 G00 Z2 G00 X64.6 Y45.7 G01 Z-0.1 F500 G2 X64.6 Y45.7 I0.8 J0 G00 Z2 G00 X64.6 Y43.1 G01 Z-0.1 F500 G2 X64.6 Y43.1 I0.8 J0 G00 Z2 G00 X64.6 Y40.6 G01 Z-0.1 F500 G2 X64.6 Y40.6 I0.8 J0 G00 Z2 G00 X64.6 Y38.1 G01 Z-0.1 F500 G2 X64.6 Y38.1 I0.8 J0 G00 Z2 G00 X64.6 Y35.5 G01 Z-0.1 F500 G2 X64.6 Y35.5 I0.8 J0 G00 Z2 G00 X64.6 Y33.0 G01 Z-0.1 F500 G2 X64.6 Y33.0 I0.8 J0 G00 Z2 G00 X64.6 Y30.4 G01 Z-0.1 F500 G2 X64.6 Y30.4 I0.8 J0 G00 Z2 G00 X64.6 Y27.9 G01 Z-0.1 F500 G2 X64.6 Y27.9 I0.8 J0 G00 Z2 G00 X64.6 Y25.4 G01 Z-0.1 F500 G2 X64.6 Y25.4 I0.8 J0 G00 Z2 G00 X64.6 Y22.8 G01 Z-0.1 F500 G2 X64.6 Y22.8 I0.8 J0 G00 Z2 G00 X64.6 Y20.3 G01 Z-0.1 F500 G2 X64.6 Y20.3 I0.8 J0 G00 Z2 G00 X39.2 Y20.3 G01 Z-0.1 F500 G2 X39.2 Y20.3 I0.8 J0 G00 Z2 G00 X39.2 Y22.8 G01 Z-0.1 F500 G2 X39.2 Y22.8 I0.8 J0 G00 Z2 G00 X39.2 Y25.4 G01 Z-0.1 F500 G2 X39.2 Y25.4 I0.8 J0 G00 Z2 G00 X39.2 Y27.9 G01 Z-0.1 F500 G2 X39.2 Y27.9 I0.8 J0 G00 Z2 G00 X39.2 Y30.4 G01 Z-0.1 F500 G2 X39.2 Y30.4 I0.8 J0 G00 Z2 G00 X39.2 Y33.0 G01 Z-0.1 F500 G2 X39.2 Y33.0 I0.8 J0 G00 Z2 G00 X39.2 Y35.5 G01 Z-0.1 F500 G2 X39.2 Y35.5 I0.8 J0 G00 Z2 G00 X39.2 Y38.1 G01 Z-0.1 F500 G2 X39.2 Y38.1 I0.8 J0 G00 Z2 G00 X39.2 Y40.6 G01 Z-0.1 F500 G2 X39.2 Y40.6 I0.8 J0 G00 Z2 G00 X39.2 Y43.1 G01 Z-0.1 F500 G2 X39.2 Y43.1 I0.8 J0 G00 Z2 G00 X39.2 Y45.7 G01 Z-0.1 F500 G2 X39.2 Y45.7 I0.8 J0 G00 Z2 G00 X39.2 Y48.2 G01 Z-0.1 F500 G2 X39.2 Y48.2 I0.8 J0 G00 Z2 G00 X39.2 Y50.8 G01 Z-0.1 F500 G2 X39.2 Y50.8 I0.8 J0 G00 Z2 G00 X39.2 Y53.3 G01 Z-0.1 F500 G2 X39.2 Y53.3 I0.8 J0 G00 Z2 G00 X39.2 Y55.8 G01 Z-0.1 F500 G2 X39.2 Y55.8 I0.8 J0 G00 Z2 G00 X2.4 Y5.6 G01 Z-0.1 F500 G2 X2.4 Y5.6 I0.4 J0 G00 Z2 G00 X30.3 Y15.7 G01 Z-0.1 F500 G01 X20.2 Y15.7 F500 G00 Z2 G00 Z2 G00 X10.0 Y48.8 G01 Z-0.1 F500 G01 X10.0 Y31.0 F500 G00 Z2 G00 Z2 G00 X10.0 Y31.0 G01 Z-0.1 F500 G01 X10.0 Y28.4 F500 G00 Z2 G00 Z2 G00 X39.2 Y17.0 G01 Z-0.1 F500 G01 X38.0 Y15.7 F500 G00 Z2 G00 Z2 G00 X20.2 Y31.0 G01 Z-0.1 F500 G01 X10.0 Y31.0 F500 G00 Z2 G00 Z2 G00 X39.2 Y20.3 G01 Z-0.1 F500 G01 X39.2 Y17.0 F500 G00 Z2 G00 Z2 G00 X20.2 Y15.7 G01 Z-0.1 F500 G01 X20.2 Y31.0 F500 G00 Z2 G00 Z2 G00 X38.0 Y15.7 G01 Z-0.1 F500 G01 X30.3 Y15.7 F500 G00 Z2 G00 Z2 G00 X36.0 Y30.4 G01 Z-0.1 F500 G01 X35.4 Y31.0 F500 G00 Z2 G00 Z2 G00 X30.3 Y51.3 G01 Z-0.1 F500 G01 X30.3 Y36.1 F500 G00 Z2 G00 Z2 G00 X39.2 Y30.4 G01 Z-0.1 F500 G01 X36.0 Y30.4 F500 G00 Z2 G00 Z2 G00 X10.0 Y51.3 G01 Z-0.1 F500 G01 X30.3 Y51.3 F500 G00 Z2 G00 Z2 G00 X35.4 Y31.0 G01 Z-0.1 F500 G01 X35.4 Y36.1 F500 G00 Z2 G00 Z2 G00 X35.4 Y36.1 G01 Z-0.1 F500 G01 X30.3 Y36.1 F500 G00 Z2 G00 Z2 G00 X68.4 Y61.5 G01 Z-0.1 F500 G01 X71.0 Y58.9 F500 G00 Z2 G00 Z2 G00 X71.0 Y58.9 G01 Z-0.1 F500 G01 X71.0 Y23.4 F500 G00 Z2 G00 Z2 G00 X15.1 Y61.5 G01 Z-0.1 F500 G01 X68.4 Y61.5 F500 G00 Z2 G00 Z2 G00 X71.0 Y23.4 G01 Z-0.1 F500 G01 X70.4 Y22.8 F500 G00 Z2 G00 Z2 G00 X10.0 Y56.4 G01 Z-0.1 F500 G01 X15.1 Y61.5 F500 G00 Z2 G00 Z2 G00 X10.0 Y53.8 G01 Z-0.1 F500 G01 X10.0 Y56.4 F500 G00 Z2 G00 Z2 G00 X70.4 Y22.8 G01 Z-0.1 F500 G01 X64.6 Y22.8 F500 G00 Z2 G00 Z2 G00 X40.5 Y10.7 G01 Z-0.1 F500 G01 X17.6 Y10.7 F500 G00 Z2 G00 Z2 G00 X43.0 Y13.2 G01 Z-0.1 F500 G01 X40.5 Y10.7 F500 G00 Z2 G00 Z2 G00 X43.0 Y20.8 G01 Z-0.1 F500 G01 X43.0 Y13.2 F500 G00 Z2 G00 Z2 G00 X12.6 Y15.7 G01 Z-0.1 F500 G01 X12.6 Y28.4 F500 G00 Z2 G00 Z2 G00 X17.6 Y10.7 G01 Z-0.1 F500 G01 X12.6 Y15.7 F500 G00 Z2 G00 Z2 G00 X41.1 Y22.8 G01 Z-0.1 F500 G01 X43.0 Y20.8 F500 G00 Z2 G00 Z2 G00 X39.2 Y22.8 G01 Z-0.1 F500 G01 X41.1 Y22.8 F500 G00 Z2 G00 Z2 G00 X53.2 Y5.6 G01 Z-0.1 F500 G01 X53.2 Y53.8 F500 G00 Z2 G00 Z2 G00 X35.4 Y58.9 G01 Z-0.1 F500 G01 X35.4 Y46.2 F500 G00 Z2 G00 Z2 G00 X4.9 Y5.6 G01 Z-0.1 F500 G01 X53.2 Y5.6 F500 G00 Z2 G00 Z2 G00 X53.2 Y53.8 G01 Z-0.1 F500 G01 X48.1 Y58.9 F500 G00 Z2 G00 Z2 G00 X4.9 Y28.4 G01 Z-0.1 F500 G01 X4.9 Y5.6 F500 G00 Z2 G00 Z2 G00 X36.0 Y45.7 G01 Z-0.1 F500 G01 X39.2 Y45.7 F500 G00 Z2 G00 Z2 G00 X35.4 Y46.2 G01 Z-0.1 F500 G01 X36.0 Y45.7 F500 G00 Z2 G00 Z2 G00 X48.1 Y58.9 G01 Z-0.1 F500 G01 X35.4 Y58.9 F500 G00 Z2 G00 Z2 G00 X7.5 Y10.7 G01 Z-0.1 F500 G01 X10.0 Y8.1 F500 G00 Z2 G00 Z2 G00 X39.8 Y53.8 G01 Z-0.1 F500 G01 X39.2 Y53.3 F500 G00 Z2 G00 Z2 G00 X48.1 Y8.1 G01 Z-0.1 F500 G01 X48.1 Y51.3 F500 G00 Z2 G00 Z2 G00 X7.5 Y28.4 G01 Z-0.1 F500 G01 X7.5 Y10.7 F500 G00 Z2 G00 Z2 G00 X48.1 Y51.3 G01 Z-0.1 F500 G01 X45.6 Y53.8 F500 G00 Z2 G00 Z2 G00 X10.0 Y8.1 G01 Z-0.1 F500 G01 X48.1 Y8.1 F500 G00 Z2 G00 Z2 G00 X45.6 Y53.8 G01 Z-0.1 F500 G01 X39.8 Y53.8 F500 G00 Z2
Out[3]:
'f = open(GRB)\n#print(f.read())\nfor x in f:\n print(x)\nf.close()\n'
And Code to generate drill file ¶
In [4]:
GRB="sonde_ailis-F_Cu.gbr"
ZW="-1.2"
ZOFF="2"
GOZFAR="G00 Z"+ZOFF
GOZW="G01 Z"+ZW+" F100"
pens={}
actualpen=None
fig, ax = plt.subplots()
print(GOZFAR);
print("G00 X0 Y0")
print(GOZW)
print(GOZFAR)
print("F500")
f = open(GRB)
#print(f.read())
for line in f:
if line[:3]=="G04":
#print("comment", " : ", line )
continue
if line[:3]=="%MO":
#print("MM or Inch", " : ", line )
continue
if line[:3]=="%TF" or line[:3]=="%TA" or line[:3]=="%TO" or line[:3]=="%TD":
#print("X2 Attribute ", " : ",line)
continue
if line[:5]=="%FSLA":
xl1=int(line[6])
xl2=int(line[7])
yl1=int(line[9])
yl2=int(line[10])
#print(xl1,xl2,yl1,yl2)
continue
if line[:3]=="%AD":
#print("Aperture Definition", " : ", line )
if line[3]=="D":
i=0
for c in line[4:]:
if not c.isdigit():
break
i+=1
#print("found ",line[4:4+i])
j=i+4
for c in line[j:]:
if c==",":
break;
j+=1
#print("D=",line[4:4+i], "Forme=", line[i+4:j], "Desc =", line[j+1:-3])
pens[line[4:4+i]]=[(line[i+4:j],line[j+1:-3])]
#print("3 ",line[j+1:-3])
if line[0]=="D":
numa=line[1:-2]
#print("found D=",numa, "pen form=", pens[numa][0][0]," desc=", pens[numa][0][1])
actualpen=pens[numa][0]
if line[0]=="X":
#X157480000Y-101600000D03*
#print("Drawing",line)
i1=1
for c in line[1:]:
if c=="Y":
break
i1+=1
x=line[1:i1]
i2=i1
for c in line[i1+1:]:
if c=="D":
break
i2+=1
y=line[i1+1:i2+1]
op=line[-3]
if x[0]=="-":
x=x[1:]
xx=-int(x[:-6])
xxf=int(x[-6])*10**(-1)
else:
xx=int(x[:-6])
xxf=int(x[-6])*10**(-1)
if y[0]=="-":
y=y[1:]
yy=-int(y[:-6])
yyf=-int(y[-6])*10**(-1)
else:
yy=int(y[:-6])
yyf=int(y[-6])*10**(-1)
xx=xx+xxf
yy=yy+yyf
xx=-xx #mirror
xx+=170 #center
yy+=130 #center
#print("drawing",xx,yy,op,line)
actualxx=xx
actualyy=yy
#print("actual",actualxx,actualyy)
if op=="3": #circle
if actualpen[0]=="C" or actualpen[0]=="O" or actualpen[0]=="RoundRect" or actualpen[0]=="R":
r=0.8
circle1 = plt.Circle((xx, yy), r, color='r')
ax.add_patch(circle1)
print(GOZFAR)
gc1="G00 X"+str(round(xx+0.4,2))+" Y"+str(round(yy,2))
print(gc1)
print(GOZW)
print(GOZFAR)
if op=="2":
currentxx=xx
currentyy=yy
#print("current",currentxx,currentyy)
continue
f.close()
#print(pens)
ax.set_aspect('equal', adjustable='datalim')
ax.plot() #Causes an autoscale update.
plt.show()
'''f = open(GRB)
#print(f.read())
for x in f:
print(x)
f.close()
'''
G00 Z2 G00 X0 Y0 G01 Z-1.2 F100 G00 Z2 F500 G00 Z2 G00 X13.0 Y28.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X10.4 Y28.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X7.9 Y28.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X5.3 Y28.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X30.7 Y15.7 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X30.7 Y36.1 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X10.4 Y53.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X10.4 Y51.3 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X10.4 Y48.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y55.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y53.3 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y50.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y48.2 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y45.7 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y43.1 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y40.6 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y38.1 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y35.5 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y33.0 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y30.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y27.9 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y25.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y22.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X65.0 Y20.3 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y20.3 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y22.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y25.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y27.9 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y30.4 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y33.0 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y35.5 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y38.1 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y40.6 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y43.1 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y45.7 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y48.2 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y50.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y53.3 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X39.6 Y55.8 G01 Z-1.2 F100 G00 Z2 G00 Z2 G00 X2.8 Y5.6 G01 Z-1.2 F100 G00 Z2
Out[4]:
'f = open(GRB)\n#print(f.read())\nfor x in f:\n print(x)\nf.close()\n'
Related links : ¶
https://www.ucamco.com/files/downloads/file_en/416/the-gerber-layer-format-specification-revision-2021-02_en.pdf?1109f5f3efc7ef822119bd893d685572¶
Viewer ¶
https://gerber.ucamco.com/¶
https://www.pythoninformer.com/python-libraries/matplotlib/line-plots/¶
http://bluegyn.com/mesprogrammes/manips/gcode-cercle/¶
In [ ]: