www.delorie.com/archives/browse.cgi   search  
Mail Archives: geda-user/2017/01/25/16:14:46

X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f
X-Recipient: geda-user AT delorie DOT com
X-Original-DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=sendgrid.net;
h=subject:to:references:from:mime-version:in-reply-to:content-type:content-transfer-encoding;
s=smtpapi; bh=1OIzZXuNsWzzVpxwzX4O+hymqqE=; b=p58tPrgOzgAFLnZv0c
y5RfLYasTN/oQZNeEowkXJppnv5nOKDZhxsf5tuZvPNC5cRKI8n0Sh7mVkEhTxHU
sgxZzxW8FNO70zuchX7a64pmhNcVfhegcmbasqQXna8eEgYktOfFb4FXSZfdzayq
CXIFvBp6BERFXsc5TP1Er48IA=
Subject: [geda-user] QFN packages script from Bdale Garbee with new features added
To: geda-user AT delorie DOT com
References: <2df480cc-5ef2-9ac6-b7ad-d17788a6b8b9 AT ecosensory DOT com>
<aec326a8-34dd-b47e-837a-b249748918b0 AT mcmahill DOT net>
<59149c35-79a3-2bd7-4b04-6d0967fcfe0a AT ecosensory DOT com>
<CA+qhd=8GfD8pbWR5gge4qzXaAXqi3t-m0Y3+UhKjz1PBpJG_yA AT mail DOT gmail DOT com>
<87d1fg1g13 DOT fsf AT rover DOT gag DOT com>
<6ab4fd42-c0fa-f820-1b65-1b7ceb9dddb9 AT ecosensory DOT com>
From: "John Griessen (john AT ecosensory DOT com) [via geda-user AT delorie DOT com]" <geda-user AT delorie DOT com>
Message-ID: <5f8ca416-a46b-631d-0e49-91b42c23d634@ecosensory.com>
Date: Wed, 25 Jan 2017 15:12:34 -0600
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101
Icedove/45.4.0
MIME-Version: 1.0
In-Reply-To: <6ab4fd42-c0fa-f820-1b65-1b7ceb9dddb9@ecosensory.com>
X-SG-EID: V53lTA/kUP1+IqXnzXuv0M/cu/N8aMtf7nxyAyKnAkvIq0C7WSKpyZDbijX8tYxPMGHIYxNClUKDdy
rk3CurHO87mC+wfS6TFuA4MbZuqMwgq/3bbcuUy7DeVkNoveqsYhBG9AGaozf2u/RmmBBTyyaag2vr
yJ9uezLb7vY/Z//kKdZiqrWycG/D5qe8P+WAp7Nde25IXp5puzVjdWCU4yWkSjPVkJg3NNR+WwZn7o
w=
Reply-To: geda-user AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: geda-user AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019