From b55dc8caa35699c320f728292a50eba432ee8c7b Mon Sep 17 00:00:00 2001
From: Leni Aniva <v@leni.sh>
Date: Fri, 30 May 2025 00:28:44 -0700
Subject: [PATCH] Calibrate measurements

---
 nhf/parts/electronics.py              | 22 +++++++--
 nhf/touhou/yasaka_kanako/onbashira.py | 70 +++++++++++++++++++--------
 2 files changed, 70 insertions(+), 22 deletions(-)

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",
             )