-
Notifications
You must be signed in to change notification settings - Fork 1
Smooth Waves When Changing Frequency in Vector Control
Pulse-Width Modulation (PWM) waves can produce a larger reference sinusoidal wave with variable frequency. For the output to be smooth, the next reference wave must have an offset so that it continues from the same point the previous reference wave left off.
The maths behind it is that
However, since there are two solutions, we must check the solution we have is the one which the offset creates a wave which has a matching gradient. This ensures a wave is smooth, and even though the frequency changes there are no sudden changes in direction. To do this we take the derivative of the first function
and the second one
Since we know
The expression we check for the old function is
If they are the same sign, then we are using the correct solution, if not, we must take the second solution, which is calculated as
Now we have the correct value for
Then just return that value.
double new_offset(long time, float old_freq, double old_offset, float new_freq) {
double new_offset = asin(sin(old_freq*MULTI_CONST*time + old_offset));
if (cos(old_freq*MULTI_CONST*time + old_offset) * cos(new_offset) < 0) {
new_offset = M_PI - new_offset;
}
new_offset -= new_freq*MULTI_CONST*time;
return new_offset;
}
(for my memory next year)
old_freq = freq;
time_abs = HAL_GetTick()*1000;
loop_timer = time_abs + TRIANGLE_TIME / 2; // goes from the current time to half the triangle wave
multiplier = MULTI_CONST*freq;
offset = new_offset(time_abs, old_freq, offset, freq);
t = time_abs * multiplier; //scale the value of time period down to (0,2pi) range
PWM_A = TRIANGLE_TIME * amplitude * sin(t + offset); //calculate pulse duty for phase A
PWM_B = TRIANGLE_TIME * amplitude * sin(t + 0.6666 * M_PI + offset); //for phase B
PWM_C = TRIANGLE_TIME * amplitude * sin(t - 0.6666 * M_PI + offset); //for phase C