The torque sensor got new electronics Bayley designed, which have a built in power supply, A/D, and micro, to convert the signal to digital as quickly as possible. I made a nice box to house all the electronics:
The torque sensor mounted, with the absorber on the right and the motor under test on the left:
To power and control the test motor, there's a bank of terminals for DC input and motor phase output, if you want to drive the test motor with the Prius inverter built into the dyno. And quick disconnect fittings for water cooling the test motor:
Speaking of inverters, here's a look under the sheet metal covers: Underneath are two Prius "bricks" mounted to a big waterblock. Although the Prius power modules have two 3-phase inverters each, we had to use two of them so we could separate out the DC link current measurement for the inverter powering the test motor.
The dyno has an internal Mac Mini with linux on it, runing a fork of my dyno software. Thanks to the cross-platform-ness of Python and Qt, all I had to do was install all the libraries and change the "COM" serial ports to "/dev/ttyUSB" and it just worked. Yes, that's the "Hybrid Synergy Drive" plaque from the Prius power module covering up the Apple logo:
To go with the computer, it has a built-in monitor which can be raised and lowered for storage:
The absorber and all the sensors work, and we've helped the FSAE team do a little bit of testing on their new motors. Next up is populating the second half of the control electronics so the dyno can control the test motor. Then we'll be able to do a full optimization of the Sonata HSG and get even more power out of the big kart.
Bayley and I have been thinking about building a bigger motor dyno for a while now, based off the same power system as the Big Kart. Over the last year we've been slowly collecting parts for it - a torque sensor, a couple more Sonata HSGs, Prius inverters, etc, and I've finally started putting together the mechanical side of things.
Whereas the small dyno is good for 10 N-m of torque and 6000 RPM, this one will be good for 60 N-m and 15,000 RPM (although not simultaneously), and somewhere around 30 kW power.
First step was acquiring the appropriate torque sensor. The DC-output one I have on the small dyno is extremely convenient, because you can just measure the output with a DAQ or A/D, but the AC coupled ones are much more common on Ebay. Unfortunately, the readouts for the AC torque sensors are very expensive and hard to come by. A pile of really big, really cheap DC-operated torque sensors showed up on ebay for $28 apiece, so we got one and the MIT FSAE team collected the rest of the lot.
10,000 inch-pounds! (~1100 N-m) and 8500 RPM. With ~2" shafts on either end. Not actually very useful.
We gutted the readout electronics from it:
And shoved them into this AC-operated 500 in-lbs, 15k RPM torque sensor. This thing is pretty much perfectly matched to the Sonata HSGs.
Several months ago I went on a shaft-coupling machining spree, making the two lovejoy couplings for the torque sensor, and two more for a pair of the HSGs:
The shaft couplings all have internal keyways, which I manually shaped on the lathe. I ground HSS inserts for a boring bar, locked the lathe spindle, and shaped the keyways with the carriage feed, retracting the cross slide ~.005" per stroke, with occasional spring passes. The keyways can be easily widened by shifting the tool up a little on the toolpost.
I've been pleasantly surprised by how nicely the keyways turn out with this process. Even for some big 6mm keyways for pulley hubs for the Big Kart, the results were very clean.
The shape of the Sonata HSGs leaves much do be desired. While at least they are completely sealed and have real shafts, unlike the motors in most hybrid transmissions (i.e. the Prius or Fusion motors, which are tightly integrated into the powertrain, and have to be freshly rehoused to be used at all), they are very strangely shaped. Their cast aluminum housings have almost no flat or square surfaces, making them very challenging to measure. I was able to eventually find the positions of all three mounting feet and the shaft by using a surface plate, a height gauge, a set of adjustable parallels, some custom-turned shafts which press-fit into the bolt holes, and one sacrificial motor housing which was bandsawed in half. The last measurements, which located the motor shaft with respect to the feet, could not be reasonably made without referencing some of the machined bores on the inside of the housing.
I machined a pair of HSG mounts. The feet were turned on MITERS's newly acquired Hardinge HLV lathe, and the base was CNC milled on the Super Mini Mill. The turned feet press-fit into locating pockets on the base, and are fastened from underneath. The two diagonal feet have 14mm bosses on top, which mate with corresponding 14mm locating bores in the bottom HSG casting.
The underside: Since the parts needed to get flipped over anyways, I did some gratuitous pocketing on the bottom:
The painful measurement process paid off. The motors dropped into place perfectly:
Like the small dyno, the base of the big dyno is a huge slab of aluminum. I started out with a big optical breadboard I got for free last fall. It's a roughly 1'x3'x1" cast aluminum sheet, with a 2" grid of 1/4-20 holes in it. Somehow this plate was extremely warped, with roughly a 1.5mm height difference between the center and the edges, in the long direction. I set up the plate on the bridgeport, and faced the hole thing:
The plate was substantially longer than the x-axis travel of the mill, so I had to swivel the column around half way through to face the whole thing.
To fixture it, I machined a little step into each end. This way the step clamps hold it down hold right at the edges, and don't put any bending stress into the plate:
Here you can see the huge gap between the center of the plate and the table of the mill:
I was expecting the plate to continue warping as I machined it from residual stress in the material, but by some miracle it didn't. Once I faced the first side, it just stayed perfectly flat. I didn't even bother facing the underside, because nothing will be mounted to it.
Pile of chips post-facing:
I squared up all the edges as well, and gave the corners a healthy chamfer.
Here's the absorber mounted:
And a preview of the whole assembly. I still need to make the foot to space the torque sensor up appropriately. The first motor we plan on dyno-ing on this thing is the HSG, so we can squeeze every last drop of performance out of the Big Kart, but after that , the motor on the right will be swappable for any other motor which fits. The plate is mounted to the top of a cart by some rubber shock mounts to vibration isolate it.
In related news, the Big Kart is frighteningly fast now, thanks to the double-motors, Polychain-based drivetrain, and new lookup tables based on the stall data and better inductance measurements. Hopefully we'll get some decent videos of it, now that the weather's shaping up. Here it is after some thrashing by Michael
I did some data-gathering for Dane on a generic looking 48V 1800W brushless electric scooter motor widely available on ebay and aliexpress, paired with a 1500W E-bike controller.
The motor had basically no shaft to speak of - it has a left-hand threaded stud on the end, and 2 flats which engage with a stamped #25 chain sprocket. Since there wasn't enough shaft to grab onto with a collet, I made a "terrorist coupling", with three steel pins that engage with the sprocket teeth:
I plugged the analog output of the talk-to-everything board into the throttle connector so I could sweep throttle commands in an automated way. It was a little tricky to tune the throttle ranges, because of how the e-bike controller works. As far as I can tell, the throttle commands voltage, not current, until you hit the DC bus current limit. That means that at low-speed, the torque vs. throttle position curve is really steep: very small changes in throttle position mean huge changes in torque, thanks to the voltage-mode control. The motor is also capable of slightly more than the ~10 N-m the dyno is good for, so I had to carefully tune the throttle range so that the dyno could regulate speed.
Dyno-ing in progress:
Initially I put the dyno in inertia-simulation mode, and did a spin-up using a hand held twist throttle to see what the full-throttle performance was like. Data below ~1200 RPM was cropped because it was pretty noisy. This whole spin-up only lasted a few seconds so the plot is little rough. The motor is legitimately good for almost 2000 mechanical watts. Surprising given the 1500 watt rating on the motor controller. Efficiency is rather poor, topping out at around 80%.
The high-speed end of the torque curve is a little bit strange looking, and I don't have a good explanation as to why. Probably something to do with the internal hall sensors and commutation scheme of the controller.
After figuring out what throttle ranges worked at a range of speeds, I did a full automated sweep of speeds and throttle setpoints to get the full operating maps. Again, the full data is in the database. The e-bike controller wasn't set up for regen, so all the maps are 1st quadrant only.
Now that I have a good process for collecting data on the motor dynamometer, and the appropriate scripts for quickly processing the data, I put up a page dedicated to motor dyno data. You can also find it in the navigation bar up top. There's only one motor two motors on it right now, but it will slowly get populated as I get a chance to run more tests.
I'm not sure if anyone else will actually find this useful, but it seems like there's a growing number of people doing legitimate robotics and other cool stuff with hobby-grade motors, so I might as well share what data I've got.
I finished up the code for automatically generating and post-processing efficiency maps on the motor dyno. You give it a maximum speed, a maximum command vs speed, and number of points to sample in speed and command, and it auto-generates a time-stamped .csv file my dyno software can read. Then the dyno plays back the time series, and logs the data. To extract the points of interest, the log has a flag in it, which is set to 1 after each operating point has settled, and 0 the rest of the time. The post-processing script just finds all the intervals where the flag is 1, averages all the samples collected over that period, and combines them into one point. So each point on the efficiency map is from several seconds of data.
Here's a video clip showing part of the process. The motor being tested is a cheap knock-off of a Tiger Motor U8, at 22 volts, and 22 peak phase amps.
Here's the scatter plot of data points tested during the efficiency map:
And here's the data interpolated into a surface, in the classic efficiency map style:
I wouldn't read too much into the relatively low numbers (~74% peak efficiency), as this test was only at 22V and high peak current and these motors are good to spin much faster on more volts.
Also, some time soon I'm going to add a motor data page to the site, with whatever data I pull off the dyno on it, so keep your eye on the top bar. I figure it might eventually be a useful resource, to have a page with lots of electric motor performance curves, efficiency maps, etc. on it.
Here's the Talk-To-Everything Board. The idea is that I want to be able to plug arbitrary motor controllers into the motor dyno, and control them from the UI on the computer. There's an FTDI chip for USB to serial, with a digital isolator and isolated DC-DC converter, so that the computer is electrically isolated from whatever motor controller gets plugged in. My favourite STM32 is broken out to a CAN tranceiver, a small buck for 0-5V output, I2C, RC PWM, TTL Serial, differential 5V serial (like RS422), and SPI. Even if I don't end up ever using several of these, it wasn't much extra effort to break out more interfaces, so I figured I might as well.
I moved the 'Everything-Board, plus DAQ and other sensitive analog stuff into an aluminum box with shielded cables in, to fix some more noise problems. I also now have a big LEM closed-loop hall current sensor for measuring the buck output current.
Here's a look at the current user interface. Notice all the extra doodads for controlling some of the test-motor interfaces. I've also added "Profile Mode", which takes in a csv series of speeds, buck voltages, and test-motor commands with time-stamps, and plays them back on the hardware. This way I can easily automate cycles like efficiency maps.
I'm currently in the progress of designing a new buck converter from scratch, to replace the awful pile of Prius power electronics that is the current buck. Progress is slow, because I have very little experience with analog electronics and hardware controls (for regulating the buck voltage and current).
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.
Nominally I'm designing this controller for 200A, 50V operation, because that's all the dyno absorber can do. This should be very safely within the ratings of these transistors.
A tricky thing about designing a high current controller like this is designing a PCB that can actually handle that current. To make the controller as compact as possible, I designed it to use custom surface-mount busbar, which I waterjet cut out of copper plate and reflowed to the PCB. Another interesting feature of this transistor package is that it physically has a cutaway underneath the package between the legs. I'm using that space to route the busbar beneath the transistors, instead of next to them.
Here's a board from 3PCB and a pile of busbar. Although I didn't ask for gold plating on the PCB, I got it for no extra cost. Presumably my boards were tacked onto a big batch that was getting plated or something?
It took two tries to solder the bus bar. First time around, I tried clamping everything at once and baking it in an oven, but that ended up warping the board and turning out poorly. At Peter's suggestion, I soldered the busbars one-at-a-time, fixturing them with steel binder clips and heat-gunning them with solder paste underneath. This worked out beautifully:
After sanding off excess solder and oxidation:
Here's the power board populated with FETs, Allegro current sensors, gate pulldowns and gate zeners, and one 22 uF film cap per leg. After reading this paper, I decided to try out using just a small-ish set of film caps instead of the the huge pile of electrolytics I'm used to seeing.
Note the bus bar routed underneath the transistors:
Logic and gate drive stack on top of the controller, next to the capacitors. An STM32F446 does all the motor-control stuff. I know the F3 series are probably a better choice for motor control things, but I had a few F446's left lying around, and this way I could just port all my FOC code over from my small controllers with minimal editing.
The power supply section of this features 5 isolated 15V DC supplies - one for the low-side gate drivers, one for each of the three high-side gate drivers, and one one for the logic. The gates are driven by 2.5A gate drive optoisolators.
Bayley actually designed the power supply and gate drive section of this for different motor control project of similar power level, so I borrowed his design. A 555 generates a square wave, which is fed into the inputs of a dual inverting/non-inverting gate drive IC. The gate driver swings around the primary of a 6-winding transformer, the 5 other windings of which are rectified to generate the 5 isolated 15V supplies.
The gate drive IC driving the transformer gets extremely warm, but its power dissipation is still within spec, and it's now operated 10's of hours at least with no problems. When the controller gets mounted to a heatsink I'll make sure it gets some airflow too.
I used ethernet connectors for programming/serial and position sensor, because they're nice cheap, locking, small-footprint connectors. And they're matte black.
To get the controller working, I spent a few days figuring out how to generate complimentary PWM signals with software-defined deadtime. That was the only significant code change, though, other than re-doing the current loops as usual.
So far I've pushed the controller to 45V, 100 phase-amps entirely without drama. The transistors get a little warm. Here's what bus voltage looks like at ~80 phase amps. Note this is running of a bench supply with several feet of wire between the supply and controller. At 41 volts on the supply, the sharp spikes hit ~7.5 volts above nominal, and the bulk ripple is a couple volts.
Here are the Eagle files, if for some reason you want to build one of these: Power Board Logic Board