Good afternoon. I am implementing an SVPWM in arduino uno with a switching frequency of 5000 Hz.
The code seems to be functional, except for the output frequency: it should be 5000 Hz, but the measured signal is only 50 Hz.
The code is provided below. I first designed the SVPWM in PLECS and then translated the blocks into code, except for the triangle wave generator, which was provided by ChatGPT :
double Vdc = 26;
double Ts = 0.0002;
double Frads = 50;
double Amp = 1;
unsigned long clock_us = 0;
float t ;
double Sine1, Sine2, Sine3;
double Valfa, Vbeta, Angle, AngleRads, Vref;
double presec1, presec2, presec3, presec4, presec5, presec6, Sector, Mts, T11, T22, T1, T2 ,T0, T1T2T0, T1T0, T2T0;
double sin1, sin2 ,sin3;
double output1, output2, output3;
const float TRI_MAX = 1.066618e-2;
const float TRI_MIN = 0.933382e-2;
const float TRI_FREQ = 5000.0;
float tri = TRI_MIN;
float step;
bool rising = true;
unsigned long lastUpdate = 0;
const int N = 100;
const int pin1 = 3;
const int pin2 = 5;
const int pin3 = 6;
void setup() {
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
step = (TRI_MAX - TRI_MIN) / (N / 2);
}
void loop() {
// Onda Triangular
unsigned long now = micros();
unsigned long Ts1 = 1000000UL / (TRI_FREQ * N);
if (now - lastUpdate >= Ts1) {
lastUpdate = now;
if (rising)
{
tri += step;
if (tri >= TRI_MAX)
{
tri = TRI_MAX;
rising = false;
}
} else
{
tri -= step;
if (tri <= TRI_MIN)
{
tri = TRI_MIN;
rising = true;
}
}
}
// End Onda Triangular
t = now / 1000000.0;
Sine1= Amp*sin(2*PI*Frads*(t));
Sine2= Amp*sin(2*PI*Frads*(t)-(2*PI/3));
Sine3= Amp*sin(2*PI*Frads*(t)-(4*PI/3));
Valfa = (Sine1 - Sine2 * 0.5 - Sine3 * 0.5) * (2.0 / 3.0);
Vbeta = (Sine2 * (sqrt(3.0) / 2.0) - Sine3 * (sqrt(3.0) / 2.0)) * (-2.0 / 3.0);
Angle = atan2(Vbeta, Valfa);
AngleRads = Angle*(180/PI);
Vref = sqrt(Valfa * Valfa + Vbeta * Vbeta);
// Sector detection
if(AngleRads>0 && AngleRads <= 60){
presec1 = 1;
}else{presec1 = 0;}
if(AngleRads>60 && AngleRads <= 120){
presec2 = 2;
}else{presec2 = 0;}
if(AngleRads>120 && AngleRads <= 180){
presec3 = 3;
}else{presec3 = 0;}
if(AngleRads>-180 && AngleRads <= -120){
presec4 = 4;
}else{presec4 = 0;}
if(AngleRads>-120 && AngleRads <= -60){
presec5 = 5;
}else{presec5 = 0;}
if(AngleRads>-60 && AngleRads <= 0){
presec6 = 6;
}else{presec6 = 0;}
Sector = presec1 + presec2 + presec3 + presec4 + presec5 + presec6;
//times
Mts= sqrt(3) * Vref * Ts/Vdc;
T1 = (Mts * sin(Sector * PI/3 - Angle))*100;
T2 = (Mts * sin(-(Sector-1) * PI/3 + Angle))*100;
T11 = Mts * sin(Sector * PI/3 - Angle);
T22 = Mts * sin(-(Sector-1) * PI/3 + Angle);
T0 = ((-T11 - T22 + Ts)/2)*100;
T1T2T0 = T1+T2+T0;
T1T0 = T1+T0;
T2T0 = T2+T0;
switch((int)Sector) {
case 1:
case 6:
sin1 = T1T2T0;
break;
case 2:
sin1 = T1T0;
break;
case 5:
sin1 = T2T0;
break;
case 3:
case 4:
sin1 = T0;
break;
default:
sin1 = 0; // segurança
break;
}
switch((int)Sector) {
case 2:
case 3:
sin2 = T1T2T0;
break;
case 4:
sin2 = T1T0;
break;
case 1:
sin2 = T2T0;
break;
case 5:
case 6:
sin2 = T0;
break;
default:
sin2 = 0; // segurança
break;
}
switch((int)Sector) {
case 4:
case 5:
sin3 = T1T2T0;
break;
case 6:
sin3 = T1T0;
break;
case 3:
sin3 = T2T0;
break;
case 1:
case 2:
sin3 = T0;
break;
default:
sin3 = 0; // segurança
break;
}
//PULSE
if (sin1 > tri) {
digitalWrite(pin1, HIGH);
} else {
digitalWrite(pin1, LOW);
}
if (sin2 > tri) {
digitalWrite(pin2, HIGH);
} else {
digitalWrite(pin2, LOW);
}
if (sin3 > tri) {
digitalWrite(pin3, HIGH);
} else {
digitalWrite(pin3, LOW);
}
}


