imrishabh18/rp2040-motor-controller

This circuit incorporates a USB-C Power Delivery (PD) interface with a CH224K controller, a WJ500V-5.08-04P motor output connector, multiple power conditioning components including capacitors, resistors, diodes, and an RP2040 microcontroller, to manage motor control, signal routing, and power management for a USB-powered stepper motor system.

Version
1.0.14
License
unset
Stars
0

tests/helpers/assertCommonGround.ts

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

/** Follow electrical edges only: names and cached connectivity keys are not edges. */
export function assertCommonGround(json: CircuitJson) {
  const parent = new Map<string, string>();
  const root = (id: string): string => {
    if (!parent.has(id)) parent.set(id, id);
    const next = parent.get(id)!;
    if (next !== id) parent.set(id, root(next));
    return parent.get(id)!;
  };
  for (const element of json) {
    const ids = element.type === "source_trace"
      ? [...element.connected_source_port_ids, ...element.connected_source_net_ids]
      : element.type === "source_component_internal_connection"
        ? element.source_port_ids : [];
    for (const id of ids.slice(1)) parent.set(root(id), root(ids[0]!));
  }
  const nets = json.filter((e): e is SourceNet => e.type === "source_net" && e.name === "GND");
  if (!nets.length) throw new Error("Missing GND net");
  const ground = root(nets[0]!.source_net_id);
  for (const net of nets) {
    if (root(net.source_net_id) !== ground) throw new Error("Disconnected GND networks");
  }
  const required = [
    ["U1", "GND"], ["TP_GND", "pin1"],
    ["DRIVER", "GND1"], ["DRIVER", "GND2"],
    ["DRIVER", "MODE"], ["DRIVER", "TRQ"],
    ["J_USB", "A1B12"], ["J_MOTOR_USB", "A1B12"],
    ["U_PD", "GND"], ["R_ISEN_A", "pin2"], ["R_ISEN_B", "pin2"],
    ["C_VM_BULK", "pin2"], ["C_VM_HF", "pin2"],
    ["C_PD_VDD", "pin2"], ["C_PD_VBUS", "pin2"],
    ["C_MOTOR_BULK", "pin2"], ["D_MOTOR_TVS", "pin1"],
    ["R_SLEEP_PD", "pin2"],
  ];
  for (const [name, pin] of required) {
    const component = json.find((e) => e.type === "source_component" && e.name === name);
    if (component?.type !== "source_component") throw new Error(`Missing ${name}`);
    const port = json.find((e) => e.type === "source_port" &&
      e.source_component_id === component.source_component_id &&
      (e.name === pin || e.port_hints?.includes(pin!)));
    if (port?.type !== "source_port" || root(port.source_port_id) !== ground) {
      throw new Error(`${name}.${pin} is not on common ground`);
    }
  }
  for (const e of json) {
    if (e.type === "pcb_copper_pour" && (!e.source_net_id || root(e.source_net_id) !== ground)) {
      throw new Error("Copper pour is not assigned to common ground");
    }
    if (e.type === "source_net" && ["VBUS", "VSYS", "V3V3", "V1V1"].includes(e.name) &&
      root(e.source_net_id) === ground) throw new Error(`${e.name} is shorted to ground`);
  }
  // Sense inputs must reach their own shunt, never bypass it to ground.
  const portFor = (name: string, pin: string) => {
    const component = json.find(e => e.type === "source_component" && e.name === name);
    if (component?.type !== "source_component") throw new Error(`Missing ${name}`);
    const port = json.find(e => e.type === "source_port" &&
      e.source_component_id === component.source_component_id &&
      (e.name === pin || e.port_hints?.includes(pin)));
    if (port?.type !== "source_port") throw new Error(`Missing ${name}.${pin}`);
    return root(port.source_port_id);
  };
  for (const channel of ["A", "B"]) {
    const sense = portFor("DRIVER", `${channel}ISEN`);
    if (sense === ground || sense !== portFor(`R_ISEN_${channel}`, "pin1")) {
      throw new Error(`Invalid ${channel}-channel current-sense connection`);
    }
  }
  const motorNets = ["AOUT1", "AOUT2", "BOUT1", "BOUT2"].map((pin, i) => {
    const motor = portFor("DRIVER", pin);
    if (motor === ground || motor !== portFor("J1", `pin${i + 1}`)) {
      throw new Error(`Invalid motor output ${pin}`);
    }
    return motor;
  });
  if (new Set(motorNets).size !== 4) throw new Error("Motor outputs are shorted together");
  return { groundNetDeclarations: nets.length, checkedGroundPorts: required.length, checkedCurrentSenseChannels: 2, checkedMotorOutputs: 4 };
}