From a60aa6a84a06ebd08072ad8e7e08d35095885f9f Mon Sep 17 00:00:00 2001 From: alexneufeld Date: Sat, 11 Sep 2021 20:04:50 -0600 Subject: [PATCH] add UNC round head square neck (carriage) bolts --- FastenersCmd.py | 1 + FsData/asmeb18.5.2def.csv | 11 + FsData/asmeb18.5.2range.csv | 11 + Icons/ASMEB18.5.2.svg | 798 ++++++++++++++++++++++++++++++++++++ ScrewMaker.py | 1 + screw_maker.py | 77 ++++ 6 files changed, 899 insertions(+) create mode 100644 FsData/asmeb18.5.2def.csv create mode 100644 FsData/asmeb18.5.2range.csv create mode 100644 Icons/ASMEB18.5.2.svg diff --git a/FastenersCmd.py b/FastenersCmd.py index e6618bf2..b461579d 100644 --- a/FastenersCmd.py +++ b/FastenersCmd.py @@ -321,6 +321,7 @@ def FSAddScrewCommand(type, help, dropGroup = None): FSAddScrewCommand("ASMEB18.3.5B", "ASME B18.3 UNC Hexagon socket set screws with cone point", "Hexagon socket") FSAddScrewCommand("ASMEB18.3.5C", "ASME B18.3 UNC Hexagon socket set screws with dog point", "Hexagon socket") FSAddScrewCommand("ASMEB18.3.5D", "ASME B18.3 UNC Hexagon socket set screws with cup point", "Hexagon socket") +FSAddScrewCommand("ASMEB18.5.2", "ASME B18.5 UNC Round head square neck bolts", "Other head") FSAddScrewCommand("ASMEB18.6.3.1A", "ASME B18.6.3 UNC slotted countersunk flat head screws", "Slotted") FSAddScrewCommand("ASMEB18.21.1.12A", "ASME B18.21.1 UN washers, narrow series", "Washer") FSAddScrewCommand("ASMEB18.21.1.12B", "ASME B18.21.1 UN washers, regular series", "Washer") diff --git a/FsData/asmeb18.5.2def.csv b/FsData/asmeb18.5.2def.csv new file mode 100644 index 00000000..19d326d7 --- /dev/null +++ b/FsData/asmeb18.5.2def.csv @@ -0,0 +1,11 @@ +"Dia","TPI","E","A","H","O","P","Q","R" +"#10",24,0.179,0.4525,0.104,0.192,0.1095,0.031,0.031 +"1/4in",20,0.2365,0.5785,0.135,0.2525,0.1405,0.031,0.031 +"5/16in",18,0.298,0.7035,0.166,0.3155,0.1715,0.031,0.031 +"3/8in",16,0.3585,0.813,0.198,0.378,0.2035,0.047,0.031 +"7/16in",14,0.4185,0.938,0.229,0.4415,0.2345,0.047,0.031 +"1/2in",13,0.4795,1.063,0.26,0.5035,0.2655,0.047,0.031 +"5/8in",11,0.6005,1.2815,0.3285,0.629,0.3285,0.078,0.062 +"3/4in",10,0.723,1.5315,0.3905,0.7545,0.3905,0.078,0.062 +"7/8in",9,0.845,1.7815,0.4485,0.88,0.4535,0.094,0.062 +"1in",8,0.966,2.0315,0.5155,1.006,0.5155,0.094,0.062 diff --git a/FsData/asmeb18.5.2range.csv b/FsData/asmeb18.5.2range.csv new file mode 100644 index 00000000..e787364e --- /dev/null +++ b/FsData/asmeb18.5.2range.csv @@ -0,0 +1,11 @@ +"Dia","Min_L","Max_L" +"#10","3/16in","8in" +"1/4in","3/8in","12in" +"5/16in","1/2in","12in" +"3/8in","1/2in","12in" +"7/16in","3/4in","12in" +"1/2in","3/4in","12in" +"5/8in","3/4in","14in" +"3/4in","1in","14in" +"7/8in","1 1/2in","14in" +"1in","1 1/2in","14in" \ No newline at end of file diff --git a/Icons/ASMEB18.5.2.svg b/Icons/ASMEB18.5.2.svg new file mode 100644 index 00000000..bae3e9b2 --- /dev/null +++ b/Icons/ASMEB18.5.2.svg @@ -0,0 +1,798 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ScrewMaker.py b/ScrewMaker.py index eca8a6a4..405fa51a 100644 --- a/ScrewMaker.py +++ b/ScrewMaker.py @@ -166,6 +166,7 @@ def FSCGetInnerThread(diam): 'ASMEB18.3.5C': ("Screw", FsData["asmeb18.3.5def"], FsData["inch_fs_length"], FsData["asmeb18.3.5range"], -1, 0), 'ASMEB18.3.5D': ("Screw", FsData["asmeb18.3.5def"], FsData["inch_fs_length"], FsData["asmeb18.3.5range"], -1, 0), 'ASMEB18.6.3.1A': ("Screw", FsData["asmeb18.6.3.1adef"], FsData["inch_fs_length"], FsData["asmeb18.6.3.1arange"], -1, 0), + 'ASMEB18.5.2': ("Screw", FsData["asmeb18.5.2def"], FsData["inch_fs_length"], FsData["asmeb18.5.2range"], -1, 0), 'ASMEB18.21.1.12A': ("Washer", FsData["asmeb18.21.1.12def"], None, None, -1, 0), 'ASMEB18.21.1.12B': ("Washer", FsData["asmeb18.21.1.12def"], None, None, -1, 0), 'ASMEB18.21.1.12C': ("Washer", FsData["asmeb18.21.1.12def"], None, None, -1, 0), diff --git a/screw_maker.py b/screw_maker.py index 33604c0d..b266eebc 100644 --- a/screw_maker.py +++ b/screw_maker.py @@ -722,6 +722,12 @@ def check_Data(self, ST_text, ND_text, NL_text): tab_range = FsData["asmeb18.3.5range"] Type_text = 'Screw' + if ST_text[:-1] == 'ASMEB18.5.5': + table = FsData["asmeb18.5.2def"] + tab_len = FsData["inch_fs_length"] + tab_range = FsData["asmeb18.5.2range"] + Type_text = 'Screw' + if ST_text == 'ASMEB18.6.3.1A': table = FsData["asmeb18.6.3.1adef"] tab_len = FsData["inch_fs_length"] @@ -922,6 +928,8 @@ def createScrew(self, ST_text, ND_text, NL_text, threadType, shapeOnly = False): table = FsData["asmeb18.3.5def"] if ST_text == 'ASMEB18.6.3.1A': table = FsData["asmeb18.6.3.1adef"] + if ST_text == 'ASMEB18.5.2': + table = FsData["asmeb18.5.2def"] if ST_text[:-1] == 'ASMEB18.21.1.12': table = FsData["asmeb18.21.1.12def"] if (ST_text == 'ScrewTap') or (ST_text == 'ScrewDie') or (ST_text == 'ThreadedRod'): @@ -997,6 +1005,10 @@ def createScrew(self, ST_text, ND_text, NL_text, threadType, shapeOnly = False): screw = self.makeIso4032(ST_text, ND_text) Type_text = 'Nut' done = True + if (ST_text == 'ASMEB18.5.2'): + screw = self.makeCarriageBolt(ST_text, ND_text, l) + Type_text = 'Screw' + done = True if ST_text == 'EN1661': screw = self.makeEN1661(ND_text) Type_text = 'Nut' @@ -3041,6 +3053,71 @@ def makeIso4026(self, SType ='ISO4026', Threadtype ='M6',l=16): return screw + def makeCarriageBolt(self, SType = 'ASMEB18.5.2', Threadtype = '1/4in', l = 25.4) : + d = self.getDia(Threadtype, False) + if SType == 'ASMEB18.5.2': + tpi,_,A,H,O,P,_,_ = FsData["asmeb18.5.2def"][Threadtype] + A,H,O,P = (25.4*x for x in (A,H,O,P)) + pitch = 25.4/tpi + if l <= 152.4: + L_t = d*2+6.35 + else: + L_t = d*2+12.7 + # lay out points for head generation + p1 = Base.Vector(0,0,H) + head_r = A/math.sqrt(2) + p2 = Base.Vector(head_r*math.sin(math.pi/8),0,H-head_r+head_r*math.cos(math.pi/8)) + p3 = Base.Vector(A/2,0,0) + p4 = Base.Vector(math.sqrt(2)/2*O,0,0) + p5 = Base.Vector(math.sqrt(2)/2*O,0,-1*P+(math.sqrt(2)/2*O-d/2)) + p6 = Base.Vector(d/2,0,-1*P) + # arcs must be converted to shapes in order to be merged with other line segments + a1 = Part.Arc(p1,p2,p3).toShape() + l2 = Part.makeLine(p3,p4) + l3 = Part.makeLine(p4,p5) + l4 = Part.makeLine(p5,p6) + wire1 = Part.Wire([a1,l2,l3,l4]) + head_shell = wire1.revolve(Base.Vector(0,0,0),Base.Vector(0,0,1),360) + if not self.rThread: + # simplified threaded section + p7 = Base.Vector(d/2,0,-1*l+d/10) + p8 = Base.Vector(d/2-d/10,0,-1*l) + p9 = Base.Vector(0,0,-1*l) + l5 = Part.makeLine(p6,p7) + l6 = Part.makeLine(p7,p8) + l7 = Part.makeLine(p8,p9) + thread_profile_wire = Part.Wire([l5,l6,l7]) + shell_thread = thread_profile_wire.revolve(Base.Vector(0,0,0),Base.Vector(0,0,1),360) + else: + # modeled threaded section + # calculate the number of thread half turns + if l <= L_t: # fully threaded fastener + residue, turns = math.modf((l-P)/pitch) + halfturns = 2*int(turns) + if residue > 0.5: + halfturns = halfturns+1 + shell_thread = self.makeShellthread(d,pitch,halfturns,False,0) + shell_thread.translate(Base.Vector(0,0,-2*pitch-P)) + else: # partially threaded fastener + residue, turns = math.modf((L_t-P)/pitch) + halfturns = 2*int(turns) + if residue > 0.5: + halfturns = halfturns+1 + shell_thread = self.makeShellthread(d,pitch,halfturns,False,0) + shell_thread.translate(Base.Vector(0,0,-2*pitch-P-(l-L_t))) + p7 = Base.Vector(d/2,0,-1*P-(l-L_t)) + helper_wire = Part.Wire([Part.makeLine(p6,p7)]) + shank = helper_wire.revolve(Base.Vector(0,0,0),Base.Vector(0,0,1),360) + shell_thread = Part.Shell(shell_thread.Faces+shank.Faces) + p_shell = Part.Shell(head_shell.Faces+shell_thread.Faces) + p_solid = Part.Solid(p_shell) + # cut 4 flats under the head + for i in range(4): + p_solid = p_solid.cut(Part.makeBox(d,A,P,Base.Vector(d/2,-1*A/2,-1*P)).rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),i*90)) + # removeSplitter is equivalent to the 'Refine' option for FreeCAD PartDesign objects + return p_solid.removeSplitter() + + def makeHextool(self,s_hex, k_hex, cir_hex): # makes a cylinder with an inner hex hole, used as cutting tool # create hexagon face