A brushless motor test bench needs a power source that holds the bus voltage through every current peak the test produces. Learn how to build a current budget from the motor count and the load, choose between a bench supply, a battery and a hybrid of both, size the wiring and pre-charge, and log bus voltage and current on every run with TofuPilot.
Build the Current Budget
Size the source from two numbers: the continuous current the bench draws during the longest test step, and the peak current it draws during transients. Both scale with the number of motors that run at the same time.
I_continuous = motors x I_motor_steadyI_peak = motors x I_motor_peakP_source = V_bus_max x I_continuous (add margin for peaks)The table below uses values measured on a 3115-size 1250KV motor driven by a 4-in-1 100 A BLHeli_32 ESC on a 6S bus, without propeller. The propeller figures are an estimate for a typical propeller at full throttle, not a measurement.
| Condition | Per motor | 4 motors |
|---|---|---|
| No prop, 25% throttle (8,350 rpm) | 0.65 A | 2.6 A |
| No prop, 70% throttle (22,600 rpm) | 2.65 A | 10.6 A |
| No prop, 100% throttle (31,000 rpm) | 3.5 to 4.5 A | 14 to 18 A |
| No prop, throttle step instead of ramp | up to 10 A spikes | up to 40 A if simultaneous |
| With prop, full throttle (estimate) | 60 to 80 A | 240 to 320 A |
Two conclusions follow from the table:
- Without propeller, the load is small. Four motors at full throttle draw 18 A continuous, about 450 W at 25.2 V (6S full charge). A 24 V, 25 A, 600 W supply covers it, provided the test ramps throttle instead of stepping it.
- With propeller, the load changes category. One motor at 70 A on a 25.2 V bus is 1.76 kW. Four motors at 70 A on a 22.2 V nominal bus is 6.2 kW. Bench supplies in that range are industrial units; a single 2.4 kW supply already costs several hundred euros.
The step spikes matter as much as the steady values. A throttle step asks the ESC to accelerate the rotor at once, and the current spike is several times the steady current. ArduPilot's MAV_CMD_DO_MOTOR_TEST cannot change throttle while a test runs, so a stepped profile built from it means stop and restart at each level, which is exactly what produces those spikes. Driving DShot directly from a microcontroller lets the test ramp throttle and keeps the peak close to the continuous value.
Choose the Source
| Source | Strengths | Limits |
|---|---|---|
| Bench supply (SMPS) | Stable voltage, current limit, remote readback over SCPI | Cannot sink current, so regeneration raises the bus; current limit folds the voltage on peaks |
| LiPo pack | Very high peak current, absorbs regeneration | Voltage depends on state of charge, sags under load, fire risk, needs charging between sessions |
| Hybrid (supply in parallel with pack) | Supply covers the average, pack covers peaks and absorbs regeneration | Supply must tolerate a back-fed output, pack must stay below full charge, more wiring |
A bench supply suits no-prop characterization and low-power endurance runs. A pack suits propeller tests where peaks reach tens of amps per motor. A hybrid suits long propeller runs where the pack alone would discharge too fast. Check the supply manual before paralleling it with a battery: some units are not designed for a back-fed output and need a series diode, which adds its own voltage drop.
Read the C-Rating Correctly
The C-rating on a LiPo label multiplies the capacity to give a maximum discharge current:
I_label = C x capacity5,000 mAh, 50C -> 50 x 5 A = 250 AThe label figure is not the current the pack sustains at a usable voltage. What limits the pack is its internal resistance, which sets the voltage sag and the heat dissipated in the cells:
V_sag = I x R_packP_heat = I^2 x R_packExample value: R_pack = 15 mOhm (6 cells x 2.5 mOhm) 70 A -> V_sag = 1.05 V, P_heat = 74 W 280 A -> V_sag = 4.2 V, P_heat = 1,176 WMeasure the internal resistance of your own packs with the charger or with a load step, and size from that value, not from the label. A pack that sags to the ESC low-voltage cutoff during a test step invalidates the test, even if its label claims ten times the current.
Size Connectors and Wire
Each milliohm in the power path costs voltage and heat at the currents a propeller test draws. Copper resistance per metre is a fixed property of the gauge:
| Gauge | Resistance | 2 m round trip at 70 A |
|---|---|---|
| 12 AWG | 5.21 mOhm/m | 0.73 V drop, 51 W |
| 10 AWG | 3.28 mOhm/m | 0.46 V drop, 32 W |
| 8 AWG | 2.06 mOhm/m | 0.29 V drop, 20 W |
The drop is I x R x length, the heat is I^2 x R x length. Ampacity depends on the insulation and how the wire is bundled, so take the current rating from the wire manufacturer. Keep the supply leads short and twisted to reduce loop inductance, which also limits voltage overshoot on current steps.
Choose connectors from the vendor's continuous rating with margin over I_continuous, and check that every crimp and solder joint in the path is rated for the same current. A connector run at its limit heats, its contact resistance rises, and the heat feeds itself.
Add Pre-Charge or an Anti-Spark Connector
ESCs carry large input capacitors. Connected directly to a charged pack, the only thing that limits the inrush current is the resistance of the pack and the wires:
Direct connection, example values: 25.2 V / 20 mOhm -> 1,260 A theoretical peakThrough a 10 Ohm pre-charge resistor, C = 2,000 uF (example value): I_peak = 25.2 V / 10 Ohm -> 2.5 A tau = R x C -> 20 ms 5 x tau -> 100 ms to reach 99% of the bus voltageThe direct connection arcs at the connector and erodes its contacts. Use an anti-spark connector, which closes through a built-in resistor before the main contact, or a pre-charge circuit: a resistor in parallel with a contactor or a switch that closes after five time constants. The same logic applies to a bench supply with its output already on: enable the output after connecting the bench, not before.
Log Bus Voltage and Current on Every Run
The bus voltage and current are part of the test result. A motor that passes on a fresh pack and fails on a sagging one is a power problem, not a motor problem, and only a logged bus trace tells them apart.
The procedure below ramps one motor to 70% throttle, holds, and ramps down, while it samples the supply readback. The trace is recorded as a multi-dimensional measurement, with a minimum voltage limit and a maximum current limit on aggregations.
procedure.yaml49 lines
name: Motor Bench Power Checkversion: 0.1.0config: PSU_ADDRESS: required: true DSHOT_PORT: required: trueplugs: - name: Bench Supply key: psu python: plugs.bench_supply:BenchSupply scope: station with: address: "{config.PSU_ADDRESS}" - name: DShot Driver key: motor python: plugs.dshot_driver:DshotDriver with: port: "{config.DSHOT_PORT}" motor_index: 0main: - name: Throttle Profile python: phases.run_profile timeout: 30s measurements: - name: Bus Trace x_axis: legend: Time unit: s y_axis: - legend: Bus Voltage key: bus_voltage unit: V aggregations: - type: min validators: - operator: ">=" expected_value: 21.5 - legend: Bus Current key: bus_current unit: A aggregations: - type: max validators: - operator: "<=" expected_value: 4.0The limits (21.5 V and 4.0 A) are example values. Set them from a baseline of known-good runs on your own bench. The supply plug reads back voltage and current with standard SCPI queries:
import pyvisaclass BenchSupply: def __init__(self, address): self._rm = pyvisa.ResourceManager() self._inst = self._rm.open_resource(address) self._inst.timeout = 2000 # ms def measure_voltage(self): return float(self._inst.query("MEAS:VOLT?")) def measure_current(self): return float(self._inst.query("MEAS:CURR?")) def __del__(self): self._inst.close()The motor plug talks to a microcontroller that generates the DShot300 frames. The line protocol is an example; replace it with the one your bench firmware implements:
plugs/dshot_driver.py20 lines
import serialclass DshotDriver: def __init__(self, port, motor_index): self._ser = serial.Serial(port, 115200, timeout=0.5) self._motor = motor_index def set_throttle(self, percent): # Example protocol: "T <motor> <percent>", firmware answers one line self._ser.write(f"T {self._motor} {percent:.1f}".encode()) self._ser.readline() def __del__(self): try: self.set_throttle(0.0) finally: self._ser.close()The phase interpolates the throttle profile, samples the bus at each step, and always returns the motor to zero:
phases/run_profile.py33 lines
import time# (time in s, throttle in %): ramp up, hold, ramp downPROFILE = [(0.0, 0.0), (2.0, 70.0), (6.0, 70.0), (8.0, 0.0)]def throttle_at(t): for (t0, p0), (t1, p1) in zip(PROFILE, PROFILE[1:]): if t0 <= t <= t1: return p0 + (p1 - p0) * (t - t0) / (t1 - t0) return 0.0def run_profile(measurements, log, motor, psu): times, volts, amps = [], [], [] start = time.monotonic() try: while (t := time.monotonic() - start) <= PROFILE[-1][0]: motor.set_throttle(throttle_at(t)) times.append(round(t, 3)) volts.append(psu.measure_voltage()) amps.append(psu.measure_current()) time.sleep(0.05) finally: motor.set_throttle(0.0) trace = measurements.bus_trace trace.x_axis = times trace.y_axis.bus_voltage = volts trace.y_axis.bus_current = amps trace.y_axis.bus_voltage.aggregations.min = min(volts) trace.y_axis.bus_current.aggregations.max = max(amps) log.info(f"{len(times)} samples, min {min(volts):.2f} V, max {max(amps):.2f} A")Supply readback over SCPI takes milliseconds per query and averages over the instrument's own integration time, so it shows sag and steady current, not microsecond spikes. To capture step spikes and regeneration peaks, add a current-sense ADC or an oscilloscope on the bus and record its peak as a separate numeric measurement.
On the dashboard, each run stores the trace against the unit serial number. The control chart of bus_voltage minimum across runs shows a pack ageing or a connector degrading before it causes a failure, and the failure Pareto separates power-limited failures from motor failures.
Common Pitfalls
Sizing from the steady current only. Throttle steps produce spikes several times the steady value. Either ramp the throttle or size the source for the spikes.
Trusting the C-rating label. Size from the measured internal resistance and the sag it produces at your test current.
Testing with a propeller on a supply sized for no-prop runs. The current rises by an order of magnitude; the supply enters current limit and the bus collapses.
Paralleling a supply and a pack without reading the supply manual. Some outputs do not tolerate back-feed. Add a series diode or choose a supply rated for it.
Connecting a charged pack without pre-charge. The inrush arc erodes the connector on every connection.
Ignoring regeneration. A switching supply cannot absorb the energy returned on deceleration, and the bus voltage rises. See how to handle regenerative braking on a test bench.
Key Points
- Build the budget as motors x current, separately for continuous and peak, with and without propeller.
- A 600 W supply covers four motors without propeller; propeller tests reach kilowatts per motor.
- Real pack current is limited by internal resistance and sag, not by the C-rating label.
- Size wire from
I x R x lengthand use pre-charge or an anti-spark connector on large packs. - Record the bus voltage and current trace on every run, with limits, so power problems are separated from unit failures.
