diff --git a/nhf/parts/electronics.py b/nhf/parts/electronics.py index 0a145b3..8ac43bd 100644 --- a/nhf/parts/electronics.py +++ b/nhf/parts/electronics.py @@ -83,11 +83,16 @@ class BatteryBox18650(Item): battery_dist: float = 20.18 height: float = 19.66 # space from bottom to battery begin - thickness: float = 1.66 + thickness: float = 2.28 battery_diam: float = 18.48 battery_height: float = 68.80 n_batteries: int = 3 + battery_gap: float = 2.0 + + diam_thread: float = 3.0 + hole_dy: float = 39.50 / 2 + def __post_init__(self): assert 2 * self.thickness < min(self.length, self.height) @@ -101,7 +106,7 @@ class BatteryBox18650(Item): def generate(self) -> Cq.Workplane: width = self.width_base + self.battery_dist * (self.n_batteries - 1) + self.battery_diam - return ( + result = ( Cq.Workplane('XY') .box( length=self.length, @@ -117,7 +122,7 @@ class BatteryBox18650(Item): centered=(True, True, False), combine='cut', ) - .copyWorkplane(Cq.Workplane('XY', origin=(-self.battery_height/2, 0, self.thickness + self.battery_diam/2))) + .copyWorkplane(Cq.Workplane('XY', origin=(-self.battery_height/2, 0, self.thickness + self.battery_diam/2 + self.battery_gap))) .rarray( xSpacing=1, ySpacing=self.battery_dist, @@ -133,3 +138,14 @@ class BatteryBox18650(Item): combine=True, ) ) + hole = Cq.Solid.makeCylinder( + radius=self.diam_thread/2, + height=self.thickness, + ) + result -= hole.moved(0, self.hole_dy) + result -= hole.moved(0, -self.hole_dy) + result.tagAbsolute("holeT1", (0, self.hole_dy, self.thickness), direction="+Z") + result.tagAbsolute("holeT2", (0, -self.hole_dy, self.thickness), direction="+Z") + result.tagAbsolute("holeB1", (0, self.hole_dy, 0), direction="-Z") + result.tagAbsolute("holeB2", (0, -self.hole_dy, 0), direction="-Z") + return result diff --git a/nhf/touhou/yasaka_kanako/onbashira.py b/nhf/touhou/yasaka_kanako/onbashira.py index e177959..bd8cd0a 100644 --- a/nhf/touhou/yasaka_kanako/onbashira.py +++ b/nhf/touhou/yasaka_kanako/onbashira.py @@ -2,6 +2,7 @@ from nhf.build import Model, TargetKind, target, assembly, submodel from nhf.materials import Role, Material import nhf.utils from nhf.parts.fasteners import FlatHeadBolt, HexNut, Washer +from nhf.parts.electronics import ArduinoUnoR3, BatteryBox18650 from typing import Optional, Union import math @@ -21,7 +22,7 @@ def has_part(li: Optional[list[str]], name: Union[str, list[str]]) -> bool: return True NUT_COMMON = HexNut( - # FIXME: measure + # FIXME: weigh mass=0.0, diam_thread=6.0, pitch=1.0, @@ -29,14 +30,14 @@ NUT_COMMON = HexNut( width=9.89, ) WASHER_COMMON = Washer( - # FIXME: measure + # FIXME: weigh mass=0.0, diam_thread=6.0, diam_outer=11.68, thickness=1.5, ) BOLT_COMMON = FlatHeadBolt( - # FIXME: measure + # FIXME: weigh mass=0.0, diam_head=12.8, height_head=2.8, @@ -45,7 +46,7 @@ BOLT_COMMON = FlatHeadBolt( pitch=1.0, ) BOLT_LONG = FlatHeadBolt( - # FIXME: measure + # FIXME: weigh mass=0.0, diam_head=12.8, height_head=2.8, @@ -54,7 +55,7 @@ BOLT_LONG = FlatHeadBolt( pitch=1.0, ) BOLT_BEARING = FlatHeadBolt( - # FIXME: measure + # FIXME: weigh mass=0.0, diam_head=12.8, height_head=2.8, @@ -63,14 +64,21 @@ BOLT_BEARING = FlatHeadBolt( pitch=1.0, ) +@dataclass(frozen=True) +class Display(Model): + thickness: float = 2.5 + length: float = 38.0 + width: float = 12.0 + @dataclass(frozen=True) class FlangeCoupler(Model): diam_thread: float = 8.0 - diam_inner: float = 10.0 - diam_outer: float = 22.0 + diam_inner: float = 16.0 + diam_outer: float = 32.0 height: float = 12.0 height_flange: float = 2.0 + height_hole: float = 7.0 diam_thread_flange: float = 4.0 n_hole_flange: int = 4 @@ -107,7 +115,14 @@ class FlangeCoupler(Model): .finalize() .extrude(self.height_flange) ) + hole_subtractor = Cq.Solid.makeCylinder( + radius=self.diam_thread_flange/2, + height=self.diam_inner, + pnt=(-self.diam_inner/2, 0, self.height_hole), + dir=(1, 0, 0) + ) result -= holes + result -= hole_subtractor result.tagAbsolute("top", (0, 0, self.height), direction="+Z") result.tagAbsolute("bot", (0, 0, 9), direction="-Z") for i in range(self.n_hole_flange): @@ -133,10 +148,11 @@ class Motor(Model): height_body: float = 83.5 diam_ring: float = 25.93 height_ring: float = 6.55 - height_shaft: float = 38.1 - height_base_shaft: float = 20.0 # FIXME: Measure + height_hole: float = 10.0 + height_shaft: float = 13.0 + height_base_shaft: float = 24.77 # Distance between anchor and the body - dx_anchor: float = 20.2 # FIXME: Measure + dx_anchor: float = 20.0 height_anchor: float = 10.4 def __post_init__(self): @@ -146,6 +162,12 @@ class Motor(Model): pass @property + def dist_mount_hole(self): + """ + Distance between mount point and shaft + """ + return self.height_hole + self.height_ring + @property def dist_mount_rotor(self): """ Distance between mount point and shaft @@ -167,13 +189,19 @@ class Motor(Model): centered=(True, True, False) ) ) - base_shaft = Cq.Solid.makeBox( - length=self.diam_shaft, - width=self.diam_shaft, - height=self.height_base_shaft, - ).moved(-self.diam_shaft/2, -self.diam_shaft/2, self.height_body) - shaft = Cq.Solid.makeCylinder( + hole_subtractor = Cq.Solid.makeCylinder( + radius=self.diam_thread/2, + height=self.diam_shaft, + pnt=(-self.diam_shaft/2, 0, self.height_body + self.height_hole), + dir=(1, 0, 0) + ) + base_shaft = Cq.Solid.makeCylinder( radius=self.diam_shaft/2, + height=self.height_base_shaft, + pnt=(0, 0, self.height_body), + ) + shaft = Cq.Solid.makeCylinder( + radius=self.diam_shaft/2 * 0.9, height=self.height_shaft, pnt=(0, 0, self.height_body + self.height_base_shaft) ) @@ -183,7 +211,7 @@ class Motor(Model): height=self.height_anchor, pnt=(0, 0, z_anchor) ) - result = result + base_shaft + shaft + anchor.moved(self.dx_anchor, 0, 0) + anchor.moved(-self.dx_anchor, 0, 0) + result = result + base_shaft + shaft + anchor.moved(self.dx_anchor, 0, 0) + anchor.moved(-self.dx_anchor, 0, 0) - hole_subtractor result.tagAbsolute("anchor1", (self.dx_anchor, 0, z_anchor), direction="+Z") result.tagAbsolute("anchor2", (-self.dx_anchor, 0, z_anchor), direction="+Z") result.tagAbsolute("shaft", (0, 0, self.height_body + self.height_base_shaft), direction="+Z") @@ -282,13 +310,16 @@ class Onbashira(Model): flange_coupler: FlangeCoupler = FlangeCoupler() auxiliary_thickness: float = 25.4 / 8 + battery_box: BatteryBox18650 = BatteryBox18650() + controller: ArduinoUnoR3 = ArduinoUnoR3() + # Distance between bind point and motor's mount points motor_driver_radius: float = 110.0 motor_seat_depth: float = 95.0 motor_seat_radius: float = 45.0 motor_coupler_flange_thickness: float = 10.0 motor_coupler_flange_radius: float = 8.0 - motor_coupler_height: float = 100.0 + motor_coupler_height: float = 120.0 motor_coupler_conn_dx: float = 30.0 motor_coupler_wall_thickness: float = 5.0 motor_coupler_inner_gap: float = 1.0 @@ -584,9 +615,10 @@ class Onbashira(Model): ) ) for i in range(self.flange_coupler.n_hole_flange): + j = self.flange_coupler.n_hole_flange - i - 1 a = a.constrain( f"flange_coupler?holeB{i}", - f"driver_disk?holeB{i}", + f"driver_disk?holeB{j}", "Plane", )