imrishabh18/rp2040-motor-controller

An RP2040-based NEMA17 stepper-motor controller with USB-C programming and PD motor-power negotiation, DRV8825 dual H-bridge drive, current/temperature telemetry, protected power filtering, status RGB LED, buzzer alarm, and optional magnetic encoder.

Version
1.0.42
License
unset
Stars
3

tests/helpers/assertPdVoltageControl.ts

import type { CircuitJson } from "circuit-json";

/** Check package pins and both power domains, independently of cached net keys. */
export function assertPdVoltageControl(json: CircuitJson) {
  const j = json as any[];
  const parent = new Map<string, string>();
  const root = (id: string): string => {
    if (!parent.has(id)) parent.set(id, id);
    if (parent.get(id) !== id) parent.set(id, root(parent.get(id)!));
    return parent.get(id)!;
  };
  for (const e of j) {
    const ids = e.type === "source_trace"
      ? [...e.connected_source_port_ids, ...e.connected_source_net_ids]
      : e.type === "source_component_internal_connection" ? e.source_port_ids : [];
    for (const id of ids.slice(1)) parent.set(root(id), root(ids[0]));
  }
  const part = (name: string) => {
    const c = j.find(e => e.type === "source_component" && e.name === name);
    if (!c) throw new Error(`Missing ${name}`);
    return c;
  };
  const port = (name: string, pin: number) => {
    const p = j.find(e => e.type === "source_port" && e.source_component_id === part(name).source_component_id && e.pin_number === pin);
    if (!p) throw new Error(`Missing ${name} pin ${pin}`);
    return p;
  };
  const net = (name: string, pin: number) => root(port(name, pin).source_port_id);
  const same = (a: [string, number], b: [string, number]) => {
    if (net(...a) !== net(...b)) throw new Error(`Disconnected ${a.join('.')} / ${b.join('.')}`);
  };
  const independent = [net('U_PD', 1), net('U_PD', 11), net('L_AVDD', 1), net('U_PD', 10)];
  // CH224K ESSOP10: CFG1=9, CFG2=2, CFG3=3. RP2040 GPIO4/5/6=6/7/8.
  for (const [index, cfgPin, mcuPin] of [[1, 9, 6], [2, 2, 7], [3, 3, 8]]) {
    const q = `Q_PD_CFG${index}`, r = `R_PD_CFG${index}_PU`;
    if (part(q).manufacturer_part_number !== 'DTC114EETL' || part(q).supplier_part_numbers.jlcpcb[0] !== 'C79605') throw new Error('Wrong PD buffer');
    if (part(r).resistance !== 47000) throw new Error(`Wrong ${r} pull-up`);
    same(['U1', mcuPin!], [q, 1]);
    same(['U_PD', cfgPin!], [q, 3]);
    same(['U_PD', cfgPin!], [r, 1]);
    same(['U_PD', 1], [r, 2]);
    same(['U_PD', 11], [q, 2]);
    independent.push(net(q, 1), net(q, 3));
  }
  if (new Set(independent).size !== independent.length) throw new Error('PD control short, GPIO reuse, or power-domain bypass');
  if (part('U_PD').manufacturer_part_number !== 'CH224K') throw new Error('Wrong PD controller');
  return {status: 'pass', gpios: [4, 5, 6], cfgPhysicalPins: [9, 2, 3], inverted: true, startupRequestV: 5};
}