so we have been struggling with a particular issue on our Motor controllers. Before i explain the issue in detail with pictures. Let me setup the context of the hardware we are using.

Motor controller:

Custom made dual channel BLDC controller with low side shunts on ChA and ChB using DRV8302 gate driver IC's. Uses NTBGS2D5N06 Mosfets and 5mOhm sense resistors with the DRV8302 Gain set to 10 V/V.

Motor Specs:

24V 30 poles 0.560Ohm 0.850uH 200RPM with Incremental encoder (4096 PPR)

Controller Configuration:

STM32F429 with TIM1 and TIM8 being used in center-aligned mode at a switching frequency of 30Khz.


The controller works fine in openloop configuration, where based on the set RPM the phase is incremented during each ISR routine. Below is the screen shot of the same.

enter image description here

Issue arises in RPM control, in which over time Vd starts decreasing from the initial value (all tests done in unloaded conditions). RPM controller is a simple PID controller with Kp = 0.004, Ki = 0.006 and Kd=0.0001.

volatile float error = static_cast<float>(set_point.targetRPM - set_point.measuredRPM);

volatile float pTerm = (error * pGain);
volatile float dTerm = (((error - prevError) * dGain )/microsPID_delta);
prevError = error;

plantOutput = pTerm + dFiltered + iTerm;
iTerm += (error * iGain * microsPID_delta);
math::truncateAbs(iTerm, 1.0f);
plantOutput *= MOTOR_CURRENT_MAX;

If left alone to run longer eventually Vd and Vq cross-over when (vq - vd) > (Vbus/sqrt(3)). Below is the screenshot of RPM Mode

enter image description here

Vd starts at ~ 0V and then gradually becomes more negative. This phenomena is speed and direction dependent. As speed increases Vd's slope increases. Things we have tried to fix the issue.

  1. change the switching frequency - tried 20Khz, 10Khz, 5Khz. Vd still falls, although much slower

  2. Add phase shunt resistors to improve current sensing @ low currents. Doesnt fix the issue.

  3. Check if the encoders and their code is buggy - works without issues

  4. Change Current controller and rpm controllers PID params - doesnt effect the issue

  5. Use higher Resistance and inductance values for cross-coupling removal to check if vq is being coupled to vd causing id to rise and eventually driving the D-axis current controller to make Vd more and more negative. Not the issue.

  6. Make Integral term of the rpm controller zero - doesnt fix the issue.

The only hack that has stopped the Vd falling issue is when in RPM mode we dont use encoder feedback for phase rather use the openloop phase where depending on the set RPM a constant delta is added each iteration.

Since I'm not an FOC expert and dont have an indepth understanding of Motors and Field control. I'm unable to understand the problem here. Perhaps it could be a a very benign deisgn oversight from our end or could be a timing related issue between the current controller and rpm controller (current controller runs at 15Khz (dual motors hence 15Khz per motor) and rpm controller runs at 3 Khz).

Please feel free to ask questions to gain a better understanding of the situation and guide us in the right direction.


  • 1
    \$\begingroup\$ This FOC is a very complex problem, there's literally hundreds of critical lines of code where problems can occur. That said, the obvious candidate from your description is that the encoder counts per revolution is off by one and you're not zeroing every revolution, which would cause a gradual drift. What FOC library are you using? There are many available. \$\endgroup\$ Nov 11, 2022 at 14:49
  • \$\begingroup\$ There is a specialized forum for motor controllers. The people running it are well versed and can probably help. xesc.org. It sounds like you are not using an observer to estimate phase. How do you get the count from the encoder? Is it over SPI or something like that, or is the encoder directly wired to the processor? \$\endgroup\$
    – user57037
    Nov 12, 2022 at 6:23
  • \$\begingroup\$ The usual way FOC is implemented is that there is are two PIDs, one for Id and one for Iq. The output of those is the output Vd and Vq which are fed to the SVM module. When speed control is desired, a second PID is closed around the Iq and Id PIDs. Generally, Id is kept at zero unless you are running faster than the base speed. Maybe you should add a signal block diagram to your question. \$\endgroup\$
    – user57037
    Nov 12, 2022 at 6:25

2 Answers 2


In your top images of the voltage and current waveforms it appears that every 7 periods there is some discontinuity. At steady state RPM these voltage waveforms should be perfectly sinusoidal. You might consider plotting the waveforms versus position. I would expect the Park/Clarke transformations that you are using to be correct. Perhaps you have an issue with how you are passing the angular variable into this function to compute the transformation. See if you can dig deeper into what is causing that discontinuity in open loop.


@DavidMolony Thanks for the suggestion. Didnt realise encoder drift could be an issue, our first suspect was phase and we checked the phase by plotting it in real time and noticed that it was working fine, we were mostly looking for discontinuities or irregularities in phase, never occurred to us that small errors were getting accumulated in the counter. Changing encoder code to not use an accumulated counter rather a counter which is reset every iteration solved the issue.

@mKeith we are using the standard FOC block structure hence didnt feel the need to add it here. And the encoders are directly wired to the processor, we are using stm32's encoder interface timer modules for counting pulses.

@Real Magnetics The plot shown is sent over serial, a buffer is filled with 2000 samples from the ISR and then sent over serial at once for plotting. Hence the discontinuity every ~2000 samples.

  • 1
    \$\begingroup\$ Glad you solved your problem. Sometimes people do things completely wrong or skip a step or whatever. That is why I ask things like this. There are slight variations on "standard." But since you fixed the problem, not much point in dwelling on this issue. Feel free to accept your own answer. \$\endgroup\$
    – user57037
    Nov 13, 2022 at 6:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.