It's somehow already been over a month since I last posted motor dyno documentation, so a lot has happened in the meantime.
The basic architecture of the system looks like this:
Most importantly, the absorber and the test motor are run off the same power supply. This means that the power supplies only have to output the losses in the system, not the absolute power of each motor. And since the buck converter powering the test motor is synchronous, the dyno supports full 4-quadrant operation.
Absorber Testing
Here's the test setup for getting the absorber controller up and running.
There's a lot going on there. The absorber is driving an even bigger brushless motor, which has a 3-phase rectifier on its phases. The output of the rectifier is fed into the MITERS Dynaload to dissipate the power. The torque sensor is fed into a USB DAQ (MCC USB-1608FS) and logged and plotted by some python scripts, and commands are sent to the absorber controller over serial from my laptop.
I had a crisis for a couple days while testing the absorber. Inexplicably, I measured about 2 times less torque than I expected for a given phase current. I went through my code and triple checked all the hardware gains. I physically measured the torque sensor gain with a lever and a weighing scale, and it perfectly matched its datasheet. Similarly, passing known current through the current sensors produced the expected output. I checked the absorber's back-emf on the scope for the nth time, and it checked out. After many hours of confusion, I realized that I was editing the DAQ-sampling function in an old version of the python file, which was no longer being called. So my display was showing just the raw torque sensor voltage, and not multiplying it by the 2.26 N-m/Volt scaling I thought I had entered. Saved. For a brief while I was worried I had somehow been fundamentally misunderstanding something about motors this whole time.
Buck Converter
The test motor is powered through a synchronous buck converter. I targeted a power range of 200+ amps at 5-48 volts, to make it useful for powering a wide range of motors and controllers. A buck converter of that size is a non-trivial design problem, so in the interest of having a working dyno, I skipped all the buck converter designing and hacked something together out of used Prius power electronics. Everything is extremely oversized and poorly suited for my needs, but the parts are so oversized I at least know I probably won't blow anything up. Eventually I'll get around to designing a more appropriately sized buck converter out of reasonable components.
The switching is done by a Prius half-bridge module, which in the car is used for the boost converter which steps up the battery voltage to 500-ish volts to run the motors. Nick Kirkby has an excellent writeup of the boost module, and how to turn it on. Output voltage is measured with an isolated voltage measurement modulePeter found. DC current is measured with an Allegro current sensor similar to the ones I used on the GigaTroller. Eventually I plan on replacing this with a LEM (closed loop hall) current sensor to squeeze a bit more resolution out.
A Nucleo receives voltage commands over serial to set the duty cycle of the buck. Right now the buck operates open-loop - I simply haven't had a chance to close the voltage loop yet.
Debugging the buck:
User Interface
To control they dyno, I've been putting together a UI which runs on a computer to control all the setpoints and log data. Right now, it looks like this:
The GUI is built with QT in Python, with the library pyqtgraph (which is built on top of PyQt) used for the real-time plotting. Data to and from the absorber controller are passed over serial, and the DAQ is sampled with a Python wrapper for MCC's Universal Library.
The dyno has a couple different operating modes right now: Road load and speed control.
Road load simulates a mechanical load - an inertia, and two friction coefficients (coulomb, viscous). It does so by measuring the torque on the torque sensor, computing what the net torque should be (measured torque - viscous friction - coulomb friction), computing what the acceleration should be (net torque/inertia), and integrating the velocity command with the acceleration. This loop isn't incredibly responsive, as it only runs at the 100 Hz of the python gui, but it does work pretty well.
Speed mode just sets the velocity command to whatever value you want.
I plan on adding another operating mode which takes a CSV timeseries of operating points (speed setpoint, buck voltage setpoint, test motor command) and following that, to make running tests like efficiency maps easy.
Here's a video demoing the inertia simulation of the road load mode:
Electrical Noise Problems
The torque sensor alone is an incredibly precise instrument. There's less than 1/1000th of a Newton-meter of noise on its output, and it (when plugged into a nice 16-bit DAQ) can easily resolve few-1000'ths of a N-m torques. Which I find incredibly impressive for a sensor which can measure >10 N-m peak. The story changes, however, when all the power electronics in the dyno get turned on. Plugging in the inverter for the absorber increased the noise on the torque sensor to a few 100'ths of a newton meter. And plugging in the buck converter gave me another order-of-magnitude of noise.
Fixing the buck converter noise was relatively straight-forward. The logic ground of the buck converter was connected to the ground of the DAQ through a USB cable. Since the serial communication to the buck can be slow, and is only in one direction, I just stuck an opto-isolator on the TX line of the st-link I'm using for serial communication.
Inverter noise was much trickier. The basic symptom was that, as soon as the inverter had power on the bus, the noise appeared. The bus voltage was completely isolated from the DAQ and torque sensor, as was the logic voltage. The noise appeared even when the inverter logic wasn't plugged in over USB. So there was literally no shared ground or power between the DAQ/torque sensor and the inverter. Fortunately, Kramnik was around while I was trying to debug, and was able to almost completely solve the problem. It seems the problem was the motor windings capacitively coupling to the motor housing and metal frame of the dyno. The solution was to 1: put a common-mode choke on the windings, right next to the inverter, and 2: add shielding braid around the windings, which is connected at each end to the motor housing and inverter heatsink. Doing this reduced the noise down to ~4/1000ths of a newton meter, which is definitely acceptable, although there's a little room for improvement.
Magmotor Testing
To test everything, I've been using some big brushed DC motors, including one of the combat-robotting-favorite Magmotor S28-200.
These plots were generated in the simplest way possible: have the absorber simulate an inertia, and apply a voltage step to the DC motor. Each line in the 3D scatter plot corresponds to a voltage step. This only worked up to ~20 volts, at which point the initial power draw tripped the power supplies. Either current limiting on the buck, or a current-controlled driver between the buck and dc motor would fix this.
Here's the same information, but re-scrambled for power vs speed. Keep in mind, this is actual mechanical power coming out of the motor, not power going in.
In the long run, the more intelligent way to produce an efficiency map would be to automatically sweep torques and speeds at steady-state, by controlling the absorber speed and the torque command to the test motor. The data above is a little bit wrong, because the test motor is accelerating - the measured torque is going to be off by the angular acceleration times rotor inertia of the test motor.
Such science. Next steps include adding more automation to the test process, so I don't have to sit there and babysit the dyno to run tests.