There has been some previous work done on the Prius inverter; this fellow here has a fairly extensive teardown of the assembly, complete with glamour shots of the gooey innards of the brick. I'll supplement his information with the following:
- The brick has significant internal propagation delays. At 20KHz, anything under 20% duty cycle is clamped to zero, and anything over 80% duty cycle is clamped to 100%.
- The internal power supplies expect a fairly low-impedance source; if your brick doesn't want to turn on check your power connections.
- The logic going into the brick is inverting; enable needs to be pulled low to turn on the phases, and the phases are HIGH when the inputs are low.
- The current sensors are 400A and 200A, respectively.
The first step was to build a board to interface with the module. A bit of Eagle layout work gave the following board and schematic:
The board is Arduino-shaped, but is actually meant to mount atop one of these:
An STM32F4 Nucleo, part of ST's latest attempt to push their high-performance ARM microcontrollers and actually a pretty good one at that. The hardware pins are Arduino-compatible, and the board can be programmed via the Mbed online IDE. Sure, their libraries are as slow as balls, but even with the overhead of the Mbed libraries the Nucleo still has about 10x the performance of an Arduino, not to mention all-important hardware floating-point support.
The board should be self-evident - X5 is a throttle input, X2 is hall sensors, X1 is 12V power, X3 and X4 control the two halves of the Prius brick (remember, there are two controllers in the brick!) in parallel, and X6 is a quick-and-dirty resistor-divider based input for the current sensors.
We have a board - firmware was next. You can download the firmware package here. A quick code walkthrough follows.
Motor commutation is interrupt-based, with throttle polling and (in the future) the current loop runnin in the main loop. Math is done in floating point thanks to the STM32F4's hardware FPU.
The commutate routine is called once every sensor change. It converts the hall sensor reading to a position estimate (in intervals of 60 degrees) and stores it. It also zeroes the ticker that is used for position interpolation, and updates the motor speed estimate (motor->last_time). In addition, the code also tries to detect and prevent jitter at the hall sensor transitions by maintaining forwards rotation of the motor when possible, which is crucial in preventing commutation misses.
The dtc_update routine is called at regular intervals (in the default firmware, 5KHz). It does two things: measure the time elapsed since the last commutation (motor->ticks += 1.0f) and update the duty cycle via a table lookup.
In its current state the firmware isn't really production-ready; the lack of current control makes it too unwieldy for use on large vehicle, but it should at least get us off the ground for further testing.