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>}
  />;
}