Optimizing moteus FET drive strength

The moteus controller uses a DRV8323 smart driver IC to drive the power MOSFETs as well as provide various safety functions. One of the capabilities it has which has so far been unexplored in moteus is its ability to control the drive strength and dead time through software configuration.

In a switching power supply or switching motor inverter, MOSFETs are arranged in a half bridge configuration. Depending upon the type of converter, one or more half bridges are used (3 phase inverters like moteus use 3 of them). Each “half bridge” has two MOSFETs, one connected between positive power and the output terminal, and the other connected between the output terminal and ground.

Power MOSFETs typically have relatively large gate capacitance, so to change their state quickly requires a lot of current. Additionally, you never want both MOSFETs conducting at the same time, otherwise current would flow straight from the supply to ground, called “shoot through”. Thus the driver has a configurable “dead time” which enforces that both are off for at least that long when switching (currents flow through the body diodes of the MOSFETs during this state).


Selecting these parameters is a balancing act. If the drive current is too low, the MOSFETs take a long time to turn on and off, which means they spend more time in a high resistance state. At some point however, higher drive currents don’t make the MOSFETs switch any faster, and just burn more power in the driver without any benefit. Similarly for the dead time, if it is too low this will result in shoot through, and if too high, it will result in current flowing through the body diodes for longer, which is much less efficient.

Until now, I hadn’t done any real optimization of these parameters, aside from ensuring the system was functional within a safety margin. In advance of some other to be announced developments, I decided to take another look.

To make a test, I set up a moteus controller with a test motor, but set up so that there was no thermal connection between the motor and the controller, and that the controller was not heatsinked at all. That would allow me to more easily determine how much heat was coming from the controller itself. Then, for various supply voltages, I commanded a fixed D phase current with just enough Q phase voltage so that the motor gently spun around. This ensured that all 3 of the half bridges were used equally. Then, I waited until things had reached thermal equilibrium, and used my DIY thermal board inspector, to measure the temperature of the motor windings, FETs, and the DRV8323.

With that test methodology in hand, I was able to search and locate the optimal drive strength, and discovered that I can use the smallest available dead time with no problems.

MeasurementOld SettingsNew settings
DRV8323 @ 24V / 8A phase current73C69C
DRV8323 @ 32V / 8A phase current86C78C
FETs @ 24V / 8A phase current64C56C
FETS @ 32V / 8A phase current74C61C
Change in thermal equilibrium with no heatsinking

So, a nice win, especially at higher input voltages. The updated settings are in git master now, and will soon be in a new release.

New moteus firmware release, 0.1-20200822-1

I’ve posted a new release of the firmware for the moteus brushless controller to github!

This release has a number of minor improvements in the host tools (for which there continue to be no distributed binaries, you get to build from source). The biggest improvement in the firmware is the improved low-torque operation as documented here and here. If you have any questions or want help upgrading, hop into discord at #moteus and ask!

Up-rating the moteus phase current

When I first posted the moteus controller up for sale, the specifications I listed were based on the design characteristics and the testing I had conducted up until that point. Specifically, the peak phase current was just the maximum that I had verified was safe to operate with.

In the interim, I’ve done a fair amount more testing and have concluded that the controller can safely drive higher phase currents than initially posted. For now, I’m increasing the peak phase current to 100A both on the specification sheet and in the default firmware configuration of all newly shipped boards. If you already have a moteus controller and want to take advantage of the higher phase current, chat us up on the mjbots discord and we’ll show you how.

moteus r4.3 controller at mjbots.com

Measuring torque ripple

Recently I described some changes I made to improve the low speed torque ripple of the moteus controlle. I also built a dynamometer. I decided to use the dynamometer to quantify how much things had improved with the torque ripple, and to see how much room for improvement was left with any anti-cogging implementation.

Dynamometer script

Here, the test script is relatively simple. I have the “fixture” controller sweep at a very low velocity (0.01Hz) through a bit more than one full revolution using a relatively high I term in the PID controller to ensure that it really holds that position no matter what external torque is applied. Then, the “device under test” controller is just commanded either to be powered off, or in position mode with a pd gain of 0 and a feedforward torque. Then I can just measure the result from the torque transducer while this sweeps through a full revolution, and correlate the measured torque with the encoder position.


For these plots, I subtracted out the DC offset to just concentrate on the ripple and not scaling factor errors. Here’s the plot from the pre-fixes controller:

In these plots, the higher torque values are displayed in lighter colors to make it easier to see the values at low torque. Also, the standard deviation and peak-to-peak values are rendered in the lower right hand corner. Before any fixes, when the controller was off (i.e. completely unpowered), there was about 0.026Nm of peak-to-peak ripple, however, when turning on the controller and commanding 0 torque, that jumped up to a 0.047 Nm peak-to-peak.

Now for the post-fix plot:

Post fixes, the torque ripple at all the tested torque levels is nearly indistinguishable from the torque of the completely unpowered motor, which is what we want to see!

STM32G4 ADC and low-torque operation

Recently dlickindorf pointed out in the mjbots discord that he was having problems with very low torques on his large PMSM hobby-grade motor. While moteus doesn’t have any anti-cogging support yet, it should still be capable of driving motors such that the unexpected torque isn’t much worse than the baseline cogging torque of the motor. However, he was seeing much worse behavior with controlling to 0 current, as much as a full percent of the maximum torque of the motor.

Needless to say, I wanted to try and understand the behavior and figure out how to make it better. I was able to reproduce the problem locally, so that was a good start. It was easiest to see when commanding a position with a low maxmum torque. Say on a 8108 motor, with 0.05 N*m maximum torque, the cogging-like torque was high enough that the position control could get stuck in a local minima far from the control point.

In other experiments with higher torque, the switching noise because audibly “squirrely” at certain electrical theta angles. One often occurred at a 0 theta pre-magnetic offset compensation, and another appeared when one phase current was near maximum and the other two phase currents were opposite sign but near equal magnitude.

Calibration smoothing

When the moteus controller is calibrated, it calculates an offset between the electrical commutation angle and the magnetic encoder not just as an average, but at 64 separate points in the revolution of the magnetic encoder. This allows the calibration to take out some of the effect of magnets that are not perfectly axis-aligned with the encoder.

However, when calculating the moving average of the offset value, I neglected to take into account the fact that the encoder wraps around between 0 and 2*pi, and those ends of the offset curve were smoothed independently. If the calibration was somewhat steep in that particular window, it resulted in a discontinuity in the offset curve, which resulted in high frequency noise when controlling near that position.

That problem was relatively easy to solve, by just filtering in a circular domain.

Current noise

The next issue was dealing where the phase current became obviously very noisy. Ultimately I tracked this down to a combination of mis-configuration of the STM32G4 ADC peripheral and coupling between the digital and analog domains.

The latter is the easiest to cover. In the core FOC loop, I use a debugging pin that goes high during the loop to be able to easily identify how long it takes on an oscilloscope. The problem was that I was starting the ADC conversions, then immediately switching that pin. That results in a large enough current transient either within the chip or on the PCB that the analog samples have significant noise introduced. Solving that was easy enough by just moving the debug pin assignment to after the ADC samples are completed.

The former was a result of bugs introduced when I ported the moteus code from the STM32F4 to the G4. The ADC peripherals are significantly different in the G4 (more like the F3 peripherals) and the configuration registers are almost entirely different. At one point several months ago I was trying to configure the sample time for the ADCs but not actually doing so at all. When I resolved that issue, I didn’t look at the resulting sampled waveforms very closely and didn’t notice that the current waveforms were still pretty bad. This was compounded by a further issue. The moteus has 3 current shunts, but it was only sampling two of them and inferring the 3rd by Kirchoff’s law.

Here’s a plot showing the 3 current values as the voltage phase was advanced through a few cycles:

The biggest problem here was that the ADC prescaler was too low for the system clock I was running. Once fixing the prescaler, and making a few additional changes, the current waveforms now look like:

So yes, there is now much less unusual discretization going on across all 3 current channels.

Final results

And now for a video showing the final result:

Testing alternate magnetic encoders

The moteus controller, uses an absolute magnetic encoder to sense the position of the rotor and thus be capable of field oriented control FOC of brushless motors. To date, all the iterations of the controller have used the AS5047P encoder from ams. This is relatively common, works fine over SPI and hasn’t caused any problems. While investigating some other issues, I decided to take a stab at trying some alternate encoders. First, I tried the AS5047U, which is the same basic encoder, but incorporates a digital filter. I also tried the MA732, from Monolithic Power, which uses a different operating principle and also includes a digital filter. The plus side of the MA732 is that it reports full 16 bit values, even if not all of them provide a lot of value.

Testing the MA732 wasn’t as easy as the AS5047U, since it doesn’t have the same pinout as the AS5047 family. Fortunately, the footprint is smaller, so I was able to make my first “castellated” adapter board:

It is from oshpark — I had to hand dremel the edges to get all the vias exposed. Since it was a one-off, I didn’t worry too much about getting perfect alignment when soldering it up. Here’s a microscope image of the side with the best alignment.

And finally with the MA732 installed:

It worked the first time, although I had to tweak the code slightly to use the alternate SPI protocol of the MA732. I’ll write up the results in a later post.

Initial dynamometer assembly

Earlier I showed off a torque transducer and the calibration fixture I used for it. I’ve now got enough assembled to make an entire dynamometer:

This has the torque transducer on one end, coupled to the “fixture” moteus controller through a bearing support. Then that is connected via a 3d printed coupler to the “device under test” moteus controller, which is hard mounted to the base plate. Any net torque between the two controllers will be coupled back to the transducer resulting in a measured torque.

I mounted it all to a nicely machined fixture plate I got from ebay. It’s flexible enough that I can build one for the qdd100 on it as well, although I might just get an entire second setup so that I can leave them both assembled all the time.