MustafaMulla29/rp2040-bldc-motor-controller-new
73×72 mm 4-layer USB‑C PD (5/9/15/20 V) RP2040 controller PCB with protected power switching, MCT8329A sensorless BLDC three-phase MOSFET bridge, USB data/programming, onboard controls, and three motor outputs feeding a 2212 motor through rigid bullet adapters.
- Version
- 0.3.100
- License
- unset
- Stars
- 0
assembly/models.tsx
import React from "react"
import { jscad, renderToJscadPlan } from "jscad-fiber/headless"
import { dimensions as d } from "./dimensions"
import { bulletGeometry } from "./upstream-bullet"
import modeling from "@jscad/modeling"
import { adapterMouthZ, adapterShoulderZ } from "./attachments"
type V3 = [number, number, number]
export function MotorEnvelope() {
const m = d.motor
return <>
<jscad.colorize color="#353a42"><jscad.cylinder radius={m.bodyDiameter / 2} height={m.bodyHeight}
center={[0, 0, m.bodyHeight / 2]} /></jscad.colorize>
{/* Maximum shaft envelope; do not guess axial thread/shoulder transitions. */}
<jscad.colorize color="#b9bdc4"><jscad.cylinder radius={m.shaftEnvelopeDiameter / 2} height={m.shaftAboveBody}
center={[0, 0, m.bodyHeight + m.shaftAboveBody / 2]} /></jscad.colorize>
</>
}
// Adapter CAD-local mm: +Z points from the board socket towards the motor.
// Origin is the socket mouth. Placement is applied by the owning CAD component.
export function adapterContactGeometry(kind: "male" | "female") {
const female=kind==="female"
const geometry=bulletGeometry(female?"bullet_female":"bullet_male",
female?d.adapter.femaleNominalDiameter:d.adapter.maleNominalDiameter,
female?d.adapter.genericFemaleContactDepth:d.adapter.illustrativeMaleLength,
female?d.adapter.illustrativeFemaleOuterDiameter:5)
// Connector-local +Z runs from its mating face toward the solder end.
// Male points toward local -Z (PCB); female opens toward local +Z (motor).
const points=geometry.points.map(([x,y,z]) => [x, female?-y:y,
female?adapterMouthZ-z:-d.adapter.illustrativeBoardInsertion+z] as V3)
return {points, faces:geometry.faces}
}
function HollowSleeve({ start, length, outer, inner, color }:
{start:number;length:number;outer:number;inner:number;color:string}) {
return <jscad.translate offset={[0,0,start+length/2]}>
<jscad.colorize color={color}>
<jscad.subtract><jscad.cylinder radius={outer/2} height={length}/>
<jscad.cylinder radius={inner/2} height={length+0.2}/></jscad.subtract>
</jscad.colorize>
</jscad.translate>
}
export function rigidAdapterMeshes() {
const male=adapterContactGeometry("male"),female=adapterContactGeometry("female")
const {primitives:{cylinder},booleans:{subtract},transforms:{translate},geometries:{geom3}}=modeling
const geometryMesh=(geometry:any,material:string) => {
const points:V3[]=[],faces:number[][]=[]
for(const polygon of geom3.toPolygons(geometry)) {
const first=points.length;points.push(...polygon.vertices as V3[])
for(let i=1;i<polygon.vertices.length-1;i++)faces.push([first,first+i,first+i+1])
}
return {points,faces,material}
}
const place=(shape:any,centerZ:number)=>translate([0,0,centerZ],shape)
const sleeve=subtract(
cylinder({radius:d.adapter.illustrativeSleeveDiameter/2,height:d.adapter.illustrativeSleeveLength,segments:48}),
cylinder({radius:d.adapter.illustrativeFemaleOuterDiameter/2,height:d.adapter.illustrativeSleeveLength+0.2,segments:48}))
const joinLength=d.adapter.illustrativeSleeveLength-d.adapter.genericFemaleContactDepth
const join=cylinder({radius:2.1,height:joinLength,segments:48})
return [{...male,material:"gold"},{...female,material:"gold"},
geometryMesh(place(join,adapterShoulderZ+joinLength/2),"gold"),
geometryMesh(place(sleeve,adapterShoulderZ+d.adapter.illustrativeSleeveLength/2),"red_sleeve")]
}
export const motorPlan = () => renderToJscadPlan(<MotorEnvelope />)
export const motorHeatShrinkPlan = () => renderToJscadPlan(
<HollowSleeve start={adapterMouthZ} length={d.illustrativeLeads.heatShrinkLength}
outer={d.illustrativeLeads.heatShrinkDiameter} inner={4.15} color="#262a31"/>)