astra/nema17-stepper-motor-controller-spring-clamp-rp2040

A 4-layer RP2040 controller board that negotiates USB‑C PD motor power and drives a NEMA17 stepper via a DRV8825, with current sensing, thermal shutdown, RGB status LED, buzzer alarm, optional AS5600 encoder, protection/filtering, and test points.

Version
1.4.0
License
unset
Stars
0

scripts/reroute-revision.tsx

import { Circuit } from "tscircuit";
import { AutoroutingPipelineSolver } from "@tscircuit/capacity-autorouter";
import { writeFileSync, mkdirSync } from "node:fs";
import Board from "../index.circuit";
mkdirSync("dist/revision",{recursive:true});
const circuit = new Circuit();
const route = async (input: any) => {
  writeFileSync("dist/revision/routing-input.json", JSON.stringify(input,null,2));
  const handlers = new Map<string,Function>();
  return {
    on(name:string, fn:Function){handlers.set(name,fn)}, stop(){},
    async start(){
      try {
        const solver=new AutoroutingPipelineSolver(input,{effort:2});
        let last=Date.now(),lastPhase="";
        const started = Date.now();
        while(!solver.solved && !solver.failed){
          if (Date.now()-started > 600_000) throw new Error("Routing exceeded ten minutes");
          const until=Date.now()+100;
          while(Date.now()<until && !solver.solved && !solver.failed) solver.step();
          if(solver.getCurrentPhase()!==lastPhase || Date.now()-last>15000){
            lastPhase=solver.getCurrentPhase();last=Date.now();
            console.log(lastPhase,solver.iterations,solver.computeProgress());
          }
          await Bun.sleep(0);
        }
        if(!solver.solved) throw new Error(String(solver.error));
        const output:any=solver.getOutputSimpleRouteJson();
        const traces=output.traces ?? output;
        // The fabrication stack uses drilled through vias, not blind/buried vias.
        // Preserve the route's wire layers; declare each physical via's full span.
        for(const t of traces) for(const p of t.route ?? []) if(p.route_type==='via'){p.from_layer='top';p.to_layer='bottom';}
        writeFileSync("dist/revision/route-plan.json",JSON.stringify({expectedInput:input,traces},null,2));
        handlers.get("complete")?.({traces});
      } catch(error){console.error(error);process.exit(1)}
    }
  };
};
circuit.add(<Board finalizeGroundPours={false} routingAlgorithm={route as any}/>);
await circuit.renderUntilSettled();
const json=circuit.getCircuitJson();
writeFileSync('dist/revision/circuit.json',JSON.stringify(json,null,2));
const errors = json.filter(x => x.type.endsWith('_error'));
console.log('Errors:', errors);
if (errors.length) process.exitCode = 1;