ShiboSoftwareDev/nema8-20mm-dual-usbc-stepper-controller
A compact 4-layer USB‑C PD stepper-motor controller PCB using a CH32X035 MCU, TMC2209 driver, dual USB‑C ports, power protection/regulation, ESD/TVS diodes, current-sense resistors, and NEMA‑8 motor connector.
- Version
- 1.0.13
- License
- unset
- Stars
- 0
scripts/search-via-positions.mjs
import fs from "node:fs"
import { runAllRoutingChecks } from "@tscircuit/checks"
const raw = JSON.parse(fs.readFileSync("dist/index/circuit.json", "utf8"))
const clean = raw.filter((element) => !String(element.type).endsWith("error"))
const samePoint = (point, x, y) => Math.hypot(point.x - x, point.y - y) < 1e-5
const moveVia = (circuit, viaId, x, y) => {
const via = circuit.find((element) => element.type === "pcb_via" && element.pcb_via_id === viaId)
if (!via) throw new Error(`Missing ${viaId}`)
return circuit.map((element) => {
if (element.type === "pcb_via" && element.pcb_via_id === viaId) return { ...element, x, y }
if (element.type !== "pcb_trace" || element.pcb_trace_id !== via.pcb_trace_id) return element
return {
...element,
route: element.route.map((point) => samePoint(point, via.x, via.y) ? { ...point, x, y } : point),
}
})
}
let base = clean
if (process.env.SKIP_BASE_MOVES !== "1") {
for (const [viaId, x, y] of [
["pcb_via_53", 0.4072, 4.6301],
["pcb_via_75", -2.7599, 1.7044],
["pcb_via_89", -2.3924, -2.575],
]) base = moveVia(base, viaId, x, y)
}
const vmEdgeTraceId = "source_trace_3__source_trace_4__source_trace_5__source_trace_6__source_trace_7__source_trace_8__source_trace_9__source_trace_10__source_trace_11_mst6_0"
base = base.map((element) => element.type === "pcb_trace" && element.pcb_trace_id === vmEdgeTraceId
? { ...element, route: element.route.map((point) => point.x > 9.65 ? { ...point, x: 9.65 } : point) }
: element)
const hardErrors = async (circuit) => (await runAllRoutingChecks(circuit))
.filter((error) => error.type !== "pcb_trace_warning")
const targets = process.argv.slice(2)
const searchTargets = targets.length ? targets : ["pcb_via_41", "pcb_via_48", "pcb_via_55", "pcb_via_57"]
const searchRange = Number(process.env.SEARCH_RANGE ?? "0.6")
const searchStep = Number(process.env.SEARCH_STEP ?? "0.1")
const centerOverride = process.env.SEARCH_CENTER?.split(",").map(Number)
for (const viaId of searchTargets) {
const via = base.find((element) => element.type === "pcb_via" && element.pcb_via_id === viaId)
if (!via) throw new Error(`Missing ${viaId}`)
const centerX = centerOverride?.[0] ?? via.x
const centerY = centerOverride?.[1] ?? via.y
const candidates = []
for (let dx = -searchRange; dx <= searchRange + 0.0001; dx += searchStep) {
for (let dy = -searchRange; dy <= searchRange + 0.0001; dy += searchStep) {
const x = Math.round((centerX + dx) * 10000) / 10000
const y = Math.round((centerY + dy) * 10000) / 10000
if ((viaId === "pcb_via_48" || viaId === "pcb_via_55") && y > 9.575) continue
if (viaId === "pcb_via_74" && x > 9.575) continue
const errors = await hardErrors(moveVia(base, viaId, x, y))
const involving = errors.filter((error) => JSON.stringify(error).includes(viaId)).length
candidates.push({ x, y, total: errors.length, involving })
}
}
candidates.sort((a, b) => a.total - b.total || a.involving - b.involving ||
Math.hypot(a.x - via.x, a.y - via.y) - Math.hypot(b.x - via.x, b.y - via.y))
console.log(viaId, JSON.stringify(candidates.slice(0, 20)))
const best = candidates[0]
const bestErrors = await hardErrors(moveVia(base, viaId, best.x, best.y))
console.log(bestErrors.map((error) => `${error.type}\t${error.message}`).join("\n"))
}