########################################
fastener - parametric threaded fasteners
########################################
Many mechanical designs will contain threaded fasteners of some kind, either in a
threaded hole or threaded screws or bolts holding two or more parts together. The
fastener sub-package provides a set of classes that
create many different types of nuts, screws and washers - as follows:
.. py:module:: fastener
.. raw:: html
.. .. image:: assets/fastener_disc.png
:alt: fastener_disc
Here is a list of the classes (and fastener types) provided:
* :class:`Nut` - the base nut class
* :class:`DomedCapNut` : din1587
* :class:`HeatSetNut` : McMaster-Carr, Hilitchi
* :class:`HexNut` : iso4033, iso4035, iso4032
* :class:`HexNutWithFlange` : din1665
* :class:`UnchamferedHexagonNut` : iso4036
* :class:`SquareNut` : din557
* :class:`Screw` - the base screw class
* :class:`ButtonHeadScrew` : iso7380_1
* :class:`ButtonHeadWithCollarScrew` : iso7380_2
* :class:`CheeseHeadScrew` : iso14580, iso7048, iso1207
* :class:`CounterSunkScrew` : iso2009, iso14582, iso14581, iso10642, iso7046
* :class:`HexHeadScrew` : iso4017, din931, iso4014
* :class:`HexHeadWithFlangeScrew` : din1662, din1665
* :class:`LowProfileScrew` : OpenBuilds
* :class:`PanHeadScrew` : asme_b_18.6.3, iso1580, iso14583
* :class:`PanHeadWithCollarScrew` : din967
* :class:`RaisedCheeseHeadScrew` : iso7045
* :class:`RaisedCounterSunkOvalHeadScrew` : iso2010, iso7047, iso14584
* :class:`SetScrew` : iso4026
* :class:`SocketHeadCapScrew` : iso4762, asme_b18.3
* :class:`Washer` - the base washer class
* :class:`PlainWasher` : iso7094, iso7093, iso7089, iso7091
* :class:`ChamferedWasher` : iso7090
* :class:`CheeseHeadWasher` : iso7092
* :class:`InternalToothLockWasher` : din6797, asme_b18.21.1
See :ref:`Extending the fastener sub-package ` for guidance on how to easily
add new sizes or entirely new types of fasteners.
The following example creates a variety of different sized fasteners:
.. code-block:: python
from build123d import *
from bd_warehouse.fastener import HexNut, SocketHeadCapScrew, SetScrew
nut = HexNut(size="M3-0.5", fastener_type="iso4032")
setscrew = SetScrew(size="M6-1", fastener_type="iso4026",length=10 * MM)
capscrew = SocketHeadCapScrew(size="#6-32", fastener_type="asme_b18.3", length=(1/2) * IN)
Both metric and imperial sized standard fasteners are directly supported by the fastener sub-package
although the majority of the fasteners currently implemented are metric.
Many of the fastener standards provide ranges for some of the dimensions - for example a minimum and
maximum head diameter. This sub-package generally uses the maximum sizes when a range is available
in-order to ensure clearance between a fastener and another part won't be compromised by a physical
part that is within specification but larger than the CAD model.
Threaded parts are complex for CAD systems to create and significantly increase the storage requirements
thus making the system slow and difficult to use. To minimize these requirements all of the fastener
classes have a ``simple`` boolean parameter that when ``True`` doesn't create actual threads at all.
Such simple parts have the same overall dimensions and such that they can be used to check for fitment
without dramatically impacting performance.
All of the fasteners default to right-handed thread but each of them provide a ``hand`` string
parameter which can either be ``"right"`` or ``"left"``.
The following sections describe each of the provided classes.
.. _nut:
***
Nut
***
As the base class of all other nut and bolt classes, all of the derived nut classes share the same
interface as follows:
.. autoclass:: fastener.Nut
:members: types, sizes, select_by_size, hole_locations, info, nut_thickness
.. :exclude-members: clearance_hole_data, clearance_hole_drill_sizes, tap_hole_data, tap_hole_drill_sizes, make_head, countersink_profile, default_countersink_profile, fastener_data
Nut Selection
=============
As there are many classes and types of nuts to select from, the Nut class provides some methods
that can help find the correct nut for your application. As a reminder, to find the subclasses of
the Nut class, use :class:`__subclasses__()`:
.. doctest::
>>> Nut.__subclasses__()
[, ...]
.. Here is a summary of the class methods:
.. .. automethod:: Nut.types
.. doctest::
>>> HexNut.types()
{'iso4033', 'iso4032', 'iso4035'}
.. .. automethod:: Nut.sizes
.. doctest::
>>> HexNut.sizes("iso4033")
['M1.6-0.35', 'M1.8-0.35', 'M2-0.4', 'M2.5-0.45', 'M3-0.45', 'M3.5-0.6', 'M4-0.7', 'M5-0.8', 'M6-1', 'M8-1.25', 'M10-1.5', 'M12-1.75', 'M14-2', 'M16-2', 'M18-2.5', 'M20-2.5', 'M22-2.5', 'M24-3', 'M27-3', 'M30-3.5', 'M33-3.5', 'M36-4', 'M39-4', 'M42-4.5', 'M45-4.5', 'M48-5', 'M52-5']
.. .. automethod:: Nut.select_by_size
.. doctest::
>>> Nut.select_by_size("M6-1")
{: ['din1587'], : ['iso4035', 'iso4032', 'iso4033'], : ['din1665'], : ['iso4036'], : ['din557']}
Derived Nut Classes
===================
The following is a list of the current nut classes derived from the base Nut class. Also listed is
the type for each of these derived classes where the type refers to a standard that defines the nut
parameters. All derived nuts inherit the same API as the base Nut class.
.. * :class:`BradTeeNut` : Hilitchi
* :class:`DomedCapNut` : din1587
* :class:`HeatSetNut` : McMaster-Carr, Hilitchi
* :class:`HexNut` : iso4033, iso4035, iso4032
* :class:`HexNutWithFlange` : din1665
* :class:`UnchamferedHexagonNut` : iso4036
* :class:`SquareNut` : din557
Detailed information about any of the nut types can be readily found on the internet from manufacture's
websites or from the standard document itself.
..
The :class:`BradTeeNut` is a compound object that uses multiple :class:`CounterSunkScrew` to fix the
nut to the base object. The size of these brads is stored in the :class:`nut_data` instance variable and
can be used to place the brads as shown in the
`brad_tee_and_heatset_nuts.py `_
example.
..
.. literalinclude:: ../examples/brad_tee_and_heatset_nuts.py
:language: python
..
.. doctest::
..
{'BradTeeNut(Hilitchi): M8-1.25': 1, 'HeatSetNut(McMaster-Carr): M4-0.7': 3, 'CounterSunkScrew(iso10642): M4-0.7x20': 3}
['M2-0.4-Short', 'M2-0.4-Standard', 'M3-0.5-Short', 'M3-0.5-Standard', 'M4-0.7-Short', 'M4-0.7-Standard', 'M5-0.8-Short', 'M5-0.8-Standard']
..
.. image:: assets/brad_tee_nut_assembly.png
Note that a :class:`HeatSetNut` can only be placed with an :class:`InsertHole`
(see the :ref:`Custom Holes ` section of more information). Also note that
the size of a :class:`HeatSetNut` includes a length component like "-Standard" or "-Short" but this depends
on the type. Use the sizes method to see the valid values.
.. doctest::
>>> HeatSetNut.sizes("McMaster-Carr")
['M2-0.4-Short', 'M2-0.4-Standard', 'M3-0.5-Short', 'M3-0.5-Standard', 'M4-0.7-Short', 'M4-0.7-Standard', 'M5-0.8-Short', 'M5-0.8-Standard']
.. _screw:
*****
Screw
*****
As the base class of all other screw and bolt classes, all of the derived screw classes share the same
interface as follows:
.. autoclass:: fastener.Screw
:exclude-members: clearance_hole_data, clearance_hole_drill_sizes, tap_hole_data, tap_hole_drill_sizes, nominal_length_range, make_head, countersink_profile, default_countersink_profile, fastener_data
The following method helps with hole creation:
.. .. automethod:: Screw.min_hole_depth
Screw Selection
===============
As there are many classes and types of screws to select from, the Screw class provides some methods that
can help find the correct screw for your application. As a reminder, to find the subclasses of the
Screw class, use :class:`__subclasses__()`:
.. doctest::
>>> Screw.__subclasses__()
[, ...]
.. Here is a summary of the class methods:
.. .. automethod:: Screw.types
.. doctest::
>>> CounterSunkScrew.types()
{'iso14582', 'iso10642', 'iso14581', 'iso2009', 'iso7046'}
.. .. automethod:: Screw.sizes
.. doctest::
>>> CounterSunkScrew.sizes("iso7046")
['M1.6-0.35', 'M2-0.4', 'M2.5-0.45', 'M3-0.5', 'M3.5-0.6', 'M4-0.7', 'M5-0.8', 'M6-1', 'M8-1.25', 'M10-1.5']
.. .. automethod:: Screw.select_by_size
* :class:`select_by_size(size:str)` : (dict{class:[type,...],} - e.g.:
.. doctest::
>>> Screw.select_by_size("M6-1")
{: ['iso7380_1'], : ['iso7380_2'], ...}
To see if a given screw type has screws in the length you are looking for, each screw class
provides a dictionary of available lengths, as follows:
.. doctest::
>>> CounterSunkScrew.nominal_length_range["iso7046"]
[3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0]
During instantiation of a screw any value of :class:`length` may be used; however, only a subset of
the above nominal_length_range is valid for any given screw size. The valid sub-range is given
with the :class:`nominal_lengths` property as follows:
.. doctest::
>>> screw = CounterSunkScrew(fastener_type="iso7046",size="M6-1",length=12 * MM)
>>> screw.nominal_lengths
[8.0, 10.0, 12.0, 14.0, 16.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0]
Derived Screw Classes
=====================
The following is a list of the current screw classes derived from the base Screw class. Also listed
is the type for each of these derived classes where the type refers to a standard that defines the
screw parameters. All derived screws inherit the same API as the base Screw class.
* :class:`ButtonHeadScrew` : iso7380_1
* :class:`ButtonHeadWithCollarScrew` : iso7380_2
* :class:`CheeseHeadScrew` : iso14580, iso7048, iso1207
* :class:`CounterSunkScrew` : iso2009, iso14582, iso14581, iso10642, iso7046
* :class:`HexHeadScrew` : iso4017, din931, iso4014
* :class:`HexHeadWithFlangeScrew` : din1662, din1665
* :class:`LowProfileScrew` : OpenBuilds
* :class:`PanHeadScrew` : asme_b_18.6.3, iso1580, iso14583
* :class:`PanHeadWithCollarScrew` : din967
* :class:`RaisedCheeseHeadScrew` : iso7045
* :class:`RaisedCounterSunkOvalHeadScrew` : iso2010, iso7047, iso14584
* :class:`SetScrew` : iso4026
* :class:`SocketHeadCapScrew` : iso4762, asme_b18.3
Detailed information about any of the screw types can be readily found on the internet from manufacture's
websites or from the standard document itself.
.. _washer:
******
Washer
******
As the base class of all other washer and bolt classes, all of the derived washer classes share
the same interface as follows:
.. autoclass:: Washer
:members: types, sizes
.. :exclude-members: clearance_hole_data, clearance_hole_drill_sizes, tap_hole_data, tap_hole_drill_sizes, nominal_length_range, make_head, countersink_profile, default_countersink_profile, default_washer_profile, fastener_data
Washer Selection
================
As there are many classes and types of washers to select from, the Washer class provides some methods
that can help find the correct washer for your application. As a reminder, to find the subclasses of
the Washer class, use :class:`__subclasses__()`:
.. doctest::
>>> Washer.__subclasses__()
[, , ]
Here is a summary of the class methods:
.. .. automethod:: Washer.types
.. doctest::
>>> PlainWasher.types()
{'iso7091', 'iso7089', 'iso7093', 'iso7094'}
.. .. automethod:: Washer.sizes
.. doctest::
>>> PlainWasher.sizes("iso7091")
['M1.6', 'M1.7', 'M2', 'M2.3', 'M2.5', 'M2.6', 'M3', 'M3.5', 'M4', 'M5', 'M6', 'M7', 'M8', 'M10', 'M12', 'M14', 'M16', 'M18', 'M20', 'M22', 'M24', 'M26', 'M27', 'M28', 'M30', 'M32', 'M33', 'M35', 'M36']
.. .. automethod:: Washer.select_by_size
.. doctest::
>>> Washer.select_by_size("M6")
{: ['iso7094', 'iso7093', 'iso7089', 'iso7091'], : ['iso7090'], : ['iso7092']}
Derived Washer Classes
======================
The following is a list of the current washer classes derived from the base Washer class. Also listed
is the type for each of these derived classes where the type refers to a standard that defines the washer
parameters. All derived washers inherit the same API as the base Washer class.
* :class:`PlainWasher` : iso7094, iso7093, iso7089, iso7091
* :class:`ChamferedWasher` : iso7090
* :class:`CheeseHeadWasher` : iso7092
* :class:`InternalToothLockWasher` : din6797, asme_b18.21.1
Detailed information about any of the washer types can be readily found on the internet from manufacture's
websites or from the standard document itself.
.. _custom holes:
************
Custom Holes
************
When designing parts with build123d a common operation is to place holes appropriate to a specific fastener
into the part. This operation is optimized with bd_warehouse by the following four custom hole objects:
.. autoclass:: fastener.ClearanceHole
.. autoclass:: fastener.InsertHole
.. autoclass:: fastener.TapHole
.. autoclass:: fastener.ThreadedHole
The APIs for these holes are very similar. The ``fit`` parameter is used
for clearance hole dimensions and to calculate the gap around the head of a countersunk screw.
The ``material`` parameter controls the size of the tap hole as they differ as a function of the
material the part is made of. For clearance and tap holes, ``depth`` values of ``None`` are treated
as thru holes. The threaded hole method requires that ``depth`` be specified as a consequence of
how the thread is constructed.
These methods use data provided by a fastener instance (either a :class:`Nut` or a :class:`Screw`) to both create
the appropriate hole (possibly countersunk) in your part as well as add the location of the holes to
the fastener's ``hole_locations`` attribute to ease the creation of assemblies with both the
base parts and fasteners.
For example, let's build the parametric bearing pillow block:
.. literalinclude:: ../examples/pillow_block.py
Which results in:
.. image:: assets/pillow_block.png
:alt: pillow_block
Note the following benefits:
* screw and bearing dimensions aren't required,
* the screw is created during instantiation of the :class:`SocketHeadCapScrew` class
without the user knowing any of its dimensions,
* the :class:`ClearanceHole` object only requires the fastener thus the user need
not provide hole dimensions.
* the assembly contains both the part and copies of the fastener thus avoiding the
overhead of many fasteners in the design.
Not only were the appropriate holes for the bearing and M2-0.4 screws created but an assembly was created to
store all of the parts in this project all without having to research the dimensions of the parts.
Note: In this example the ``simple=False`` parameter creates accurate threads on each of the
screws which significantly increases the complexity of the model. The default of simple is True
which models the thread as a simple cylinder which is sufficient for most applications without
the performance cost of accurate threads.
The data used in the creation of these holes is available via three instance methods:
.. doctest::
>>> screw = CounterSunkScrew(fastener_type="iso7046", size="M6-1", length=10)
>>> screw.clearance_hole_diameters
{'Close': 6.4, 'Normal': 6.6, 'Loose': 7.0}
>>> screw.clearance_drill_sizes
{'Close': '6.4', 'Normal': '6.6', 'Loose': '7'}
>>> screw.tap_hole_diameters
{'Soft': 5.0, 'Hard': 5.4}
>>> screw.tap_drill_sizes
{'Soft': '5', 'Hard': '5.4'}
Note that with imperial sized holes (e.g. 7/16), the drill sizes could be a fractional size (e.g. 25/64)
or a numbered or lettered size (e.g. U).
Captive Nuts
============
The :class:`ClearanceHole` method has a ``captive_nut`` parameter that
when used with a hex or square nut will create a hole that captures the nut such that it
can't spin. Here is an example:
.. literalinclude:: ../examples/captive_nuts.py
Which results in:
.. image:: assets/captive_nuts.png
:alt: captive_nuts
The space around the nuts is controlled by the ``fit`` parameter.
.. _extending:
**********************************
Extending the fastener sub-package
**********************************
The fastener sub-package has been designed to be extended in the following two ways:
Alternate Sizes
===============
As mentioned previously, the data used to guide the creation of fastener objects is derived
from :class:`.csv` files found in the same place as the source code. One can add to the set of standard
sized fasteners by inserting appropriate data into the tables. There is a table for each fastener
class; an example of the 'socket_head_cap_parameters.csv' is below:
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| Size | iso4762:dk | iso4762:k | ... | asme_b18.3:dk | asme_b18.3:k | | asme_b18.3:s |
+============+============+===========+=====+===============+==============+=====+==============+
| M2-0.4 | 3.98 | 2 | | | | | |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| M2.5-0.45 | 4.68 | 2.5 | | 0.096 | 0.06 | | 0.05 |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| M3-0.5 | 5.68 | 3 | | 0.118 | 0.073 | | 1/16 |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| ... | | | | 0.118 | 0.073 | | 1/16 |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| #0-80 | | | | 0.14 | 0.086 | | 5/64 |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| #1-64 | | | | | | | |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| #1-72 | | | | | | | |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
| #2-56 | | | | | | | |
+------------+------------+-----------+-----+---------------+--------------+-----+--------------+
The first row must contain a 'Size' and a set of '{fastener_type}:{parameter}'
values. The parameters are taken from the ISO standards where 'k' represents the
head height of a screw head, 'dk' is represents the head diameter, etc. Refer to
the appropriate document for a complete description. The fastener 'Size' field
has the format 'M{thread major diameter}-{thread pitch}' for metric fasteners or
either '#{guage}-{TPI}' or '{fractional major diameter}-{TPI}' for imperial
fasteners (TPI refers to Threads Per Inch). All the data for imperial fasteners
must be entered as inch dimensions while metric data is in millimeters.
There is also a 'nominal_screw_lengths.csv' file that contains a list of all the
lengths supported by the standard, as follows:
+------------+------+--------------------------+
| Screw_Type | Unit | Nominal_Sizes |
+============+======+==========================+
| din931 | mm | 30,35,40,45,50,55,60,... |
+------------+------+--------------------------+
| ... | | |
+------------+------+--------------------------+
The 'short' and 'long' values from the first table (not shown) control the
minimum and maximum values in the nominal length ranges for each screw.
New Fastener Types
==================
The base/derived class structure was designed to allow the creation of new
fastener types/classes. For new fastener classes a 2D drawing of one half of the
fastener profile is required. If the fastener has a non circular plan (e.g. a
hex or a square) a 2D drawing of the plan is required. If the fastener contains
a flange and a plan, a 2D profile of the flange is required. If these profiles
or plans are present, the base class will use them to build the fastener. The
Abstract Base Class technology ensures derived classes can't be created with
missing components.
*********
Reference
*********
.. autoclass:: DomedCapNut
.. autoclass:: HeatSetNut
.. autoclass:: HexNut
.. autoclass:: HexNutWithFlange
.. autoclass:: UnchamferedHexagonNut
.. autoclass:: SquareNut
.. autoclass:: ButtonHeadScrew
.. autoclass:: ButtonHeadWithCollarScrew
.. autoclass:: CheeseHeadScrew
.. autoclass:: CounterSunkScrew
.. autoclass:: HexHeadScrew
.. autoclass:: HexHeadWithFlangeScrew
.. autoclass:: PanHeadScrew
.. autoclass:: PanHeadWithCollarScrew
.. autoclass:: RaisedCheeseHeadScrew
.. autoclass:: RaisedCounterSunkOvalHeadScrew
.. autoclass:: SetScrew
.. autoclass:: SocketHeadCapScrew
.. autoclass:: PlainWasher
.. autoclass:: ChamferedWasher
.. autoclass:: CheeseHeadWasher