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.
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.
[moderator action: added CODE tags]
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.
[moderator action: added CODE tags]
Last edited by a moderator: