# ----------------------------------------------------------------------------
# -- Components
# -- parts_set library
# -- Python classes that creates useful sets of parts for FreeCAD
# ----------------------------------------------------------------------------
# -- (c) Felipe Machado
# -- Area of Electronic Technology. Rey Juan Carlos University (urjc.es)
# -- July-2018
# ----------------------------------------------------------------------------
# --- LGPL Licence
# ----------------------------------------------------------------------------
import FreeCAD
import Part
import logging
import os
import inspect
import Draft
import DraftGeomUtils
import DraftVecUtils
import math
#import copy;
#import Mesh;
# ---------------------- can be taken away after debugging
# directory this file is
filepath = os.getcwd()
import sys
# to get the components
# In FreeCAD can be added: Preferences->General->Macro->Macro path
sys.path.append(filepath)
# ---------------------- can be taken away after debugging
import kcomp # before, it was called mat_cte
import fcfun
import comps
import shp_clss
import fc_clss
import parts
from fcfun import V0, VX, VY, VZ
from fcfun import VXN, VYN, VZN
logging.basicConfig(level=logging.DEBUG,
format='%(%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class BearWashSet (fc_clss.PartsSet):
""" A set of bearings and washers, usually to make idle pulleys
Parameters:
-----------
metric : int
Metric (diameter) of the bolt that holds the set
axis_h : FreeCAD.Vector
vector along the cylinder height
pos_h : int
location of pos along axis_h (0,1,2,3)
0: pos is centered along its height
1: pos is at the base of the bearing
2: pos is at the base of the regular washer
3: pos is at the base of the large washer (this is the bottom)
axis_d : FreeCAD.Vector
vector perpendicular to the axis_h, along the radius
pos_d : int
location of pos along axis_d (0,1,2,3)
0: pos is centered at the cylinder axis
1: pos is at the bearing internal radius (defined by netric)
2: pos is at the bearing external radius
3: pos is at the large washer external radius
axis_w : FreeCAD.Vector
vector perpendicular to the axis_h and axis_d, along the radius
pos_w : int
location of pos along axis_w (0,1,2,3)
0: pos is centered at the cylinder axis
1: pos is at the bearing internal radius (defined by netric)
2: pos is at the bearing external radius
3: pos is at the large washer external radius
group : int
1: make a group
0: leave as individual componentes
pos : FreeCAD.Vector
Position of the cylinder, taking into account where the center is
Attributes:
-----------
metric : int or float (in case of M2.5) or even str for inches ?
Metric of the washer
pos_o : FreeCAD.Vector
Position of the origin of the shape
h_o : dictionary of FreeCAD.Vector
vectors from the origin to the different points along axis_h
d_o : dictionary of FreeCAD.Vector
vectors from the origin to the different points along axis_d
w_o : dictionary of FreeCAD.Vector
vectors from the origin to the different points along axis_w
h0_cen : int
d0_cen : int
w0_cen : int
indicates if pos_h = 0 (pos_d, pos_w) is at the center along
axis_h, axis_d, axis_w, or if it is at the end.
1 : at the center (symmetrical, or almost symmetrical)
0 : at the end
tot_h : float
Total height of the set: idler pulley
r_in : float
inner radius, the radius of the bearing
r_ext : float
external radius, the radius of the large washer
idler pulley without the washer for the bolt because it is between a holder,
The holder is in dots, not in the group
pos_o is at the center of symmetry: see o in the drawing
axis_h
: pos_h
...:...
: : bolt head
..........:.....:........
: Holder for the pulley group
....._________________...:
|_________________| 3 large washer
|_________| 2 regular washer
| | 1
| o | 0 bearing
|_________| -1
___|_________|___ -2 regular washer
....|_________________|.. -3 large washer
:
.........................: Holder for the pulley group
:.....: nut
:.: bolt shank
01 2 3 pos_d, pos_w
"""
# large washer (din9021) metric
lwash_m_dict = { 3: 4, 4: 6}
# regular washer (din125) has the same metric as the pulley
# bearing tipe
bear_m_dict = { 3: 603, 4: 624}
def __init__(self, metric,
axis_h, pos_h,
axis_d = None, pos_d = 0,
axis_w = None, pos_w = 0,
pos = V0,
group = 1,
name = ''):
default_name = 'bearing_idlpulley_m' + str(metric)
self.set_name (name, default_name, change = 0)
fc_clss.PartsSet.__init__(self,
axis_d = axis_d, axis_w = axis_w, axis_h = axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i): # so we keep the attributes by CylHole
setattr(self, i, values[i])
try:
# lwash_m is the size (metric) of the large washer
self.lwash_m = self.lwash_m_dict[metric]
# bear_type is the type of bearing, such as 603, 624,...
self.bear_type = self.bear_m_dict[metric]
# lwash_dict is the dictionary with the dimensions of large washer
self.lwash_dict = kcomp.D9021[self.lwash_m]
# rwash_dict is the dictionary with the dimensions of regular washer
self.rwash_dict = kcomp.D125[metric]
# bear is the dictionary with the dimensions of the bearing
self.bear_dict = kcomp.BEARING[self.bear_type]
except KeyError:
logger.error('Bearing/washer key not found: ' + str(metric))
else:
# dimensions of each element
# height, along axis_h
self.lwash_h = self.lwash_dict['t'] # height (thickness)
self.lwash_r_out = self.lwash_dict['do']/2.
self.rwash_h = self.rwash_dict['t'] # height (thickness)
self.rwash_r_out = self.rwash_dict['do']/2.
self.bear_h = self.bear_dict['t'] # height (thickness)
self.bear_r_out = self.bear_dict['do']/2.
# total height:
self.tot_h = 2 * (self.lwash_h + self.rwash_h) + self.bear_h
# inner radius of the pulley, the radius of the bearing
self.r_in = self.bear_r_out
# external radius, the radius of the large washer
self.r_ext = self.lwash_r_out
# pos_h/d/w = 0 are at the center
self.h0_cen = 1
self.d0_cen = 1
self.w0_cen = 1
# the origin (pos_o) is at the center of symmetry
# vectors from o (orig) along axis_h, to the pos_h points
# h_o is a dictionary created in Obj3D.__init__
self.h_o[0] = V0
self.h_o[1] = self.vec_h(-self.bear_h/2.)
self.h_o[2] = self.vec_h(-self.bear_h/2. - self.rwash_h)
self.h_o[3] = self.vec_h(- self.bear_h/2.
- self.rwash_h
- self.lwash_h)
self.d_o[0] = V0
if self.axis_d is not None:
self.d_o[1] = self.vec_d(-metric/2.)
self.d_o[2] = self.vec_d(-self.bear_r_out)
self.d_o[3] = self.vec_d(-self.lwash_r_out)
elif pos_d != 0:
logger.error('axis_d not defined while pos_d != 0')
self.w_o[0] = V0
if self.axis_d is not None:
self.w_o[1] = self.vec_w(-self.metric/2.)
self.w_o[2] = self.vec_w(-self.bear_r_out)
self.w_o[3] = self.vec_w(-self.lwash_r_out)
elif pos_w != 0:
logger.error('axis_w not defined while pos_w != 0')
# calculates the position of the origin, and keeps it in attribute
# pos_o
self.set_pos_o()
# creation of the bearing
bearing = fc_clss.BearingOutl(bearing_nb = self.bear_type,
axis_h = self.axis_h,
pos_h = 0,
axis_d = self.axis_d,
axis_w = self.axis_w,
pos = self.pos_o,
#pos = rwash_b.get_pos_h(1),
name = 'idlpull_bearing')
self.append_part(bearing)
# creation of the bottom regular washer
rwash_b = fc_clss.Din125Washer(metric= metric,
axis_h = self.axis_h,
pos_h = 1,
pos = bearing.get_pos_h(-1),
name = 'idlpull_rwash_bt')
self.append_part(rwash_b)
# creation of the bottom large washer
lwash_b = fc_clss.Din9021Washer(metric= self.lwash_m,
axis_h = self.axis_h,
pos_h = 1,
pos = rwash_b.get_pos_h(-1),
name = 'idlpull_lwash_bt')
self.append_part(lwash_b)
# creation of the top regular washer
rwash_t = fc_clss.Din125Washer(metric= metric,
axis_h = self.axis_h,
pos_h = -1,
pos = bearing.get_pos_h(1),
name = 'idlpull_rwash_tp')
self.append_part(rwash_t)
# creation of the top large washer
lwash_t = fc_clss.Din9021Washer(metric= self.lwash_m,
axis_h = self.axis_h,
pos_h = -1,
pos = rwash_t.get_pos_h(1),
name = 'idlpull_lwash_tp')
self.append_part(lwash_t)
if group == 1:
self.make_group ()
#doc = FreeCAD.newDocument()
#idle_pulley = BearWashSet( metric=3,
# axis_h = VZ, pos_h = 0,
# axis_d = None, pos_d = 0,
# axis_w = None, pos_w = 0,
# pos = V0,
# name = '')
class Din912BoltWashSet (fc_clss.PartsSet):
""" A din 912 bolt and a wahser set
Parameters:
-----------
metric : int (could be 2.5)
Metric (diameter) of the bolt
shank_l : float
length of the bolt, not including the head
the real length depends on shank_l_adjust
wide_washer : int
0: normal washer (default) din 125
1: wide washer din 9021
shank_l_adjust : int
0: shank length will be the size of the parameter shank_l
-1: shank length will be the size of the closest shorter or equal
to shank_l available lengths for this type of bolts
1: shank length will be the size of the closest larger or equal
to shank_l available lengths for this type of bolts
-2: shank length will be the size of the closest shorter or equal
to shank_l + washer thick available lengths for this type of bolts
available lengths for this type of bolts
2: shank length will be the size of the closest larger or equal
to shank_l + washer thick available lengths for this type of bolts
shank_out : float
0: default
distance to the end of the shank, just for positioning, it doesnt
change shank_l
I dont think it is necessary, but just in case
head_out : float
0: default
distance to the end of the head, just for positioning, it doesnt
change head_l
I dont think it is necessary, but just in case
axis_h : FreeCAD.Vector
vector along the bolt axis
axis_d : FreeCAD.Vector
vector along the radius, a direction perpendicular to axis_h
if head is hexagonal or the socket, it will point the direction of a
vertex
axis_w : FreeCAD.Vector
vector along the other radius, a direction perpendicular to axis_h
and axis_d
it is not necessary if pos_w == 0
It can be None
pos_h : int
location of pos along axis_h
0: top of the head, considering head_out,
1: position of the head not considering head_out
if head_out = 0, it will be the same as pos_h = 0
2: union of the head and the shank, beginning of the washer
3: end of the washer
4: where the screw starts, if all the shank is screwed, it will be
the same as pos_h = 2
5: end of the shank, not considering shank_out
6: end of the shank, if shank_out = 0, will be the same as pos_h = 5
6: top of the head, considering xtr_head_l, if xtr_head_l = 0
will be the same as pos_h = 0
pos_d : int
location of pos along axis_d (symmetric)
0: pos is at the central axis
1: radius of the shank
2: radius of the head
3: outer radius of the washer
pos_w : int
location of pos along axis_d (symmetric)
0: pos is at the central axis
1: radius of the shank
2: radius of the head
3: outer radius of the washer
axis_w : FreeCAD.Vector
vector perpendicular to the axis_h and axis_d, along the radius
pos_w : int
location of pos along axis_w (0,1,2,3)
0: pos is centered at the cylinder axis
1: pos is at the bearing internal radius (defined by netric)
2: pos is at the bearing external radius
3: pos is at the large washer external radius
group : int
1: make a group
0: leave as individual componentes
pos : FreeCAD.Vector
Position of the cylinder, taking into account where the center is
axis_h
:
: shank_r
:+
: :
: :
....6......... _:_:...................
shank_out+....5.........| : | : :
| : | + thread_l :
| : | : :
| : | : :
| : | : + shank_l
4 |.:.|....: :
| : | :
| : | :
.... 3 _______|_:_|_______ :
washer_thick : | :: : :: | :
:... 2 |______::_:_::______|..........:
| : | :
| ..:.. | + head_l
...1......| : : : | :
head_out+...0......|__:_:_:__|...............:.... axis_d
0 1 2 3
: : :
:....: :
: + :
: head_r :
: :
:.........:
+ washer_ro
"""
def __init__(self, metric,
shank_l,
wide_washer = 0,
shank_l_adjust = 0,
shank_out = 0,
head_out = 0,
axis_h = VZ,
axis_d = None, axis_w = None,
pos_h = 0, pos_d = 0, pos_w = 0,
pos = V0,
group = 1, # 1: make a group
name = ''):
default_name = 'd912bolt_washer_m' + str(int(metric))
self.set_name (name, default_name, change=0)
fc_clss.PartsSet.__init__(self,
axis_d = axis_d, axis_w = axis_w, axis_h = axis_h)
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i): # so we keep the attributes by CylHole
setattr(self, i, values[i])
self.bolt_dict = kcomp.D912[metric]
if wide_washer == 0:
self.washer_dict = kcomp.D125[metric]
else:
self.washer_dict = kcomp.D9021[metric]
self.washer_thick = self.washer_dict['t']
self.washer_do = self.washer_dict['do']
self.washer_ro = self.washer_do/2.
if shank_l_adjust == 0:
self.shank_l = shank_l
else:
sh_l_list = self.bolt_dict['shank_l_list']
if shank_l_adjust == -1: # smaller closest to shank_l
self.shank_l = [sh_l for sh_l in sh_l_list if sh_l<=shank_l][-1]
elif shank_l_adjust == 1: # larger closest to shank_l
self.shank_l = [sh_l for sh_l in sh_l_list if sh_l>=shank_l][0]
elif shank_l_adjust == -2: # smaller closest to shank_l, washer
self.shank_l = [sh_l for sh_l in sh_l_list
if sh_l<=shank_l+self.washer_thick][-1]
elif shank_l_adjust == 2: # larger closest to shank_l + washer_thick
self.shank_l = [sh_l for sh_l in sh_l_list
if sh_l>=shank_l+self.washer_thick][0]
else:
logger.error('wrong value for parameter shank_l_adjust')
self.shank_l = shank_l
if self.bolt_dict['thread'] > self.shank_l:
self.thread_l = self.shank_l
else:
self.thread_l = self.bolt_dict['thread']
self.shank_r = self.metric/2.
self.head_l = self.bolt_dict['head_l']
self.head_r = self.bolt_dict['head_r']
self.h0_cen = 0
self.d0_cen = 1 # symmetrical
self.w0_cen = 1 # symmetrical
self.tot_l = self.head_l + self.shank_l
# vectors from o (orig) along axis_h, to the pos_h points
# h_o is a dictionary created in Obj3D.__init__
self.h_o[0] = V0 #origin
self.h_o[1] = self.vec_h(head_out)
self.h_o[2] = self.vec_h(self.head_l)
self.h_o[3] = self.vec_h(self.head_l + self.washer_thick)
self.h_o[4] = self.vec_h(self.tot_l - self.thread_l)
self.h_o[5] = self.vec_h(self.tot_l - shank_out)
self.h_o[6] = self.vec_h(self.tot_l)
self.d_o[0] = V0
if not (self.axis_d is None or self.axis_d == V0):
# negative because is symmetric
self.d_o[1] = self.vec_d(-self.shank_r)
self.d_o[2] = self.vec_d(-self.head_r)
self.d_o[3] = self.vec_d(-self.washer_ro)
elif pos_d != 0:
logger.error('axis_d not defined while pos_d != 0')
self.w_o[0] = V0
if not (self.axis_w is None or self.axis_w == V0):
# negative because is symmetric
self.w_o[1] = self.vec_w(-self.shank_r)
self.w_o[2] = self.vec_w(-self.head_r)
self.w_o[3] = self.vec_w(-self.washer_ro)
elif pos_w != 0:
logger.error('axis_w not defined while pos_w != 0')
self.set_pos_o()
# creation of the bolt, at the origin self.pos_o:
bolt = fc_clss.Din912Bolt(metric = metric,
shank_l = self.shank_l,
shank_out = shank_out,
head_out = head_out,
axis_h = self.axis_h,
axis_d = self.axis_d,
axis_w = self.axis_w,
pos_h = 0, pos_d = 0, pos_w = 0,
pos = self.pos_o)
self.append_part(bolt)
# creation of the washer, at the origin at pos_h = 2, and at the end
# of the washer, could use an if
if wide_washer == 0:
washer = fc_clss.Din125Washer(metric = metric,
axis_h = self.axis_h,
pos_h = -1, # base of cylinder
pos = self.get_pos_h(2))
else:
washer = fc_clss.Din9021Washer(metric = metric,
axis_h = self.axis_h,
pos_h = -1, # base of cylinder
pos = self.get_pos_h(2))
self.append_part(washer)
if group == 1:
self.make_group()
#boltwash = Din912BoltWashSet(metric = 3, shank_l = 20,
# wide_washer = 0,
# shank_l_adjust = 1, # 1: take the next larger size
# shank_out = 0,
# head_out = 0,
# axis_h = VZ,
# axis_d = None, axis_w = None,
# pos_h = 0, pos_d = 0, pos_w = 0,
# pos = V0)
class Din934NutWashSet (fc_clss.PartsSet):
""" A din 934 nut and a wahser set
Parameters:
-----------
metric : int (could be 2.5)
Metric (diameter) of the bolt
wide_washer : int
0: normal washer (default) din 125
1: wide washer din 9021
axis_d_apo : int
0: default: axis_d points to the vertex
1: axis_d points to the center of a side
axis_h : FreeCAD.Vector
vector along the bolt axis
axis_d : FreeCAD.Vector
vector along the first vertex, a direction perpendicular to axis_h
it is not necessary if pos_d == 0
It can be None, but if None, axis_w has to be None
vector along the radius, a direction perpendicular to axis_h
axis_w : FreeCAD.Vector
vector along the other radius, a direction perpendicular to axis_h
and axis_d
it is not necessary if pos_w == 0
It can be None
pos_h : int
location of pos along axis_h
0: at the base of the washer
1: end of the washer, beginning of the nut
2: end of the nut
pos_d : int
location of pos along axis_d (symmetric)
0: pos is at the central axis
1: radius of the hole
2: apotheme
3: circumradius
4: radius of the washer
pos_w : int
location of pos along axis_d (symmetric)
0: pos is at the central axis
1: radius of the hole
2: apotheme
3: circumradius
4: radius of the washer
group : int
1: make a group
0: leave as individual componentes
pos : FreeCAD.Vector
Position of the cylinder, taking into account where the center is
axis_h
:
: metric/2
:+
: :
: :
2 ____:____ :
| : | : | + head_l
| : | : | :
.... 1 ____|__:_:_:__|____ :
washer_thick : | : : : | :
:... 0 |_______:_:_:_______|...........axis_d
0 1 23 4
: : :
:....: :
: + :
: head_r :
: :
:.........:
+ washer_ro
"""
def __init__(self, metric,
wide_washer = 0,
axis_d_apo = 0,
axis_h = VZ,
axis_d = None, axis_w = None,
pos_h = 0, pos_d = 0, pos_w = 0,
pos = V0,
group = 1, # 1: make a group
name = ''):
default_name = 'd934' + str(int(metric))
self.set_name (name, default_name, change=0)
fc_clss.PartsSet.__init__(self,
axis_d = axis_d, axis_w = axis_w, axis_h = axis_h)
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i): # so we keep the attributes by CylHole
setattr(self, i, values[i])
self.nut_dict = kcomp.D934[metric]
self.nut_h = self.nut_dict['l']
self.nut_ro = self.nut_dict['circ_r']
# either or the next, not exact
#self.nut_apo = self.nut_dict['a2']/2.
self.nut_apo = self.nut_ro * 0.866 # cos 30
if wide_washer == 0:
self.washer_dict = kcomp.D125[metric]
else:
self.washer_dict = kcomp.D9021[metric]
self.washer_thick = self.washer_dict['t']
self.washer_do = self.washer_dict['do']
self.washer_ro = self.washer_do/2.
self.h0_cen = 0
self.d0_cen = 1 # symmetrical
self.w0_cen = 1 # symmetrical
self.tot_h = self.nut_h + self.washer_thick
# vectors from o (orig) along axis_h, to the pos_h points
# h_o is a dictionary created in Obj3D.__init__
self.h_o[0] = V0 #origin
self.h_o[1] = self.vec_h(self.washer_thick)
self.h_o[2] = self.vec_h(self.washer_thick + self.nut_h)
self.d_o[0] = V0
if not (self.axis_d is None or self.axis_d == V0):
# negative because is symmetric
self.d_o[1] = self.vec_d(-metric/2.)
self.d_o[2] = self.vec_d(-self.nut_apo)
self.d_o[3] = self.vec_d(-self.nut_ro)
self.d_o[4] = self.vec_d(-self.washer_ro)
elif pos_d != 0:
logger.error('axis_d not defined while pos_d != 0')
self.w_o[0] = V0
if not (self.axis_w is None or self.axis_w == V0):
# negative because is symmetric
self.w_o[1] = self.vec_w(-metric/2.)
self.w_o[2] = self.vec_w(-self.nut_apo)
self.w_o[3] = self.vec_w(-self.nut_ro)
self.w_o[4] = self.vec_w(-self.washer_ro)
elif pos_w != 0:
logger.error('axis_w not defined while pos_w != 0')
self.set_pos_o()
# creation of the nut, at pos h = 1
nut = fc_clss.Din934Nut(metric = metric,
axis_d_apo = axis_d_apo,
axis_h = self.axis_h,
axis_d = self.axis_d,
axis_w = self.axis_w,
pos_h = -1, pos_d = 0, pos_w = 0,
pos = self.get_pos_h(1))
self.append_part(nut)
# creation of the washer, at the origin , and at the end
# of the washer, could use an if
if wide_washer == 0:
washer = fc_clss.Din125Washer(metric = metric,
axis_h = self.axis_h,
pos_h = -1, # base of cylinder
pos = self.pos_o)
else:
washer = fc_clss.Din9021Washer(metric = metric,
axis_h = self.axis_h,
pos_h = -1, # base of cylinder
pos = self.pos_o)
self.append_part(washer)
if group == 1:
self.make_group()
#nut_wash = Din934NutWashSet(metric =4,
# wide_washer = 0,
# axis_d_apo = 1,
# axis_h = VZ,
# axis_d = VX, axis_w = None,
# pos_h = 2, pos_d = 2, pos_w = 0,
# pos = V0,
# group = 1, # 1: make a group
# name = '')
[docs]class NemaMotorPulleySet (fc_clss.PartsSet):
"""
Set composed of a Nema Motor and a pulley
Number positions of the pulley will be after the positions of the motor
::
axis_h
:
:
_______:_______ .....11 <-> 5
|______:_:______|.....10 <-> 4
| : : |
| : : |........9 <-> 3
| : : |
___|__:_:__|___ .....8 <-> 2
|______:_:______|.....7 <-> 1
| : : |
| : : |
| : : |
|_____:o:_____|......6 <-> 0 (for the pulley)
: : :
: : :
0...56789.......axis_d, axis_w
|
01 23456 (for the pulley)
axis_h
:
:
2 ............................
| | :
| | + shaft_l
___|1|___............. :
_____|____0____|_____......:..circle_h.:
| :: 3 :: | :
| | :
| | :
| | + base_l
| | :
| | :
| | :
|__________4__________|.....:
: : :
: : :
: : :+ rear_shaft_l (optional)
:5: :
01...2..3..4.....:...........axis_d (same as axis_w)
| | | |
| | | v
| | | end of the motor
| | v
| | bolt holes
| V
| radius of the circle (cylinder)
v
radius of the shaft
axis_w
:
:
__________:__________.....
/ \....: chmf_r
| O O |
| _ |
| . . |
| ( ( ) ) |........axis_d
| . . |
| - |
| O O |
\_____________________/
: :
:.....................:
+
motor_w (same as d): Nema size in inches /10
pos_o (origin) is at pos_d=0, pos_w=0, pos_h=1
Parameters
----------
nema_size: dict
List of sizes defines in kcomps NEMA motor dimensions.
base_l: float,
Length (height) of the base
shaft_l: float,
Length (height) of the shaft, including the small cylinder (circle)
at the base
shaft_r: float,
Radius of the shaft, if not defined, it will take the dimension defined
in kcomp
circle_r: float,
Radius of the cylinder (circle) at the base of the shaft
if 0 or circle_h = 0 -> no cylinder
circle_h: float,
Height of the cylinder at the base of the shaft
if 0 or circle_r = 0 -> no cylinder
chmf_r: float,
Chamfer radius of the chamfer along the base length (height)
rear_shaft_l: float
Length of the rear shaft, 0 : no rear shaft
bolt_depth: float
Depth of the bolt holes of the motor
pulley_pitch: float/int
Distance between teeth: Typically 2mm, or 3mm
pulley_n_teeth: int
Number of teeth of the pulley
pulley_toothed_h: float
Height of the toothed part of the pulley
pulley_top_flange_h: float
Height (thickness) of the top flange, if 0, no top flange
pulley_bot_flange_h: float
Height (thickness) of the bot flange, if 0, no bottom flange
pulley_tot_h: float
Total height of the pulley
pulley_flange_d: float
Flange diameter, if 0, it will be the same as the base_d
pulley_base_d: float
Base diameter
pulley_tol: float
Tolerance for radius (it will substracted to the radius)
twice for the diameter. Or added if a shape to substract
pulley_pos_h : float
position in mm of the pulley along the shaft
* 0: it is at the base of the shaft
* -1: the top of the pulley will be aligned with the end of the shaft
axis_d: FreeCAD.Vector
Depth vector of coordinate system (perpendicular to the height)
axis_w: FreeCAD.Vector
Width vector of coordinate system
if V0: it will be calculated using the cross product: axis_h x axis_d
axis_h: FreeCAD.Vector
Height vector of coordinate system
pos_d: int
location of pos along the axis_d see drawing
* Locations coinciding with the motor
* 0: at the axis of the shaft
* 1: at the radius of the shaft
* 2: at the end of the circle(cylinder) at the base of the shaft
* 3: at the bolts
* 4: at the end of the piece
* Locations of the pulley
* 5: at the inner radius
* 7: at the external radius
* 7: at the pitch radius (outside the toothed part)
* 8: at the end of the base (not the toothed part)
* 9: at the end of the flange (V0 is no flange)
pos_w: int
location of pos along the axis_w see drawing
* Same locations of pos_d
pos_h: int
location of pos along the axis_h, see drawing
* 0: at the base of the shaft (not including the circle at the base
of the shaft)
* 1: at the end of the circle at the base of the shaft
* 2: at the end of the shaft
* 3: at the end of the bolt holes
* 4: at the bottom base
* 5: at the end of the rear shaft, if no rear shaft, it will be
the same as pos_h = 4
* 6: at the base of the pulley
* 7: at the base of the bottom flange of the pulley
* 8: at the base of the toothed part of the pulley
* 9: at the center of the toothed part of the pulley
* 10: at the end (top) of the toothed part of the pulley
* 11: at the end (top) of the pulley of the pulley
pos : FreeCAD.Vector
Position of the model
name: str
Object name
"""
def __init__ (self,
# motor parameters
nema_size = 17,
base_l = 32.,
shaft_l = 24.,
shaft_r = 0,
circle_r = 11.,
circle_h = 2.,
chmf_r = 1,
rear_shaft_l=0,
bolt_depth = 3.,
# pulley parameters
pulley_pitch = 2.,
pulley_n_teeth = 20,
pulley_toothed_h = 7.5,
pulley_top_flange_h = 1.,
pulley_bot_flange_h = 0,
pulley_tot_h = 16.,
pulley_flange_d = 15.,
pulley_base_d = 15.,
pulley_tol = 0,
pulley_pos_h = -1,
# general parameters
axis_d = VX,
axis_w = None,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 1,
pos = V0,
group = 1,
name = ''):
default_name = 'nema' + str(nema_size) + '_pulley_set'
self.set_name (name, default_name, change=0)
if (axis_w is None) or (axis_w == V0):
axis_w = axis_h.cross(axis_d)
fc_clss.PartsSet.__init__(self, axis_d = axis_d,
axis_w = axis_w, axis_h = axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
# pos_w = 0 and pos_d are at the center, pos_h
self.d0_cen = 1 #symmetric
self.w0_cen = 1 #symmetric
self.h0_cen = 0
# creation of the motor, we don't know all the relative positions
# so we create it at pos_d=pos_w = 0, pos_h = 1
nema_motor = comps.PartNemaMotor (
nema_size = nema_size,
base_l = base_l,
shaft_l = shaft_l,
shaft_r = shaft_r,
circle_r = circle_r,
circle_h = circle_h,
chmf_r = chmf_r,
rear_shaft_l= rear_shaft_l,
bolt_depth = bolt_depth,
bolt_out = 0,
cut_extra = 0,
axis_d = self.axis_d,
axis_w = self.axis_w,
axis_h = self.axis_h,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = pos)
self.append_part(nema_motor)
nema_motor.parent = self
self.shaft_r = nema_motor.shaft_r
self.circle_r = nema_motor.circle_r
self.circle_h = nema_motor.circle_h
# creation of the pulley. Locate it at pos_d,w,h = 0
gt_pulley = comps.PartGtPulley (
pitch = pulley_pitch,
n_teeth = pulley_n_teeth,
toothed_h = pulley_toothed_h,
top_flange_h = pulley_top_flange_h,
bot_flange_h = pulley_bot_flange_h,
tot_h = pulley_tot_h,
flange_d = pulley_flange_d,
base_d = pulley_base_d,
shaft_d = 2 * self.shaft_r,
tol = 0,
axis_d = self.axis_d,
axis_w = self.axis_w,
axis_h = self.axis_h,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = pos,
model_type = 1) # dimensional model
if pulley_pos_h < 0: #top of the pulley aligned with top of the shaft
# shaft_l includes the length of the circle
pulley_pos_h = shaft_l - gt_pulley.tot_h
if pulley_pos_h < 0:
pulley_pos_h = 0
self.pulley_pos_h = pulley_pos_h
elif pulley_pos_h + gt_pulley.base_h > shaft_l:
logger.warning("pulley seems to be out of the shaft")
self.append_part(gt_pulley)
gt_pulley.parent = self
# conversions of the relative points from the parts to the total set
self.d_o[0] = nema_motor.d_o[0] # V0
self.d_o[1] = nema_motor.d_o[1]
self.d_o[2] = nema_motor.d_o[2]
self.d_o[3] = nema_motor.d_o[3]
self.d_o[4] = nema_motor.d_o[4]
self.d_o[5] = gt_pulley.d_o[2]
self.d_o[6] = gt_pulley.d_o[3]
self.d_o[7] = gt_pulley.d_o[4]
self.d_o[8] = gt_pulley.d_o[5]
self.d_o[9] = gt_pulley.d_o[6]
self.w_o[0] = nema_motor.w_o[0] # V0
self.w_o[1] = nema_motor.w_o[1]
self.w_o[2] = nema_motor.w_o[2]
self.w_o[3] = nema_motor.w_o[3]
self.w_o[4] = nema_motor.w_o[4]
self.w_o[5] = gt_pulley.w_o[2]
self.w_o[6] = gt_pulley.w_o[3]
self.w_o[7] = gt_pulley.w_o[4]
self.w_o[8] = gt_pulley.w_o[5]
self.w_o[9] = gt_pulley.w_o[6]
self.h_o[0] = nema_motor.h_o[0] # V0 (origin) base of the shaft
self.h_o[1] = nema_motor.h_o[1] # end of the circle
self.h_o[2] = nema_motor.h_o[2] # end of the shaft
self.h_o[3] = nema_motor.h_o[3] # bottom end of the bolt holes
self.h_o[4] = nema_motor.h_o[4] # bottom of the base
self.h_o[5] = nema_motor.h_o[5] # rear shaft
# position of the base of the shaft (including the circle)
# + nema_motor.h_o[0] = V0 (not needed)
# relative position of the base of the pulley: V0 (not needed)
# + gt_pulley.h_o[0] = V0 -> base of the pulley
# distance from the base of the shaft (circle included) to the base
# of the pulley:
# + self.vec_h(self.pulley_pos_h):
#self.h_o[6] = ( nema_motor.h_o[0] + gt_pulley.h_o[0]
# + self.vec_h(self.pulley_pos_h))
self.h_o[6] = self.vec_h(self.pulley_pos_h)
self.h_o[7] = self.h_o[6] + gt_pulley.h_o[1]
self.h_o[8] = self.h_o[6] + gt_pulley.h_o[2]
self.h_o[9] = self.h_o[6] + gt_pulley.h_o[3]
self.h_o[10] = self.h_o[6] + gt_pulley.h_o[4]
self.h_o[11] = self.h_o[6] + gt_pulley.h_o[5]
# check if the pulley is on top of the shaft or not:
if self.h_o[11].Length > self.h_o[5].Length:
self.tot_h = self.h_o[11].Length + self.h_o[0].Length
else:
self.tot_h = self.h_o[5].Length + self.h_o[0].Length
self.set_pos_o(adjust = 1)
self.set_part_place(nema_motor)
self.set_part_place(gt_pulley, self.get_o_to_h(6))
self.place_fcos()
if group == 1:
self.make_group()
def get_nema_motor(self):
""" gets the nema motor"""
part_list = self.get_parts()
for part_i in part_list:
if isinstance(part_i, PartNemaMotor):
return part_i
def get_gt_pulley(self):
""" gets the gt2 pulley"""
part_list = self.get_parts()
for part_i in part_list:
if isinstance(part_i, comps.PartGtPulley):
return part_i
#motor_pulley = NemaMotorPulleySet(pulley_pos_h = 10,
# rear_shaft_l = 10,
# axis_d = VZ,
# axis_w = VY,
# axis_h = VX,
# pos_d = 2,
# pos_w = 0,
# pos_h = 4,
# pos = V0,
# )
class NemaMotorPulleyHolderSet (fc_clss.PartsSet):
""" Set composed of a Nema Motor with a pulley and the holder of the motor
Number positions of the pulley will be after the positions of the motor
axis_h
:
:
_______:_______ .....13 <-> 5
|______:_:______|.....12 <-> 4
| : : |
| : : |........11 <-> 3
| : : |
___|__:_:__|___ .....10 <-> 2
|______:_:______|..... <-> 1 (not used)
| : : |
| : : |
| : : |
|_____:o:_____|......9 <-> 0 (for the pulley)
: : :
: : :
0...567.......axis_d, axis_w (pos_d for motor_pulley)
|
234 (correspondence with the pulley)
2: inner radius
3: external radius
4: pitch radius
5, 6: base and flange not defined here
axis_h
:
:
6 ............................
| | :
| | + shaft_l
___|5|___............. :
_____|____1____|_____......:..circle_h.: (same as 3 in the holder)
| :: :: | :
| | :
| | :
| | + base_l
| | :
| | :
| | :
|__________7__________|.....:
: : :
: : :
: : :+ rear_shaft_l (optional)
: : :
:8:...............:...........axis_d (same as axis_w)
axis_w
:
:
__________:__________.....
/ \....: chmf_r
| O O |
| _ |
| . . |
| ( ( ) ) |........axis_d
| . . |
| - |
| O O |
\_____________________/
: :
:.....................:
+
motor_w (same as d): Nema size in inches /10
axis_d
:
________5_________ 9: belt pitch radius
|| || 8: belt outer radius
|| O 4_ O || 7: belt inner radius
|| / \ || 6: shaft_radius
|| | 3 | ||
|| \ / || 10: shaft radius
|| O 2_ O || 11: belt inner radius, 12:belt outer r; 13: pitch r
||_______1________|| .....
||_______o____::__|| ..... wall_thick.....> axis_w
0 1 2 3 (axis_w)
4567
||||
|||7: belt pitch radius
|||
||6 : belt outer radius
||
|5 : belt inner radius
|
4: shaft radius
(along axis_w is symmetrical: negative number will get
the other side)
axis_h (for the holder is pointing to the opposite direction)
:
:
:
________0_________ ....................................> axis_w
| :: : : :: | :
|__::__:_1__:__::__|.................... :
|| ||....+ motor_min_h : :
|| || 2 || || : +tot_h
|| || || || + motor_max_h :
|| || || || : :
|| || 3 || ||...................: :
||_______4________||..................................:
: : : :
: : : :
: : : :
: : : :
: :..........: :
: bolt_wall_sep :
: :
: :
:.....tot_w........:
pos_h: int
location along axis_h
0 : top of the holder
1 : top inner wall: top of motor body
2 : top end of the rail
3 : bottom end of the rail
4 : bottom end of the rail
5 : end of the motor circle (cylinder)
6 : end of the shaft
7 : base of motor body
8 : rear shaft
9 : base of pulley
10: bottom of pulley toothed part
11: middle of pulley toothed part
12: top of pulley toothed part
13: end of pulley
"""
def __init__ (self,
# motor parameters
nema_size = 17,
motor_base_l = 32.,
motor_shaft_l = 24.,
motor_shaft_r = 0,
motor_circle_r = 11.,
motor_circle_h = 2.,
motor_chmf_r = 1,
motor_rear_shaft_l=0,
motor_bolt_depth = 3.,
# pulley parameters
pulley_pitch = 2.,
pulley_n_teeth = 20,
pulley_toothed_h = 7.5,
pulley_top_flange_h = 1.,
pulley_bot_flange_h = 0,
pulley_tot_h = 16.,
pulley_flange_d = 15.,
pulley_base_d = 15.,
pulley_tol = 0,
pulley_pos_h = -1,
# holder parameters
hold_wall_thick = 4.,
hold_motorside_thick = 4.,
hold_reinf_thick = 4.,
hold_rail_min_h =10.,
hold_rail_max_h =20.,
hold_rail = 1, # if there is a rail or not at the profile side
hold_motor_xtr_space = 2., # counting on one side
hold_bolt_wall_d = 4., # Metric of the wall bolts
hold_bolt_wall_sep = 0, # optional
hold_chmf_r = 1.,
# general parameters
axis_d = VX,
axis_w = None,
axis_h = VZ,
pos_d = 0,
pos_w = 0,
pos_h = 1,
pos = V0,
group = 0,
name = ''):
default_name = 'nema_' + str(nema_size) + 'holer_motor_pulley_set'
self.set_name (name, default_name, change=0)
if (axis_w is None) or (axis_w == V0):
axis_w = axis_h.cross(axis_d)
fc_clss.PartsSet.__init__(self, axis_d = axis_d,
axis_w = axis_w, axis_h = axis_h)
# save the arguments as attributes:
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
for i in args:
if not hasattr(self,i):
setattr(self, i, values[i])
# pos_w = 0 is at the center
self.d0_cen = 0
self.w0_cen = 1 #symmetric
self.h0_cen = 0
# creation of the motor with pulley
nema_motor_pulley = NemaMotorPulleySet (
# motor parameters
nema_size = nema_size,
base_l = motor_base_l,
shaft_l = motor_shaft_l,
shaft_r = motor_shaft_r,
circle_r = motor_circle_r,
circle_h = motor_circle_h,
chmf_r = motor_chmf_r,
rear_shaft_l = motor_rear_shaft_l,
bolt_depth = motor_bolt_depth,
# pulley parameters
pulley_pitch = pulley_pitch,
pulley_n_teeth = pulley_n_teeth,
pulley_toothed_h = pulley_toothed_h,
pulley_top_flange_h = pulley_top_flange_h,
pulley_bot_flange_h = pulley_bot_flange_h,
pulley_tot_h = pulley_tot_h,
pulley_flange_d = pulley_flange_d,
pulley_base_d = pulley_base_d,
pulley_tol = pulley_tol,
pulley_pos_h = pulley_pos_h,
# general parameters
axis_d = axis_d,
axis_w = axis_w,
axis_h = axis_h,
pos_d = 0,
pos_w = 0,
pos_h = 0,
pos = pos)
self.append_part(nema_motor_pulley)
nema_motor_pulley.parent = self
nema_holder = parts.PartNemaMotorHolder(
nema_size = nema_size,
wall_thick = hold_wall_thick,
motorside_thick = hold_motorside_thick,
reinf_thick = hold_reinf_thick,
motor_min_h = hold_rail_min_h,
motor_max_h = hold_rail_max_h,
rail = hold_rail,
motor_xtr_space = hold_motor_xtr_space,
bolt_wall_d = hold_bolt_wall_d,
bolt_wall_sep = hold_bolt_wall_sep,
chmf_r = hold_chmf_r,
axis_h = axis_h.negative(), #pointing down
axis_d = axis_d,
axis_w = axis_w,
#pos_h = 0, # at the point of union with the motor
pos_h = 0, # at the point of union with the motor
pos_d = 0,
pos_w = 0,
pos = pos)
self.append_part(nema_holder)
nema_holder.parent = self
self.d_o[0] = nema_holder.d_o[0] # end that is attatched to the profile
self.d_o[1] = nema_holder.d_o[1] # inside the wall that is attached
self.d_o[2] = nema_holder.d_o[2] # bolt holes closed to the wall
self.d_o[3] = nema_holder.d_o[3] # at the motor axis
self.d_o[4] = nema_holder.d_o[4] # bolt holes away from the wall
self.d_o[5] = nema_holder.d_o[5] # the other end, opposite to the wall
# not sure which order to take
# taking first away from the wall
# axis -v shaft radius
self.d_o[6] = nema_holder.d_o[3] + nema_motor_pulley.d_o[1]
# axis -v belt inner radius
self.d_o[7] = nema_holder.d_o[3] + nema_motor_pulley.d_o[5]
# axis -v belt external radius
self.d_o[8] = nema_holder.d_o[3] + nema_motor_pulley.d_o[6]
# axis -v belt pitch radius
self.d_o[9] = nema_holder.d_o[3] + nema_motor_pulley.d_o[7]
# then, taking those closer to the the wall
# axis -v shaft radius
self.d_o[10] = nema_holder.d_o[3] + nema_motor_pulley.d_o[1].negative()
# axis -v belt inner radius
self.d_o[11] = nema_holder.d_o[3] + nema_motor_pulley.d_o[5].negative()
# axis -v belt external radius
self.d_o[12] = nema_holder.d_o[3] + nema_motor_pulley.d_o[6].negative()
# axis -v belt pitch radius
self.d_o[13] = nema_holder.d_o[3] + nema_motor_pulley.d_o[7].negative()
# symmetric
self.w_o[0] = nema_holder.w_o[0] # motor axis
self.w_o[1] = nema_holder.w_o[1] # rail (or wall bolt holes)
self.w_o[2] = nema_holder.w_o[2] # bolt holes for the motor
self.w_o[3] = nema_holder.w_o[3] # end of the piece
self.w_o[4] = nema_motor_pulley.w_o[4] # shaft radius
self.w_o[5] = nema_motor_pulley.w_o[5] # belt inner radius
self.w_o[6] = nema_motor_pulley.w_o[6] # belt outer radius
self.w_o[7] = nema_motor_pulley.w_o[7] # belt pitch radius
self.h_o[0] = nema_holder.h_o[0] # top of the holder
self.h_o[1] = nema_holder.h_o[1] # top inner wall: top of motor body
self.h_o[2] = nema_holder.h_o[2] # top end of the rail
self.h_o[3] = nema_holder.h_o[3] # bottom end of the rail
self.h_o[4] = nema_holder.h_o[4] # bottom end of the rail
# end of the motor circle (cylinder):
self.h_o[5] = self.h_o[1] + nema_motor_pulley.h_o[1]
self.h_o[6] = self.h_o[1] + nema_motor_pulley.h_o[2] #end of the shaft
self.h_o[7] = self.h_o[1] + nema_motor_pulley.h_o[4] #base of motor body
self.h_o[8] = self.h_o[1] + nema_motor_pulley.h_o[5] #rear shaft
self.h_o[9] = self.h_o[1] + nema_motor_pulley.h_o[5] #base of pulley
# bottom of pulley toothed part
self.h_o[10] = self.h_o[1] + nema_motor_pulley.h_o[8]
# middle of pulley toothed part
self.h_o[11] = self.h_o[1] + nema_motor_pulley.h_o[9]
# top of pulley toothed part
self.h_o[12] = self.h_o[1] + nema_motor_pulley.h_o[10]
# end of pulley
self.h_o[13] = self.h_o[1] + nema_motor_pulley.h_o[11]
self.set_pos_o(adjust = 1)
self.set_part_place(nema_holder)
self.set_part_place(nema_motor_pulley, self.get_o_to_h(1)
+self.get_o_to_d(3))
self.place_fcos()
if group == 1:
self.make_group()
def get_nema_holder(self):
""" gets the nema holder"""
part_list = self.get_parts()
for part_i in part_list:
if isinstance(part_i, PartNemaMotorHolder):
return part_i
def get_nema_motor_pulley(self):
""" gets the nema motor pulley set"""
part_list = self.get_parts()
for part_i in part_list:
if isinstance(part_i, NemaMotorPulleySet):
return part_i
#doc = FreeCAD.newDocument()
#nemamotorpullhold = NemaMotorPulleyHolderSet(
# hold_bolt_wall_sep = 40.,
# axis_d = VX,
# axis_w = VY,
# axis_h = VZ,
# pos_d = 1,
# pos_w = 3,
# pos_h = 1,
# pos = V0
# )