diff --git a/nhf/materials.py b/nhf/materials.py
index 09d9ad6..7477e62 100644
--- a/nhf/materials.py
+++ b/nhf/materials.py
@@ -34,7 +34,7 @@ class Role(Flag):
     STRUCTURE = auto()
     DECORATION = auto()
     ELECTRONIC = auto()
-    MOTION = auto()
+    MOTOR = auto()
 
     # Fasteners, etc.
     CONNECTION = auto()
@@ -69,7 +69,7 @@ ROLE_COLOR_MAP = {
     Role.STRUCTURE:  _color('gray', 0.4),
     Role.DECORATION: _color('lightseagreen', 0.4),
     Role.ELECTRONIC: _color('mediumorchid', 0.7),
-    Role.MOTION:     _color('thistle3', 0.7),
+    Role.MOTOR:      _color('thistle3', 0.7),
     Role.CONNECTION: _color('steelblue3', 0.8),
     Role.HANDLE:     _color('tomato4', 0.8),
 }
diff --git a/nhf/parts/fasteners.py b/nhf/parts/fasteners.py
index 1489464..492331f 100644
--- a/nhf/parts/fasteners.py
+++ b/nhf/parts/fasteners.py
@@ -35,7 +35,7 @@ class FlatHeadBolt(Item):
                 centered=(True, True, False))
         )
         rod.faces("<Z").tag("tip")
-        rod.faces(">Z").tag("root")
+        rod.tagAbsolute("root", (0, 0, self.height_thread), direction="-Z")
         rod = rod.union(head.located(Cq.Location((0, 0, self.height_thread))))
         return rod
 
diff --git a/nhf/touhou/yasaka_kanako/onbashira.py b/nhf/touhou/yasaka_kanako/onbashira.py
index 93a6223..c2eeed8 100644
--- a/nhf/touhou/yasaka_kanako/onbashira.py
+++ b/nhf/touhou/yasaka_kanako/onbashira.py
@@ -31,6 +31,15 @@ BOLT_COMMON = FlatHeadBolt(
     height_thread=30.0,
     pitch=1.0,
 )
+BOLT_LONG = FlatHeadBolt(
+    # FIXME: measure
+    mass=0.0,
+    diam_head=12.8,
+    height_head=2.8,
+    diam_thread=6.0,
+    height_thread=50.0,
+    pitch=1.0,
+)
 BOLT_BEARING = FlatHeadBolt(
     # FIXME: measure
     mass=0.0,
@@ -41,6 +50,59 @@ BOLT_BEARING = FlatHeadBolt(
     pitch=1.0,
 )
 
+@dataclass(frozen=True)
+class FlangeCoupler(Model):
+
+    diam_thread: float = 8.0
+    diam_inner: float = 10.0
+    diam_outer: float = 22.0
+    height: float = 12.0
+    height_flange: float = 2.0
+
+    diam_thread_flange: float = 4.0
+    n_hole_flange: int = 4
+    r_hole_flange: float = 8.0 # FIXME: Measure!
+
+    def generate(self) -> Cq.Workplane:
+        result = (
+            Cq.Workplane()
+            .cylinder(
+                radius=self.diam_outer/2,
+                height=self.height_flange,
+                centered=(True, True, False),
+            )
+            .faces(">Z")
+            .cylinder(
+                radius=self.diam_inner/2,
+                height=self.height - self.height_flange,
+                centered=(True, True, False),
+            )
+            .faces(">Z")
+            .hole(self.diam_thread)
+        )
+        holes = (
+            Cq.Workplane()
+            .sketch()
+            .regularPolygon(
+                self.r_hole_flange,
+                self.n_hole_flange,
+                mode="c",
+                tag="holes",
+            )
+            .vertices(tag="holes")
+            .circle(self.diam_thread_flange/2)
+            .finalize()
+            .extrude(self.height_flange)
+        )
+        result -= holes
+        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):
+            loc = Cq.Location.rot2d(i * 360 / self.n_hole_flange) * Cq.Location(self.r_hole_flange, 0)
+            result.tagAbsolute(f"holeT{i}", loc * Cq.Location(0, 0, self.height_flange), direction="+Z")
+            result.tagAbsolute(f"holeB{i}", loc, direction="-Z")
+        return result
+
 
 @dataclass(frozen=True)
 class Motor(Model):
@@ -53,13 +115,15 @@ class Motor(Model):
     power: float = 30.0 # watts
 
     diam_thread: float = 4.0
+    diam_shaft: float = 8.0
     diam_body: float = 51.0
     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
     # Distance between anchor and the body
-    dx_anchor: float = 20.2
+    dx_anchor: float = 20.2 # FIXME: Measure
     height_anchor: float = 10.4
 
     def __post_init__(self):
@@ -68,6 +132,13 @@ class Motor(Model):
         assert self.dx_anchor < self.diam_body / 2
         pass
 
+    @property
+    def dist_mount_rotor(self):
+        """
+        Distance between mount point and shaft
+        """
+        return self.height_base_shaft + self.height_ring
+
     def generate(self) -> Cq.Workplane:
         result = (
             Cq.Workplane()
@@ -83,17 +154,26 @@ 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(
-            radius=self.diam_thread/2,
+            radius=self.diam_shaft/2,
             height=self.height_shaft,
-            pnt=(0, 0, self.height_body)
+            pnt=(0, 0, self.height_body + self.height_base_shaft)
         )
+        z_anchor = self.height_body - self.height_ring
         anchor = Cq.Solid.makeCylinder(
             radius=self.diam_thread/2,
             height=self.height_anchor,
-            pnt=(0, 0, self.height_body - self.height_ring)
+            pnt=(0, 0, z_anchor)
         )
-        result = result + 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)
+        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")
         return result
 
 
@@ -172,10 +252,11 @@ class Onbashira(Model):
     # Extra bind sites for stator to prevent warping
     stator_bind_extra: int = 2
     rotor_inner_radius: float = 36.0
-    rotor_bind_bolt_diam: float = BOLT_COMMON.diam_thread
+    rotor_bind_bolt_diam: float = BOLT_BEARING.diam_thread
     rotor_bind_radius: float = 82.0
     rotor_bind_extra: int = 1
-    rotor_spacer_outer_diam: float = 15.0
+    stator_spacer_outer_diam: float = 15.0
+    rotor_spacer_outer_diam: float = 12.0
 
     handle_base_height: float = 10.0
     handle_thickness: float = 17.0
@@ -183,6 +264,8 @@ class Onbashira(Model):
     handle_height: float = 50.0
 
     motor: Motor = Motor()
+    flange_coupler: FlangeCoupler = FlangeCoupler()
+    auxiliary_thickness: float = 25.4 / 8
 
     material_side: Material = Material.WOOD_BIRCH
     material_bearing: Material = Material.PLASTIC_PLA
@@ -191,6 +274,7 @@ class Onbashira(Model):
     material_barrel: Material = Material.ACRYLIC_BLACK
     material_brace: Material = Material.PLASTIC_PLA
     material_fastener: Material = Material.STEEL_STAINLESS
+    material_auxiliary: Material = Material.WOOD_BIRCH
 
     def __post_init__(self):
         assert self.n_side >= 3
@@ -235,7 +319,15 @@ class Onbashira(Model):
         theta = math.pi / self.n_side
         dt = self.angle_joint_thickness * math.tan(theta)
         return dt * 2
-
+    @property
+    def angle_joint_bind_pos(self) -> Cq.Location:
+        """
+        Planar position of the joint bind position
+        """
+        th = math.pi / self.n_side
+        x = self.angle_joint_bind_radius * math.cos(th)
+        y = self.angle_joint_bind_radius * math.sin(th)
+        return Cq.Location.from2d(x, y)
 
     @property
     def angle_dihedral(self) -> float:
@@ -270,6 +362,153 @@ class Onbashira(Model):
             .extrude(self.side_width * 1.5)
         )
 
+    @target(name="motor-driver-shaft")
+    def motor_driver_shaft(self) -> Cq.Workplane:
+        """
+        Driver shaft which connects to each barrel to move them.
+
+        The driver shaft reaches
+        """
+        return (
+            Cq.Workplane()
+            .cylinder(
+                radius=self.barrel_diam/2,
+                height=20.0
+            )
+        )
+
+    @target(name="motor-driver-disk", kind=TargetKind.DXF)
+    def profile_motor_driver_disk(self) -> Cq.Sketch:
+        """
+        A drive disk mounts onto the motor, and extends into gun barrels to turn them.
+        """
+        return (
+            Cq.Sketch()
+            .circle(self.rotor_radius)
+            # Drill out the centre which will accomodate the motor shaft
+            .circle(self.motor.diam_shaft/2, mode="s")
+            # Drill out couplers
+            .reset()
+            .regularPolygon(
+                self.flange_coupler.r_hole_flange,
+                self.flange_coupler.n_hole_flange,
+                mode="c",
+                tag="hole",
+            )
+            .vertices(tag="hole")
+            .circle(self.flange_coupler.diam_thread_flange/2, mode="s")
+            .reset()
+            .regularPolygon(
+                self.rotation_radius,
+                self.n_side,
+                mode="c",
+                tag="const",
+            )
+            .vertices(tag="const")
+            .circle(BOLT_COMMON.diam_thread/2, mode="s")
+        )
+    def motor_driver_disk(self) -> Cq.Workplane:
+        result = (
+            Cq.Workplane()
+            .placeSketch(self.profile_motor_driver_disk())
+            .extrude(self.auxiliary_thickness)
+        )
+        n = self.flange_coupler.n_hole_flange
+        for i in range(n):
+            loc = Cq.Location.rot2d(i * 360 / n) * Cq.Location(self.flange_coupler.r_hole_flange, 0)
+            result.tagAbsolute(f"holeT{i}", loc * Cq.Location(0, 0, self.auxiliary_thickness), direction="+Z")
+            result.tagAbsolute(f"holeB{i}", loc, direction="-Z")
+        return result
+
+    @target(name="motor-mount-plate", kind=TargetKind.DXF)
+    def profile_motor_mount_plate(self) -> Cq.Sketch:
+        assert self.n_side == 6
+        bx, by = self.angle_joint_bind_pos.to2d_pos()
+        gap = 10.0
+        hole_dx = self.motor.dx_anchor
+        return (
+            Cq.Sketch()
+            .rect((bx + gap) * 2, (by + gap) * 2)
+            .reset()
+            .rect(bx * 2, by * 2, mode="c", tag="corner")
+            .vertices(tag="corner")
+            .circle(BOLT_COMMON.diam_thread/2, mode="s")
+            .reset()
+            .push([
+                (hole_dx, 0),
+                (-hole_dx, 0),
+            ])
+            .circle(self.motor.diam_thread/2, mode="s")
+        )
+    def motor_mount_plate(self) -> Cq.Workplane:
+        result = (
+            Cq.Workplane()
+            .placeSketch(self.profile_motor_mount_plate())
+            .extrude(self.auxiliary_thickness)
+        )
+        result.tagAbsolute("anchor1", (self.motor.dx_anchor, 0, 0), direction="-Z")
+        result.tagAbsolute("anchor2", (-self.motor.dx_anchor, 0, 0), direction="-Z")
+        bp = self.angle_joint_bind_pos
+        for i in range(self.n_side):
+            if i in {1, 4}:
+                continue
+            angle = i * 360 / self.n_side
+            x, y = (Cq.Location.rot2d(angle) * bp).to2d_pos()
+            result.tagAbsolute(f"holeF{i}", (x,  y, self.auxiliary_thickness), direction="+Z")
+            result.tagAbsolute(f"holeB{i}", (x,  -y, 0), direction="-Z")
+        return result
+
+    @assembly()
+    def assembly_motor(self) -> Cq.Assembly:
+        a = (
+            Cq.Assembly()
+            .addS(
+                self.motor.generate(),
+                name="motor",
+                role=Role.MOTOR,
+            )
+            .addS(
+                self.flange_coupler.generate(),
+                name="flange_coupler",
+                role=Role.CONNECTION | Role.STRUCTURE,
+                material=self.material_fastener,
+            )
+            .addS(
+                self.motor_driver_disk(),
+                name="driver_disk",
+                role=Role.CONNECTION | Role.STRUCTURE,
+                material=self.material_auxiliary,
+            )
+            .addS(
+                self.motor_mount_plate(),
+                name="mount_plate",
+                role=Role.CONNECTION | Role.STRUCTURE,
+                material=self.material_auxiliary,
+            )
+            .constrain(
+                "mount_plate?anchor1",
+                "motor?anchor1",
+                "Plane",
+            )
+            .constrain(
+                "mount_plate?anchor2",
+                "motor?anchor2",
+                "Plane",
+            )
+            .constrain(
+                "flange_coupler?top",
+                "motor?shaft",
+                "Plane"
+            )
+        )
+        for i in range(self.flange_coupler.n_hole_flange):
+            a = a.constrain(
+                f"flange_coupler?holeB{i}",
+                f"driver_disk?holeB{i}",
+                "Plane",
+            )
+        return a.solve()
+
     @target(name="stator-coupler")
     def stator_coupler(self) -> Cq.Workplane:
         """
@@ -358,13 +597,16 @@ class Onbashira(Model):
                     br * math.sin(-angle2),
                 ).tagPlane(f"holeE{i}", direction="-Z")
         return result
+    @property
+    def rotor_radius(self) -> float:
+        return self.bearing_track_radius - self.bearing_gap/2
     @target(name="bearing-rotor", kind=TargetKind.DXF)
     def profile_bearing_rotor(self) -> Cq.Sketch:
         bolt_angle = (180 / self.n_side) * 1.5
         n_binds = 1 + self.rotor_bind_extra
         return (
             Cq.Sketch()
-            .circle(self.bearing_track_radius - self.bearing_gap/2)
+            .circle(self.rotor_radius)
             .circle(self.rotor_inner_radius, mode="s")
             .reset()
             .regularPolygon(
@@ -420,7 +662,7 @@ class Onbashira(Model):
     @target(name="stator-spacer")
     def stator_spacer(self) -> Cq.Solid:
         outer = Cq.Solid.makeCylinder(
-            radius=self.rotor_spacer_outer_diam/2,
+            radius=self.stator_spacer_outer_diam/2,
             height=self.bearing_disk_gap,
         )
         inner = Cq.Solid.makeCylinder(
@@ -533,6 +775,10 @@ class Onbashira(Model):
             )
         )
         z = -self.bearing_disk_gap/2
+        da_bind_stator = 360 / self.n_side
+        da_bind_rotor = 360 / self.n_side
+        da_bind_stator_minor = 360 / self.n_side / (1 + self.stator_bind_extra)
+        da_bind_rotor_minor = 360 / self.n_side / (1 + self.rotor_bind_extra)
         for i in range(self.n_side):
             loc_barrel = Cq.Location.rot2d((i+1/2) * 360/self.n_side) * \
                 Cq.Location(self.rotation_radius, 0, -self.barrel_length/2)
@@ -543,22 +789,26 @@ class Onbashira(Model):
                 role=Role.DECORATION,
                 loc=loc_barrel,
             )
-            loc = Cq.Location.rot2d(i * 360/self.n_side) * Cq.Location(self.rotor_bind_radius, 0, z)
-            #a = a.addS(
-            #    self.stator_spacer(),
-            #    name=f"spacerRotor{i}",
-            #    material=self.material_spacer,
-            #    role=Role.STRUCTURE,
-            #    loc=loc
-            #)
-            loc = Cq.Location.rot2d((i+0.5) * 360/self.n_side) * Cq.Location(self.angle_joint_bind_radius, 0, z)
-            #a = a.addS(
-            #    self.rotor_spacer(),
-            #    name=f"spacerStator{i}",
-            #    material=self.material_spacer,
-            #    role=Role.STRUCTURE,
-            #    loc=loc
-            #)
+            for j in range(1 + self.rotor_bind_extra):
+                angle = i * da_bind_rotor + (j+0.5) * da_bind_rotor_minor
+                loc = Cq.Location.rot2d(angle) * Cq.Location(self.rotor_bind_radius, 0, z)
+                a = a.addS(
+                    self.rotor_spacer(),
+                    name=f"spacer_rotor{i}_{j}",
+                    material=self.material_spacer,
+                    role=Role.STRUCTURE,
+                    loc=loc
+                )
+            for j in range(1 + self.stator_bind_extra):
+                angle = i * da_bind_stator + (j+0.5) * da_bind_stator_minor
+                loc = Cq.Location.rot2d(angle) * Cq.Location(self.stator_bind_radius, 0, z)
+                a = a.addS(
+                    self.stator_spacer(),
+                    name=f"spacer_stator{i}_{j}",
+                    material=self.material_spacer,
+                    role=Role.STRUCTURE,
+                    loc=loc
+                )
         for i in range(self.n_bearing_balls):
             ball = self.bearing_spindle()
             loc = Cq.Location.rot2d(i * 360/self.n_bearing_balls) * Cq.Location(self.bearing_track_radius, 0, 0)
@@ -1393,6 +1643,7 @@ class Onbashira(Model):
                 material=self.material_brace,
                 role=Role.HANDLE,
             )
+            .add(self.assembly_motor(), name="motor")
             .add(self.assembly_machine(), name="machine")
         )
         # Add handle
@@ -1428,6 +1679,38 @@ class Onbashira(Model):
                 f"machine/stator2?holeB{ir}",
                 "Plane",
             )
+            if i not in {1, 4}:
+                a = a.constrain(
+                    f"motor/mount_plate?holeF{i}",
+                    f"ring2/side{(ir+2)%self.n_side}?holeStatorR",
+                    "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(
+                BOLT_COMMON.generate(),
+                name=name_bolt,
+                material=self.material_fastener,
+                role=Role.CONNECTION,
+            )
+            a = a.constrain(
+                f"chamber_back?holeF{i}",
+                f"{name_bolt}?root",
+                "Plane",
+            )
             for ih in range(len(self.angle_joint_bolt_position)):
                 a = a.constrain(
                     f"chamber/side{i}?holeFPI{ih}",
@@ -1452,19 +1735,6 @@ class Onbashira(Model):
                 #)
 
                 # Generate bolts for the chamber back
-                name_bolt =f"chamber_back{i}boltFPI{ih}"
-                a = a.addS(
-                    BOLT_COMMON.generate(),
-                    name=name_bolt,
-                    material=self.material_fastener,
-                    role=Role.CONNECTION,
-                )
-                a = a.constrain(
-                    f"chamber_back?holeF{i}",
-                    f"{name_bolt}?root",
-                    "Plane",
-                    param=0,
-                )
                 for (nl, nc, nr) in [
                         ("section1", "ring1", "section2"),
                         ("section2", "ring2", "section3"),