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

tests/thermal-protection.test.tsx

import { expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { Circuit } from "tscircuit";
import type { CircuitJson } from "circuit-json";
import Board from "../index.circuit";
import { assertThermalProtection } from "./helpers/assertThermalProtection";

async function buildJson(): Promise<CircuitJson> {
  if (process.env.CIRCUIT_JSON_PATH) return JSON.parse(readFileSync(process.env.CIRCUIT_JSON_PATH, "utf8"));
  const circuit = new Circuit({ platform: { pcbDisabled: true } });
  circuit.add(<Board routingDisabled />);
  await circuit.renderUntilSettled();
  return circuit.getCircuitJson();
}

test("sensor uses the correct pins, rail and pull resistors; enable passes through both interlocks", async () => {
  const json = await buildJson();
  expect(assertThermalProtection(json).status).toBe("pass");
  const disconnect = json.filter(e => !(e.type === "source_trace" && e.name === "TEMP_HARDWARE_INTERLOCK"));
  expect(() => assertThermalProtection(disconnect)).toThrow("Disconnected");
  const port = (part: string, label: string) => {
    const c = json.find(e => e.type === "source_component" && e.name === part)!;
    if (c.type !== "source_component") throw Error("component");
    const p = json.find(e => e.type === "source_port" && e.source_component_id === c.source_component_id && e.port_hints?.includes(label));
    if (p?.type !== "source_port") throw Error("port");
    return p.source_port_id;
  };
  const bypass: CircuitJson = [...json, { type: "source_trace", source_trace_id: "test_bypass",
    connected_source_port_ids: [port("Q_PD_ENABLE", "drain"), port("DRIVER", "nSleep")], connected_source_net_ids: [] }];
  expect(() => assertThermalProtection(bypass)).toThrow("bypass");
}, 60_000);