techmannih/nema34-mounted-stepper-controller

A USB-C PD-powered RP2040 motor controller with protected 48 V power, DRV8262 dual-bridge drive for a NEMA34 motor, regenerative-braking resistor, isolated sensing, hardware interlocks, and telemetry/status interfaces.

Version
0.3.113
License
unset
Stars
1

firmware/tests/test_commissioning.cpp

#include <cassert>
#include "../target/main.cpp"
static bool suspended;
void initializeSuspendTimer() {}
void enterUsbSuspendPower() {}
void leaveUsbSuspendPower() {}
bool usbIsSuspended() {return suspended;}
void sleepWhileUsbSuspended() {}
static unsigned stepEdges;
static uint8_t previousMicrostep;
static void advance(unsigned ms) {
  for(unsigned i=0;i<ms;++i) {
    for(fakeMicros=0;fakeMicros<1000;fakeMicros+=20) {
      stepInterrupt(nullptr);
      if(driver.enabled && driver.microstep!=previousMicrostep) ++stepEdges;
      previousMicrostep=driver.microstep;
    }
    fakeMicros=0; ++fakeNow; loop();
  }
}
static void press() {fakeLevels[pin(PD1180_PIN_USER_BUTTON_N)]=LOW;advance(40);fakeLevels[pin(PD1180_PIN_USER_BUTTON_N)]=HIGH;advance(40);}
int main() {
  static_assert(PD1180_TEST_PROFILE==1 || PD1180_TEST_PROFILE==2);
  fakeLevels[pin(PD1180_PIN_USER_BUTTON_N)]=HIGH;
  fakeAdc[pin(PD1180_PIN_USB_VBUS_SENSE)]=279;
  for(auto p:{PD1180_PIN_LOGIC_PG_MCU,PD1180_PIN_EFUSE_FAULT_N,PD1180_PIN_DRV_FAULT_N}) fakeLevels[pin(p)]=HIGH;
  pdBus.pdPresent=pdBus.pdVoltagePresent=pdBus.adcPresent=pdBus.temperaturePresent=true;
  motorSpi.transferObserver=[](uint8_t) {
    assert(!fakeLevels[pin(PD1180_PIN_DRV_ENABLE_A)] && !fakeLevels[pin(PD1180_PIN_DRV_ENABLE_B)]);
    assert(!fakeLevels[pin(PD1180_PIN_DAC_CS_N)] && fakeLevels[pin(PD1180_PIN_DAC_LDAC_N)]);
  };
  setup();advance(400);
  assert(inputs.pd_power_good && inputs.temperature_valid && inputs.configuration_verified);
  assert(!control.armed && !fakeLevels[pin(PD1180_PIN_POWER_PERMIT)] && stepEdges==0);
  press();advance(1450); // C18 ramp interval: motor power is not yet good.
  assert(control.power_permit && !control.mcu_run && !control.fault_latched && stepEdges==0);
  fakeLevels[pin(PD1180_PIN_MOTOR_PG)]=fakeLevels[pin(PD1180_PIN_VMOTOR_OK)]=HIGH;
  advance(400);
  if(powerTestOnly) {
    assert(control.power_permit && !control.mcu_run && stepEdges==0);
    advance(30000);assert(!control.power_permit && control.fault_latched && stepEdges==0);
  } else {
    assert(control.mcu_run && driver.configured && driverStatus.valid && stepEdges>0);
    assert(currentMa<=800 && driver.rms_ma==800); // bounded software current target
    advance(12000);
    assert(!control.armed && !control.power_permit && !control.mcu_run && !stepMotion.active);
    const auto stopped=stepEdges;advance(2000);assert(stepEdges==stopped); // no automatic repeat
    press();advance(600);assert(control.mcu_run);
    fakeLevels[pin(PD1180_PIN_DRV_FAULT_N)]=LOW;advance(1);
    assert(!fakeLevels[pin(PD1180_PIN_MCU_RUN)] && !fakeLevels[pin(PD1180_PIN_POWER_PERMIT)]);
    advance(40);assert(control.fault_latched && !desiredMotion);
    fakeLevels[pin(PD1180_PIN_DRV_FAULT_N)]=HIGH;advance(1000);assert(!control.mcu_run);
    press();advance(100);assert(!control.armed); // acknowledge only
    press();advance(600);assert(control.mcu_run);
    suspended=true;advance(1);assert(!control.mcu_run && !control.power_permit && !desiredMotion);
    suspended=false;advance(800);assert(!control.armed && !control.mcu_run);
  }
  if(!powerTestOnly) {
    assert(motorSpi.hz==8000000 && motorSpi.mode==SPI_MODE0 && motorSpi.order==MSBFIRST);
    assert(!motorSpi.bytes.empty() && motorSpi.bytes.size()%4==0);
    for(size_t n=0;n<motorSpi.bytes.size();n+=4) {
      const unsigned a=(motorSpi.bytes[n]<<8)|motorSpi.bytes[n+1];
      const unsigned b=(motorSpi.bytes[n+2]<<8)|motorSpi.bytes[n+3];
      // Both DACs enabled, gain 2, distinct A/B selects and bounded references.
      assert((a&0xf000)==0x1000 && (b&0xf000)==0x9000);
      assert((a&0xfff)<=359 && (b&0xfff)<=359);
    }
  }
  puts(powerTestOnly ? "PASS: stationary profile powers bus, never enable phases, expires and latches" : "PASS: real target delayed startup, DAC phase sequencing, bounded motion/stop, fault latch and suspend");
}