ShiboSoftwareDev/nema8-20mm-dual-usbc-stepper-controller

A compact 4-layer USB‑C PD/data controller board using a CH32X035 MCU and TMC2209 driver to power and control a NEMA‑8 stepper motor, with 3.3‑V regulation, USB ESD/reverse-polarity/TVS protection, current sensing, and boot control.

Version
1.0.12
License
unset
Stars
0

scripts/search-simple-route.mjs

import fs from "node:fs"
import { runAllRoutingChecks } from "@tscircuit/checks"

const traceId = process.argv[2]
const layer = process.argv[3] ?? "top"
const step = Number(process.argv[4] ?? 0.1)
if (!traceId) throw new Error("usage: node search-simple-route.mjs <trace-id> [layer] [step]")

const circuit = JSON.parse(fs.readFileSync("dist/index/circuit.json", "utf8"))
  .filter((element) => !String(element.type).endsWith("error"))
const original = circuit.find((element) => element.type === "pcb_trace" && element.pcb_trace_id === traceId)
if (!original) throw new Error(`missing ${traceId}`)

const start = original.route[0]
const end = original.route.at(-1)
const wire = (x, y, extra = {}) => ({ route_type: "wire", x, y, width: 0.15, layer, ...extra })
const makeRoute = (points) => points.map(([x, y], index) => wire(x, y,
  index === 0 ? { start_pcb_port_id: start.start_pcb_port_id }
    : index === points.length - 1 ? { end_pcb_port_id: end.end_pcb_port_id } : {}))
const score = async (route) => runAllRoutingChecks(circuit.map((element) =>
  element.type === "pcb_trace" && element.pcb_trace_id === traceId
    ? { ...element, route }
    : element))

const originalErrors = await runAllRoutingChecks(circuit)
const targetErrorCount = (errors) => errors.filter((error) => error.pcb_trace_id === traceId).length
let best = { errors: originalErrors, route: original.route }
console.log(`start\t${originalErrors.length}\t${start.x},${start.y}\t${end.x},${end.y}`)

const probeRoute = makeRoute([[start.x, start.y], [start.x, 2.8], [end.x, 2.8], [end.x, end.y]])
const probeErrors = await score(probeRoute)
console.log(`probe\t${probeErrors.length}\t${targetErrorCount(probeErrors)}`)
console.log(probeErrors.filter((error) => error.pcb_trace_id === traceId).map((error) => error.message).join("\n"))

const xs = []
const ys = []
for (let x = -9; x <= 9 + 1e-9; x += step) xs.push(Number(x.toFixed(3)))
for (let y = -9; y <= 9 + 1e-9; y += step) ys.push(Number(y.toFixed(3)))
const candidates = []
for (const x of xs) {
  candidates.push([[start.x, start.y], [x, start.y], [x, end.y], [end.x, end.y]])
}
for (const y of ys) {
  candidates.push([[start.x, start.y], [start.x, y], [end.x, y], [end.x, end.y]])
}

for (const points of candidates) {
  const route = makeRoute(points)
  let errors
  try { errors = await score(route) } catch { continue }
  if (targetErrorCount(errors) < targetErrorCount(best.errors) ||
      (targetErrorCount(errors) === targetErrorCount(best.errors) && errors.length < best.errors.length)) {
    best = { errors, route }
    console.log(`best\t${errors.length}\t${JSON.stringify(points)}`)
  }
}

console.log(`winner\t${best.errors.length}\t${JSON.stringify(best.route)}`)
console.log(best.errors.map((error) => error.message).join("\n"))