From 0a4ca64dadf6a90726c6730299e5edf7d1e2794f Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sun, 1 Jun 2025 22:52:13 -0700 Subject: [PATCH] Add front stabilization bracket --- nhf/touhou/yasaka_kanako/onbashira.py | 140 +++++++++++++++++++++----- 1 file changed, 115 insertions(+), 25 deletions(-) diff --git a/nhf/touhou/yasaka_kanako/onbashira.py b/nhf/touhou/yasaka_kanako/onbashira.py index b9d1ed9..d2d17aa 100644 --- a/nhf/touhou/yasaka_kanako/onbashira.py +++ b/nhf/touhou/yasaka_kanako/onbashira.py @@ -236,6 +236,10 @@ class Onbashira(Model): section1_gohei_loc: float = 30.0 gohei_bolt_diam: float = 6.0 + # Extension from each gohei bolt's centre + front_bracket_ext: float = 6.0 + front_bracket_depth: float = 15.0 + front_bracket_thickness: float = 6.0 magnet_size: float = 6.0 @@ -275,7 +279,7 @@ class Onbashira(Model): barrel_wall_thickness: float = 25.4 / 8 barrel_length: float = 25.4 * 12 # Longitudinal shift - barrel_shift: float = -20.0 + barrel_shift: float = 30.0 # Gap between the stator edge and the inner face of the barrel stator_gap: float = 3.0 @@ -291,6 +295,8 @@ class Onbashira(Model): bearing_spindle_max_diam: float = 16.0 bearing_spindle_ext: float = 5.0 bearing_spindle_gap: float = 0.2 + bearing_spindle_tail: float = 4.0 + bearing_spindle_tail_diam: float = 6.0 bearing_gasket_extend: float = 12.0 bearing_disk_thickness: float = 25.4 / 16 @@ -373,12 +379,18 @@ class Onbashira(Model): def angle_side(self) -> float: return 360 / self.n_side @property - def delta_side_width(self) -> float: + def ratio_side_width(self) -> float: """ Difference between interior and exterior side width due to side thickness """ theta = math.pi / self.n_side - dt = self.side_thickness * math.tan(theta) + return math.tan(theta) + @property + def delta_side_width(self) -> float: + """ + Difference between interior and exterior side width due to side thickness + """ + dt = self.side_thickness * self.ratio_side_width return dt * 2 @property def side_width_inner(self) -> float: @@ -701,8 +713,8 @@ class Onbashira(Model): for i in range(self.n_side): angle = (i+0.5) * th1 result.faces(">Z").moveTo( - br * math.cos(angle), - br * math.sin(angle), + br * math.cos(-angle), + br * math.sin(-angle), ).tagPlane(f"holeF{i}") result.faces(" BOLT_BEARING.diam_thread hole = Cq.Solid.makeCylinder( radius=(BOLT_BEARING.diam_thread + self.bearing_spindle_gap)/2, - height=h*4 - ).moved(0, 0, -h*2) - top = cone + cyl - hole + height=self.bearing_spindle_height + ).moved(0, 0, -self.bearing_spindle_height/2) + top = cone + cyl + tail - hole return top + top.mirror("XY") def barrel(self) -> Cq.Compound: @@ -1429,6 +1450,51 @@ class Onbashira(Model): ### Side Panels + @target(name="front-bracket") + def front_bracket(self) -> Cq.Workplane: + assert self.front_bracket_ext > self.gohei_bolt_diam / 2 + assert self.front_bracket_depth > self.gohei_bolt_diam + x0 = self.bulk_radius + y0 = x0 * math.tan(2 * math.pi / self.n_side) + s1 = self.side_width_inner + s2 = s1 - self.front_bracket_thickness * self.ratio_side_width + result = ( + Cq.Workplane() + .sketch() + .regularPolygon(s1, self.n_side) + .regularPolygon(s2, self.n_side, mode="s") + .polygon([ + (0, 0), + (x0, 0), + (x0, y0), + ], mode="i") + .finalize() + .extrude(self.front_bracket_depth) + .translate((0, 0, -self.front_bracket_depth/2)) + ) + hole_subtractor = Cq.Solid.makeCylinder( + radius=BOLT_COMMON.diam_thread/2, + height=self.bulk_radius, + dir=(1, 0, 0) + ) + result -= hole_subtractor + angle = 360 / self.n_side + result -= hole_subtractor.rotate((0,0,0), (0, 0, 1), angle) + loc_rot = Cq.Location.rot2d(angle) + r1 = self.bulk_radius - self.side_thickness + result.tagAbsolute("holeT1", (r1, 0, 0), direction="+X") + loc_ht1 = (loc_rot * Cq.Location(r1, 0, 0)).toTuple()[0] + result.tagAbsolute("holeT2", loc_ht1, direction=loc_ht1) + return result + + @target(name="front-bracket-large") + def front_bracket_large(self) -> Cq.Workplane: + """ + Optional alternative that is a bit bigger + """ + result = self.front_bracket() + return result + result.mirror("XZ") + def profile_side_panel( self, length: float, @@ -1546,8 +1612,12 @@ class Onbashira(Model): result.tagAbsolute(f"holeBSI{i}", (-px, -py, t), direction="+Z") result.tagAbsolute(f"holeBPO{i}", (+px, -py, 0), direction="-Z") result.tagAbsolute(f"holeBSO{i}", (-px, -py, 0), direction="-Z") - + # Mark the gohei attachment points + y_gohei = self.side_length1/2 - self.section1_gohei_loc + result.tagAbsolute(f"holeGoheiB", (0, y_gohei, t), direction="+Z") + result.tagAbsolute(f"holeGoheiF", (0, y_gohei, 0), direction="-Z") return result + @target(name="side-panel2", kind=TargetKind.DXF) def profile_side_panel2(self) -> Cq.Sketch: return ( @@ -1579,7 +1649,26 @@ class Onbashira(Model): role=Role.STRUCTURE | Role.DECORATION, loc=Cq.Location.rot2d(i*360/self.n_side) * Cq.Location(-r,0,0,90,0,90), ) - return a + a = a.constrain(f"side{i}", "Fixed") + for i in range(self.n_side): + i1 = (i + 1) % self.n_side + name_bracket = f"front_bracket{i}" + a = a.addS( + self.front_bracket(), + name=name_bracket, + role=Role.STRUCTURE, + ) + a = a.constrain( + f"side{i1}?holeGoheiB", + f"{name_bracket}?holeT1", + "Plane", + ) + a = a.constrain( + f"side{i}?holeGoheiB", + f"{name_bracket}?holeT2", + "Plane", + ) + return a.solve() def assembly_section(self, **kwargs) -> Cq.Assembly: a = Cq.Assembly() side = self.side_panel(**kwargs) @@ -2335,6 +2424,7 @@ class Onbashira(Model): a = a.add(self.assembly_machine(), name="machine") if has_part(parts, "electronics1"): a = a.add(self.assembly_electronics1(), name="electronics1") + a = a.constrain("electronics1/controller", "Fixed") if has_part(parts, ["electronics1", "ring3"]): a = a.constrain( f"electronics1/barL?holeBO2", @@ -2374,27 +2464,27 @@ class Onbashira(Model): ) a = a.constrain( f"{coupler_name}?holeOB", - f"ring1/side{i}?holeStatorL", + f"ring1/side{i}?holeStatorR", "Plane", ) a = a.constrain( f"{coupler_name}?holeIF", - f"machine/stator2?holeB{ir}", + f"machine/stator1?holeF{ir}", "Plane", ) - name_bolt =f"stator_outer_bolt{i}" - a = a.addS( - BOLT_LONG.generate(), - name=name_bolt, - material=self.material_fastener, - role=Role.CONNECTION, - ) - a = a.constrain( - f"{coupler_name}?holeOF", - f"{name_bolt}?root", - "Plane", - ) + #name_bolt =f"stator_outer_bolt{i}" + #a = a.addS( + # BOLT_LONG.generate(), + # name=name_bolt, + # material=self.material_fastener, + # role=Role.CONNECTION, + #) + #a = a.constrain( + # f"{coupler_name}?holeOF", + # f"{name_bolt}?root", + # "Plane", + #) name_bolt =f"chamber_back{i}boltFPI{i}" a = a.addS(