Mail Archives: geda-user/2017/01/25/16:14:46
On 01/23/2017 02:45 PM, John Griessen (john AT ecosensory DOT com) [via geda-user AT delorie DOT com] wrote:
> On 01/21/2017 11:25 AM, Bdale Garbee wrote:
>> All of the products shipped by Altus Metrum, LLC, to date have used a
>> makefile-driven gschem -> pcb workflow, and all of our designs are in
>> the hw/ tree on git.gag.com if anyone wants to learn more from studying
>> what we've done.
>>
>> Bdale
> Thanks Bdale, I'll be looking at it and most likely using it on a QFN 48 pads + center...
I made a version of that with variables similar to found in datasheets such as
These:
http://www.ti.com/lit/an/sloa122/sloa122.pdf
http://www.nxp.com/assets/documents/data/en/application-notes/AN1902.pdf
Datasheet excerpt images:
http://ecosensory.com/geda/qfn_guidelines.png
Old image before doing this script:
http://ecosensory.com/geda/qfn_solderpaste.png
New image of gerbv viewing script output
http://ecosensory.com/geda/qfn48_smallpaste.py.gerbv.png
Here is my parameterized upgrade to Bdale's python QFN generator below.
It's 7/8 done. Anyone want to tidy it up for me while I work on other things?
Thanks, John Griessen
========================qfn48_smallpaste.py========================
#!/usr/bin/python
# Copyright 2016 by Bdale Garbee, John Griessen. GPLv2
#
# Program to emit PCB footprint for UFQPN48 package used by STM32F401CE
# Pad[x y x y 1000 3 ...] x, y footprint coords are relative to footprint center.
# PCB y coordinate is going *DOWN* the page...it can fool you if expecting Y up.
EdgePadHeelSquare = 6.20 # inside edge of pads to opposite inside edge distance.
EdgePadWidth = 0.28 # Pad metal width.
NumEdgePads = 48 # Integer number of pads around edge of QFN.
EdgePadSoldermaskOpen = 0.5 # width of gap in soldermask or resist over pad
EdgePadClearance = 0.5 # width of gap between copper and pad.
EdgePadLength = 0.55 # Distance from end to end of pad.
EdgePadHeelLength = 0.45 # Length end to end of pad heel (rounded inner part).
PadSpacing = 0.50
NumCoreGridDiv = 5 # Symmetry needs an odd number grid around zero.
ViaSize = .635 # Via 25 mils diameter (.635mm dia.)
ViaDrillSize = .381 # Via drill hole 15 mils diameter (.381mm dia.)
CoreGridSize = 5.4 # Grid zone of soldermask openings and paste dots.
CenterPadSquare = 5.60 # Pad lines start EdgePadWidth/2 outside this box.
CenterPadClearance = 0.9 # width of gap between copper and pad.
SilkWidth = 0.26
CoreGridSquare = CoreGridSize/NumCoreGridDiv # Size of squares with vias, paste dots..
CenterPasteShrink = 0.16 # Paste is smaller than Pad by CenterPasteShrink * 2.
CenterPasteWidth = CoreGridSquare - (2 * CenterPasteShrink) # Paste is smaller.
EdgePasteShrink = 0.06 # Paste is smaller than Pad by EdgePasteShrink * 2.
EdgePasteWidth = EdgePadWidth - (2 * EdgePasteShrink)
EdgePadHeelStart = EdgePadHeelSquare/2 + EdgePadWidth/2
EdgePadHeelEnd = EdgePadHeelSquare/2 + EdgePadHeelLength
EdgePadStart = EdgePadHeelSquare/2 + EdgePadHeelLength + EdgePadWidth/2
EdgePadEnd = EdgePadHeelSquare/2 + EdgePadLength - EdgePadWidth/2
PadRowStartCenter = (NumEdgePads/4 - 1) * PadSpacing/2
PadGridSize = (NumCoreGridDiv -1)/2 # Odd number cols, rows around zero.
EdgePadHeelStart = EdgePadHeelSquare/2+EdgePadWidth
import sys
# we're going to use the 1/100 of a mil fundamental unit form
def mm2mils100( mm ):
return int( mm / 25.4 * 1000.0 * 100.0 + 0.5 )
print '# author: Bdale Garbee, John Griessen'
print '# email: john AT cibolo DOT com'
print '# dist-license: GPL 2'
print '# use-license: unlimited'
print '# mm2mils100(CenterPasteWidth) = ' , mm2mils100(CenterPasteWidth), CenterPasteWidth
print 'Element[0x0 "QFN36" "" "" 0 0 0 0 0 100 0x0]'
print "("
# center pad under the chip -- usually needs thermal or current vias
print ' Pad[',\
mm2mils100(0), \
mm2mils100(0), \
mm2mils100(0), \
mm2mils100(0), \
mm2mils100(CenterPadSquare), \
mm2mils100(CenterPadClearance), \
0, \
'"%i"' % (NumEdgePads+1), '"%i"' % (NumEdgePads+1), '"square,nopaste"]'
# vias in the center pad -- center is zero, (python range doesn't include final integer)
for viarow in range (-PadGridSize/2,(PadGridSize/2)+1):
for viacol in range (-PadGridSize/2,(PadGridSize/2)+1):
print ' Pin[',\
mm2mils100(2 * viacol * CoreGridSquare), \
mm2mils100(2 * viarow * CoreGridSquare), \
mm2mils100(ViaSize), \
2500, \
0, \
mm2mils100(ViaDrillSize), \
'"%i"' % (NumEdgePads+1), '"%i"' % (NumEdgePads+1), ' 0x0002]'
# break pad under chip into a grid to control the resist and paste masks
for viarow in range (-2, 3):
for viacol in range (-2, 3):
if (viarow in (-2, 0, 2)) and (viacol in (-2, 0, 2)):
# copper sub-square with resist over vias
print ' Pad[',\
mm2mils100(viacol * CoreGridSquare), \
mm2mils100(viarow * CoreGridSquare), \
mm2mils100(viacol * CoreGridSquare), \
mm2mils100(viarow * CoreGridSquare), \
mm2mils100(CoreGridSquare), \
0, \
0, \
'"%i"' % (NumEdgePads+1), '"%i"' % (NumEdgePads+1), ' "square,nopaste"]'
else:
# copper sub-square without resist
print ' Pad[',\
mm2mils100(viacol * CoreGridSquare), \
mm2mils100(viarow * CoreGridSquare), \
mm2mils100(viacol * CoreGridSquare), \
mm2mils100(viarow * CoreGridSquare), \
mm2mils100(CoreGridSquare), \
0, \
mm2mils100(CoreGridSquare+0.02), \
'"%i"' % (NumEdgePads+1), '"%i"' % (NumEdgePads+1), ' "square,nopaste"]'
# copper dot to control paste mask generation
print ' Pad[',\
mm2mils100(viacol * CoreGridSquare), \
mm2mils100(viarow * CoreGridSquare), \
mm2mils100(viacol * CoreGridSquare), \
mm2mils100(viarow * CoreGridSquare), \
mm2mils100(CenterPasteWidth), \
0, \
mm2mils100(CoreGridSquare+0.02), \
'"%i"' % (NumEdgePads+1), '"%i"' % (NumEdgePads+1), ' "square"]'
for edgepadnum in range (1, (NumEdgePads/4)+1):
# edgepads stepping horizontally
hpd = mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
mm2mils100(-EdgePadHeelStart), \
mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
mm2mils100(-EdgePadHeelEnd), \
mm2mils100(EdgePadWidth), \
mm2mils100(EdgePadClearance), \
mm2mils100(EdgePadSoldermaskOpen), \
'"%i"' % ((NumEdgePads*3/4)+1-edgepadnum), '"%i"' % ((NumEdgePads*3/4)+1-edgepadnum)
#full metal pad heels define the < NumEdgePads*3/4 row:
print ' Pad[', hpd[0], hpd[1], hpd[2], hpd[3], hpd[4], hpd[5], hpd[6], hpd[7] , hpd[8], '"nopaste"]'
#full metal pad toes define the < NumEdgePads*3/4 row:
print ' Pad[', hpd[0], mm2mils100(-EdgePadStart), hpd[2], \
mm2mils100(-EdgePadEnd), hpd[4], hpd[5], hpd[6], hpd[7] , hpd[8], '"square,nopaste"]'
#solderpaste pad heels define the < NumEdgePads*3/4 row:
print ' Pad[', hpd[0], hpd[1], hpd[2], hpd[3], \
mm2mils100(EdgePasteWidth), hpd[5], hpd[6], hpd[7] , hpd[8], '""]'
#solderpaste pad toes define the < NumEdgePads*3/4 row:
print ' Pad[', hpd[0], mm2mils100(-EdgePadStart), hpd[2], \
mm2mils100(-EdgePadEnd), mm2mils100(EdgePasteWidth), hpd[5], \
hpd[6], hpd[7] , hpd[8], '"square"]'
#full metal pad heels define the first side row:
print ' Pad[', hpd[0], mm2mils100(EdgePadHeelStart), hpd[2], \
mm2mils100(EdgePadHeelEnd), hpd[4], hpd[5], hpd[6], \
'"%i"' % edgepadnum, '"%i"' % edgepadnum, '"nopaste"]'
#full metal pad toes define the first side row:
print ' Pad[', hpd[0], mm2mils100(EdgePadStart), hpd[2], \
mm2mils100(EdgePadEnd), \
hpd[4], hpd[5], hpd[6], '"%i"' % edgepadnum, '"%i"' % edgepadnum, '"square,nopaste"]'
#solderpaste pad heels define the first side row:
print ' Pad[', hpd[0], mm2mils100(EdgePadHeelStart), hpd[2], \
mm2mils100(EdgePadHeelEnd), mm2mils100(EdgePasteWidth), hpd[5], hpd[6], \
'"%i"' % edgepadnum, '"%i"' % edgepadnum, '""]'
#solderpaste pad toes define the first side row:
print ' Pad[', hpd[0], mm2mils100(EdgePadStart), hpd[2], \
mm2mils100(EdgePadEnd), mm2mils100(EdgePasteWidth), \
hpd[5], hpd[6], '"%i"' % edgepadnum, '"%i"' % edgepadnum, '"square"]'
# edgepads running vertically
vpd = mm2mils100(EdgePadHeelStart), \
mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
mm2mils100(EdgePadHeelEnd), \
mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
mm2mils100(EdgePadWidth), \
mm2mils100(EdgePadClearance), \
mm2mils100(EdgePadSoldermaskOpen), \
'"%i"' % (NumEdgePads/2+1-edgepadnum), '"%i"' % (NumEdgePads/2+1-edgepadnum)
#full metal pad heels define the < NumEdgePads/2 side column:
print ' Pad[', vpd[0], vpd[1], vpd[2], vpd[3], vpd[4], vpd[5], vpd[6], vpd[7] , vpd[8], '"nopaste"]'
#full metal pad toes define the < NumEdgePads/2 side column:
print ' Pad[', mm2mils100(EdgePadStart), vpd[1], mm2mils100(EdgePadEnd), \
vpd[3], vpd[4], vpd[5], vpd[6], vpd[7] , vpd[8], '"square,nopaste"]'
#full metal pad heels define the highest numbered side column:
print ' Pad[',\
mm2mils100(-EdgePadHeelStart), \
mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
mm2mils100(-EdgePadHeelEnd), \
mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
vpd[4], vpd[5], vpd[6], \
'"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '"nopaste"]'
#full metal pad toes define the highest numbered side column:
print ' Pad[',\
mm2mils100(-EdgePadStart), \
mm2mils100(PadRowStartCenter - (edgepadnum - 2) * PadSpacing), \
mm2mils100(-EdgePadEnd), \
mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
vpd[4], vpd[5], vpd[6], \
'"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '"square,nopaste"]'
# silk layer mark for pin one:
print ' ElementArc[',\
mm2mils100(-PadRowStartCenter - PadSpacing), \
mm2mils100(EdgePadHeelEnd), \
' 400 400 0 360 ' , mm2mils100(SilkWidth), ' ]'
print ")"
========================qfn48_smallpaste.py========================
- Raw text -