imrishabh18/nema17-motor-controller-flex
An RP2040-based USB‑C/USB‑PD controller board that powers and drives a NEMA17 stepper via a DRV8825, with current/temperature/voltage monitoring, optional AS5600 encoder, buzzer/RGB status indicators, QSPI flash, and flexible motor/encoder connections.
- Version
- 1.2.0
- License
- unset
- Stars
- 0
imports/MotorSocket6.tsx
import type { ConnectorProps } from "@tscircuit/props";
import { Fragment } from "react";
// PROVISIONAL: viewed from the top of the flat flex; contact 1 is at low Y.
// Confirm against the actual motor before applying power. Changing this map
// requires regenerating and validating routing/route-plan.json.
export const motorContactMap = {
A_PLUS: 1,
A_MINUS: 3,
B_PLUS: 4,
B_MINUS: 6,
} as const;
const positions = [1, 2, 3, 4, 5, 6] as const;
const channels = Object.entries(motorContactMap);
if (new Set(Object.values(motorContactMap)).size !== 4 ||
Object.values(motorContactMap).some(pin => pin < 1 || pin > 6)) {
throw new Error("Assign four different motor contacts in 1…6");
}
const used: number[] = Object.values(motorContactMap);
const unused = positions.filter(pin => !used.includes(pin));
const pinLabels = Object.fromEntries(positions.map(pin => [
`pin${pin}`, [channels.find(([, contact]) => contact === pin)?.[0] ?? `UNUSED_${pin}`],
]));
// Envelope proxy: 12.5 × 2.4 × 4.4 mm above PCB, 2.4 mm solder tails.
// Six openings show mating direction. Not a detailed contact/retention model.
const body = { type: "colorize", color: [0.12, 0.12, 0.14], shape: {
type: "subtract", shapes: [
{ type: "cuboid", size: [12.5, 2.4, 4.4], center: [0, 0, 2.2] },
...positions.map(pin => ({ type: "cuboid", size: [0.9, 0.9, 3.8], center: [(pin - 3.5) * 2, 0, 3] })),
],
}};
const tails = positions.map(pin => ({ type: "colorize", color: [0.7, 0.7, 0.72], shape: {
type: "cuboid", size: [0.5, 0.2, 2.4], center: [(pin - 3.5) * 2, 0, -1.2],
}}));
/** Wire-free prototype candidate: Harwin M22-7130642 PCB receptacle.
* https://www.harwin.com/products/M22-7130642
* Manufacturer drill 0.80 ±0.05 mm, 2 mm pitch, 0.5 mm square mating pins.
* Not a qualified JST-PH mate: motor shroud, engagement, pin order and retention
* need physical testing. The PCB island provides the custom adapter/backing.
*/
export function MotorSocket6(props: Omit<ConnectorProps, "pinLabels" | "footprint">) {
return <connector
{...props}
manufacturerPartNumber="M22-7130642"
supplierPartNumbers={{}}
isSmt={false}
pinLabels={pinLabels}
noConnect={unused.map(pin => `pin${pin}`)}
pcbPinLabels={Object.fromEntries(positions.map(pin => [
`pin${pin}`, channels.find(([, contact]) => contact === pin)?.[0].replace("_PLUS", "+").replace("_MINUS", "-") ?? "NC",
]))}
cadModel={{
jscad: { type: "union", shapes: [body, ...tails] },
modelOriginPosition: { x: 0, y: 0, z: 0 },
modelBounds: { min: { x: -6.25, y: -1.2, z: -2.4 }, max: { x: 6.25, y: 1.2, z: 4.4 } },
size: { x: 12.5, y: 2.4, z: 6.8 },
}}
footprint={<footprint insertionDirection="from_above">
{positions.map(pin => <Fragment key={pin}><platedhole pcbX={(pin - 3.5) * 2} pcbY={0}
portHints={[`pin${pin}`]} shape="circle" holeDiameter={0.8} outerDiameter={1.4} /></Fragment>)}
<silkscreenrect pcbX={0} pcbY={0} width={12.5} height={2.4} strokeWidth={0.1} />
<silkscreentext pcbX={-6.6} pcbY={0} text="1" fontSize={0.6} />
<courtyardrect pcbX={0} pcbY={0} width={13.5} height={3.4} />
</footprint>}
/>;
}