# Space Vector PWM Help Needed

#### Jerryxm

##### Newbie level 6
I'm building a board to control a three-phase PMSM motor. I believe I have most of the control code implemented and working, except that my SVPWM algorithm generates a DC offset of 8v. I'm not sure what causes this and would like to eliminate it. As a comparison, I also implemented a straight PWM implementation that generates sine waves based on a lookup table, and looking at its output on an oscilloscope, the three sine waves are 120 degrees out of phase (as expected) and go down to 0v and up to close to the DC rail voltage. The signals generated by my SVPWM implementation look like textbook examples of SVPWM when I look at them on a scope (see attached scope shot), except that the center of the signals sit right at 8v. If I increase of decrease or decrease Iq, the span of the waves increases or decreases, but it's always centered on 8v. I'm not sure why this is--I'm not an expert on control theory or motor control--and I assume I need to get rid of this offset.

Can anyone help me understand the cause of the 8v DC offset and how to get rid of it? (assuming I do want to get rid of it.)

My SVPWM code is below. Input parameters are:

alpha, beta : converted from Iq, Id, and the rotor electrical angle using the inverse Park transform
theta: rotor electrical angle in radians
Vdc: DC rail in volts (12v in this case)
T: value in the period register of the timers used to generate PWM
Tu, Tv, Tw: outputs that are put into the PWM timer compare registers

The thing I'm most unsure about here is the calculation of the modulation index, which is used later to scale the PWM on times. Is my calculation of it correct?

Note: This code isn't optimized yet.

Code:
void svpwm(float alpha, float beta, float theta, float Vdc, float T, float *Tu, float *Tv, float *Tw)

{

float Vref, modulationIndex;
float Ta, Tb, T0, sinTheta;
uint32_t sector;

Vref = sqrtf((alpha * alpha) + (beta * beta));
modulationIndex = (Vref * PIOVER2) / Vdc;

/*
* Put theta in the range 0 - pi/3 (0-60 degrees) and determine which
* of the six sectors of the SV hexagon the angle lies.
*/
sector = 1;
while(theta > PIOVER3) {
theta -= PIOVER3;
sector++;
}

/*
* Ta and Tb are the on times the two sector endpoints used to synthesize the desired voltage.
* T0 is the time the (+++) and (---) states are active
* Tu, Tv, Tw are the times (in timer compare counts) the U, V, and W high-side MOSFETs are on.
*/
sinTheta = sinf(theta);
Ta = modulationIndex * (cosf(theta) - (ONEOVERSQRT3 * sinTheta));
Tb = modulationIndex * TWOOVERSQRT3 * sinTheta;
T0 = (T - (T * Ta) - (T * Tb)) / T;

switch(sector) {
case 1:
*Tu = T * (0.5f * T0);
*Tv = T * ((0.5f * T0) + Ta);
*Tw = T - (T * (0.5f * T0));
break;
case 2:
*Tu = T * ((0.5f * T0) + Tb);
*Tv = T * 0.5f * T0;
*Tw = T - (T * (0.5f * T0));
break;
case 3:
*Tu = T - (T * (0.5f * T0));
*Tv = T * (0.5f * T0);
*Tw = T * ((0.5f * T0) + Ta);
break;
case 4:
*Tu = T - (T * (0.5f * T0));
*Tv = T * ((0.5f * T0) + Tb);
*Tw = T * (0.5f * T0);
break;
case 5:
*Tu = T * ((0.5f * T0) + Ta);
*Tv = T - (T * (0.5f * T0));
*Tw = T * (0.5f * T0);
break;
case 6:
*Tu = T * (0.5f * T0);
*Tv = T - (T * (0.5f * T0));
*Tw = T * ((0.5f * T0) + Tb);
break;
}
}

Here's how I'm measuring the SVPWM waveforms with a scope in my original post. I've disconnected the motor from the control board and substituted the simple test fixture shown in the diagram below and have the scope probes connected to the test points indicated.

Last edited by a moderator:

#### KlausST

##### Super Moderator
Staff member
Hi,

maybe the DC offset is caused by the hardware.
The wavefrom looks good, so far.

But indeed: as long as all three outputs have the same DC offset it won´t harm the motor. It won´t be able to see the offset.

I don´t know where exactly you measured the signal, nor do I know the true amplitude. A schematic or at least a sketch would be helpful.

Klaus

#### Jerryxm

##### Newbie level 6
Hi Klaus. Thanks for adding the code tags. I'll remember to use them the next time I post code.

The scope capture I posted was measured using a test fixture shown in the second photo in my post and the amplitudes can be read in the scope shot (all three phases are referenced to the same ground point on the scope). The scope's ground leads were connected to the same ground the capacitors in the diagram are connected, so I'm measuring phase voltages rather than line-to-line or line-to-neutral voltages.

Unfortunately, the DC offset does seem to have some negative effect as when I replace the test fixture with a motor, the motor doesn't spin. In an earlier version of the code, I generated sine waves directly using a sine lookup table to generate three sine waves at 0 degrees, +120 degrees, and -120 degrees. With this arrangement, the motor spins very smoothly, quietly, and coolly. Looking at the output on the scope, I don't see any DC offset at all. Using SVPWM, not only doesn't the motor spin, it also draws a lot more current and gets quite warm.

Another issue with the DC offset is that it doesn't allow using the full range of DC voltage.

#### FvM

##### Super Moderator
Staff member
I presume you have half bridge drivers with DC-=0 and DC+=12V. Respectively the DC bias should be 6 V. You have apparently 8 V DC bias, thus an unwanted DC offset of 2 V. Things would be clearer if you show phase voltage U, V or W relative to DC- (GND).

You also don't show the motor wiring. We expect that it has three phase lines and no external star point connection.

Do you apply a frequency/voltage ramp when starting the motor? Otherwise it will probably not run.

#### KlausST

##### Super Moderator
Staff member
Hi,

again: the DC offset won´t harm motor function. If the motor does not spin, then this is a different error.
again: I still miss informations that simply can be shown with a sketch.
For example: are we talking about 8V on a 12V rail or 8V on a 600V rail ...

Klaus

#### Jerryxm

##### Newbie level 6
I presume you have half bridge drivers with DC-=0 and DC+=12V. Respectively the DC bias should be 6 V. You have apparently 8 V DC bias, thus an unwanted DC offset of 2 V. Things would be clearer if you show phase voltage U, V or W relative to DC- (GND).

You also don't show the motor wiring. We expect that it has three phase lines and no external star point connection.

Do you apply a frequency/voltage ramp when starting the motor? Otherwise it will probably not run.

The scope shot I posted shows the phase voltages U, V, and W relative to DC- (GND). What I'm having a hard time understanding is why the sine waves generated by SVPWM are offset by 8v. When I generate sine wave directly (e.g. not using SVPWM, but using lookup takes to generate sine waves independently for each motor phase, but 120 degrees out of phase with each other) there is no offset -- the bottom of the sine waves sit right at 0v.

This also happens on the Infineon board I used initially to test my code before I started building my own board. Here's the schematic for the Infineon board showing the half-bridges connected to the motor phases.

The MOSFETs are driven by gate drivers, which in turn are driven directly by the PWM outputs of a microcontroller.

Yes, I'm using a ramp function to start the motor. The motor runs fine when generating sine waves using lookup tables, but not when generating them with SVPWM.
--- Updated ---

Hi,

again: the DC offset won´t harm motor function. If the motor does not spin, then this is a different error.
again: I still miss informations that simply can be shown with a sketch.
For example: are we talking about 8V on a 12V rail or 8V on a 600V rail ...

Klaus

Hi Klaus. It's an 8V offset on a 12V rail (actually, I just measured the rail and it's a little higher than 12V -- it's around 14-15V).

#### KlausST

##### Super Moderator
Staff member
Hi,

if the rail is 14..15V then what "offset" do you expect.
I´d say 8V isn´t that bad.

What are R19..R14 for. I´d rather expect a 10k resistor...Usually you want to reduce capacitance at this node than to add some.

Klaus

#### Jerryxm

##### Newbie level 6
Here are two scope shots showing what the waveforms look like when I generate sine waves using a lookup table rather than using SVPWM. As can been seen, the waveforms extend down to nearly 0V. The first is for a high value of Iq and the second is for a lower value.

For the SVPWM case, if I decrease Iq, the peak-to-peak spread of the waveforms decreases, but they stay centered at an 8V DC offset.

#### KlausST

##### Super Moderator
Staff member
Hi,

so I´d begin with what`s the difference in code between sine and the modfiied sine?

you said that with sin you used a table.
But here I see no table. Why do you do it differently here?

Honestly I don´t understand all your calculations. ... how you calculate the amplitude (in PWM values) and how the offset.

Try a table.

Klaus

#### Jerryxm

##### Newbie level 6
I solved the problem that was preventing the motor from starting to run. Here's the story...

The motor I'm working with has an incremental quadrature encoder. When I was working on the non-SVPWM implementation I wrote code that established the initial electrical position of the rotor by energizing the high-side U phase MOSFET and the V low-side MOSFET, waited until the rotor stopped moving, and then zeroed the position counter. That worked fine when starting the motor with the non-SVPWM implementation (which generates three sine waves via table lookup) in either the clockwise or anti-clockwise directions, but it didn't work with the SVPWM implementation (the rotor moved slightly and then stopped).

To get the motor to spin with the SVPWM implementation, I had to modify the code that establishes the initial rotor electrical position by energizing the V phase high-side MOSFET rather than the U phase high-side. After this change, the motor will start and run in both directions. At the same RPM, the motor draws more current for the SVPWM implementation than the previous, sine table lookup implementation. I'm assuming this is due to either the 8V DC offset the SVPWM implementation generates or perhaps the rotor Iq axis isn't exactly 90 degrees ahead or behind the Id axis.

#### FvM

##### Super Moderator
Staff member
I'm assuming this is due to either the 8V DC offset the SVPWM implementation generates or perhaps the rotor Iq axis isn't exactly 90 degrees ahead or behind the Id axis.
I presume the latter. Bias voltage should have no effect on power consumption. For maximal undistorted output voltage, it would be however DC/2, 6V rather than 8V.

#### Jerryxm

##### Newbie level 6
I presume the latter.

I think you're probably correct.

What is the best way to establish the initial electrical rotor position on a motor with an incremental quadrature encoder? There's no absolute position reference, so finding the position of the poles of the rotor needs to be done when initializing the controller. I'm not sure the way that I'm doing it now is correct, or if yields a result anywhere near where the rotor magnetic poles really are.

Some help here would be appreciated.