techmannih/nema34-mounted-stepper-controller
A 48 V USB‑C PD 3.1 EPR NEMA‑34 stepper controller PCB combining STM32/TMC5160 control, external MOSFET motor bridges, protected power and regenerative braking, USB data, telemetry, diagnostics, status LEDs, and buzzer alarms.
- Version
- 0.3.92
- License
- unset
- Stars
- 1
firmware/tests/test_target_power.cpp
#include <cassert>
#include "../target/main.cpp"
static bool suspended;
static unsigned sleeps;
void initializeSuspendTimer() {}
bool usbIsSuspended() { return suspended; }
void sleepWhileUsbSuspended() { ++sleeps; }
static void advance(unsigned ms) { fakeNow+=ms; loop(); }
static void expectSafe() {
for (auto p : {PD1180_PIN_MCU_RUN, PD1180_PIN_POWER_PERMIT, PD1180_PIN_SD_MODE})
assert(fakeLevels[pin(p)]==LOW);
for (auto p : {PD1180_PIN_TMC_CS_N, PD1180_PIN_ENC_CS_N, PD1180_PIN_FLASH_CS_N}) {
assert(fakeModes[pin(p)]==OUTPUT_OPEN_DRAIN);
assert(fakeLevels[pin(p)]==HIGH);
}
}
int main() {
uint8_t identity[8] = {'P','D','1','1','8','0','4','1'};
assert(pdConfigurationMatches(identity));
for (unsigned i=0;i<sizeof(identity);i++) {identity[i]^=1; assert(!pdConfigurationMatches(identity)); identity[i]^=1;}
memset(identity,0,sizeof(identity)); assert(!pdConfigurationMatches(identity));
assert(!pdImageVerified && !motionQualified);
// Exercise the actual mux scan and target call site: bus=200 ms, return=240
// ms. Q16 goes low after the bus reading; the next scan recovers at 300 ms.
pdBus.adcPresent=true;
control.power_permit=true;
for(unsigned t=10;t<=180;t+=10) {
fakeNow=t; pollBusAdc(t);
if(t%60==0) pollPower();
}
assert(brakePreflight.ready);
control.mcu_run=true;
for(unsigned t=190;t<=300;t+=10) {
fakeNow=t;
pdBus.adcRaw[2]=(t>200 && t<=240) ? 0 : 19762;
pollBusAdc(t);
if(t==240) {
assert(adcSampleAt[0]==200 && adcSampleAt[2]==240);
pollPower(); assert(inputs.brake_preflight_ok && !brakePreflight.faulted);
}
if(t==250 || t==300) {
pollPower(); assert(inputs.brake_preflight_ok && !brakePreflight.faulted);
}
}
assert(!brakePreflight.mismatch_pending);
invalidateTelemetry(); fakeNow=lastAdcPoll=0; pdBus.adcChannels.clear();
pdBus.adcPresent=true;
for (unsigned n=1;n<=6;n++) pollBusAdc(n*10u);
assert((pdBus.adcChannels==std::vector<unsigned>{0,1,2}));
assert(adcValid[0] && adcValid[1] && adcValid[2]);
assert(adcMv[2]==2470 && adcSampleAt[2]==60);
pdBus.adcFail=true; pollBusAdc(70);
assert(!adcValid[0] && !adcValid[1] && !adcValid[2]);
pdBus.adcPresent=false; pdBus.adcFail=false; pdBus.transactions=0;
invalidateTelemetry(); lastAdcPoll=0;
fakeAdc[pin(PD1180_PIN_USB_VBUS_SENSE)]=279; // Approximately 5 V DATA supply.
setup(); advance(1);
assert(usbStarted && !peripheralsStarted && !pdBus.started);
assert(pdBus.transactions==0);
expectSafe();
SerialUSB.input="ARM\n";advance(1);advance(1);
assert(SerialUSB.output.find("BLOCKED")!=std::string::npos);
expectSafe();
fakeAdc[pin(PD1180_PIN_BOARD_POWER_SENSE)]=2048;
advance(1);assert(!peripheralsStarted);
advance(19);assert(!peripheralsStarted);
advance(1);assert(peripheralsStarted && pdBus.started);
assert(!spiStarted && motorSpi.transactions==0);
inputs.motor_power_good=inputs.vmotor_in_range=true;
pollDriver(fakeNow+20);
assert(spiStarted && !tmcStatus.valid && !inputs.driver_ready);
inputs.motor_power_good=false; pollDriver(fakeNow+21);
assert(!spiStarted && fakeModes[pin(PD1180_PIN_SPI_MOSI)]==INPUT_ANALOG);
adcValid[0]=adcValid[2]=phaseValid=inputs.temperature_valid=true;
brakePreflight.ready=inputs.brake_preflight_ok=true;
fakeAdc[pin(PD1180_PIN_BOARD_POWER_SENSE)]=0;
advance(1);
assert(!peripheralsStarted && !pdBus.started && !adcValid[0] && !adcValid[2] && !brakePreflight.ready && !inputs.brake_preflight_ok && !phaseValid && !inputs.temperature_valid);
assert(fakeModes[pin(PD1180_PIN_PD_SCL)]==INPUT_ANALOG);
expectSafe();
fakeAdc[pin(PD1180_PIN_BOARD_POWER_SENSE)]=2048;
advance(1);advance(20);assert(peripheralsStarted);
commandLength=3; responseLength=10;
const auto reads=pdBus.transactions, reloads=IWatchdog.reloads;
suspended=true;advance(1);
assert(sleeps==1 && IWatchdog.reloads==reloads+1);
assert(pdBus.transactions==reads && !pdBus.started && !peripheralsStarted);
assert(commandLength==0 && responseLength==0 && fakeLevels[pin(PD1180_PIN_STATUS_GPIO)]==LOW);
expectSafe();
suspended=false;advance(1);assert(!peripheralsStarted);
advance(20);assert(peripheralsStarted);
expectSafe();
suspended=true;advance(1);
fakeAdc[pin(PD1180_PIN_USB_VBUS_SENSE)]=0;advance(1);
assert(!usbStarted && !SerialUSB.started);
expectSafe();
puts("PASS: target USB-only startup, power loss/recovery, suspend/resume, detach and ARM lock");
}