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.41
License
unset
Stars
3

tests/drv8825.test.tsx

import {expect, test} from "bun:test";
import {Circuit} from "tscircuit";
import Board from "../index.circuit";

test("DRV8825 physical pins, isolated reference, microstep mode and charge pump", async () => {
  const c=new Circuit({platform:{pcbDisabled:true}});
  c.add(<Board routingDisabled/>); await c.renderUntilSettled();
  const j:any[]=c.getCircuitJson();
  const parent=new Map<string,string>();
  const root=(id:string):string=>{if(!parent.has(id))parent.set(id,id);const p=parent.get(id)!;if(p!==id)parent.set(id,root(p));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)=>j.find(e=>e.type==='source_component'&&e.name===name)!;
  const port=(name:string,pin:number|string)=>j.find(e=>e.type==='source_port'&&e.source_component_id===part(name).source_component_id&&(typeof pin==='number'?e.pin_number===pin:e.name===pin||e.port_hints?.includes(pin)))!;
  const net=(name:string,pin:number|string)=>root(port(name,pin).source_port_id);
  const groups:[string,number|string][][]=[
    [['DRIVER',1],['C_CP',1]], [['DRIVER',2],['C_CP',2]],
    [['DRIVER',3],['C_VCP',1],['R_VCP',1]],
    [['DRIVER',4],['DRIVER',11],['C_VMA',1],['C_VM_HF',1],['C_VM_BULK',1],['C_VCP',2],['R_VCP',2],['D_MOTOR_BLOCK',1]],
    [['DRIVER',6],['R_ISEN_A',1]], [['DRIVER',9],['R_ISEN_B',1]],
    [['DRIVER',12],['DRIVER',13],['R_DRV_REF_TOP',2],['R_DRV_REF_BOTTOM',1],['C_DRV_REF',1]],
    [['DRIVER',15],['DRIVER',26],['C_DRV_3V3',1],['R_DRV_REF_TOP',1]],
    [['DRIVER',14],['DRIVER',28],['DRIVER',29],['DRIVER',24],['DRIVER',25],['C_DRV_3V3',2],['C_DRV_REF',2],['R_DRV_REF_BOTTOM',2],['U1','GND']],
    [['DRIVER',22],['U1','GPIO18']], [['DRIVER',20],['U1','GPIO19']],
    [['DRIVER',16],['U1','GPIO20']], [['DRIVER',21],['U1','GPIO21'],['R_DRV_ENABLE_PU',1]],
    [['DRIVER',17],['Q_PD_ENABLE','drain']], [['DRIVER',18],['U1','GPIO23']],
    [['R_DRV_ENABLE_PU',2],['L_AVDD',1]],
  ];
  for(const g of groups)for(const other of g.slice(1))expect(net(...other)).toBe(net(...g[0]!));
  expect(new Set(groups.map(g=>net(...g[0]!))).size).toBe(groups.length);
  for(const pin of [19,23,27]){
    const p=port('DRIVER',pin);
    expect(j.filter(e=>e.type==='source_trace'&&e.connected_source_port_ids.includes(p.source_port_id))).toEqual([]);
  }
  const reference=3.3*part('R_DRV_REF_BOTTOM').resistance/(part('R_DRV_REF_TOP').resistance+part('R_DRV_REF_BOTTOM').resistance);
  expect(reference).toBeCloseTo(1.5,6);
  for(const phase of ['A','B'])expect(reference/(5*part(`R_ISEN_${phase}`).resistance)).toBeCloseTo(1,6);
  expect(3.4/(4400*.99)+3.4/80000+6e-6).toBeLessThan(.001);
  expect(part('C_CP').capacitance).toBeCloseTo(10e-9,12);
  expect(part('C_CP').max_voltage_rating).toBeGreaterThanOrEqual(50);
  expect(part('C_VCP').capacitance).toBeCloseTo(100e-9,12);
  expect(part('C_DRV_3V3').capacitance).toBeCloseTo(470e-9,12);
  for(const name of ['C_MOTOR_BULK','C_PD_VBUS','C_VM_BULK','C_VMA','C_VM_HF'])expect(part(name).max_voltage_rating).toBeGreaterThanOrEqual(50);
},60000);