La commande MLI (Modulation de Largeur d’Impulsion) de type sinusoïdal sPWM est largement utilisée dans la commande des convertisseurs (AC/DC, DC/AC, AC/AC, etc.). Elle permet de synthétiser un signal qui s’approche du signal sinusoïdal à partir d’un signal tout ou rien (signal carré). En effet, un signal carré est une combinaison linaire d’une multitude des harmoniques (f0, 2f0, 3f0,…, nf0). Un signal carré est simple à générer via les composants de puissances. En revanche, il n’est pas efficace en termes du rendement et pertes dus aux harmoniques secondaires. Le transfert de puissance est maximale lorsque le signal est constitué d’une seule harmonique (sinus pur).
Les aspects théoriques de la modulation MLI sont abordés dans le projet onduleur monophasé. Concernant l’onduleur triphasé, il suffit de générer trois sinusoïdes décalées de 60°. La technique consiste d’utiliser un seul tableau pour les phases contenant les échantillons d’une demi période du signal sinusoïdal. Ensuite, utiliser trois indices décalés les uns par rapport aux autres de 60°. Si le tableau est constitué de N échantillons, alors le décalage 60° est équivalent à N/6 échantillons. Durant l’initialisation des indices, on définit : I_Phase1=0, I_Phase2=N/6 et I_Phase3=2*N/6. Voir le tuto pour plus de détails.
/*
* Commande Symétrique : SetCMD1() & SetCMD2()
* Commande Décalée : SetCMD3() & SetCMD4()
* Commande PWM(MLI) : Voir le programme
*/
#define Tr11 22 // Transistor 1/Bras 1
#define Tr12 23 // Transistor 2/Bras 1
#define Tr21 24 // Transistor 1/Bras 2
#define Tr22 25 // Transistor 2/Bras 2
#define Tr31 26 // Transistor 1/Bras 3
#define Tr32 27 // Transistor 2/Bras 3
#define T0_us 333 // Période de l'onduleur (Symétrique) : T=6*T0 (µs)
// Période de l'onduleur (Décalée) : T=12*T0 (µs)
// sPWM: Période d'incrémentation du Timer
// sPWM: Période globale T=2*N*T0_us => F=1/F: Fréquence de l'Onduleur
/* Params sPWM */
#define N 64 // Niveaux de l'onduleur : Nombre d’échantillons (format 2^n)
#define TimerStep 13 // Pas d'incrémentation du Timer rapide (>>1)
int Trans[6]; // Ou bien PORTA
unsigned long MedSine[N];
unsigned long TimerSPWM=0;
unsigned long i_sin[3]={0,0,0};
bool sPWM_l[3]={false,false,false};
bool sPWM_r[3]={true,true,true};
bool sinePolar[3]={false,false,false};
double sine_val=0.0, A=0.0;
int Nbit=0; // Amplitude du signal sinusoïdal 2^8
void setup()
{
// Pinout
Trans[0]=Tr11; Trans[1]=Tr12;
Trans[2]=Tr21; Trans[3]=Tr22;
Trans[4]=Tr31; Trans[5]=Tr32;
for (int i=0;i<6; i++)
{
pinMode(Trans[i], OUTPUT);
digitalWrite(Trans[i], LOW);
}
// Ou bien: Init du port A en sortie
//DDRA =0xff; PORTA=0x00;
// Codage binaire de l'amplitude
Nbit=(int)round((log((float)N)/log(2.0)));
// Init Timers // Déphasage de 60°/Bras (60°=>T/6)
i_sin[0]=0; // Bras 1 - 0°
i_sin[1]=round((float)N/6.0); // Bras 2 - 60°
i_sin[2]=round(2.0*(float)N/6.0); // Bras 3 - 120°
// Génération du signal sinusoïdal : 1/2 Période (2*N échantillons/période)
A=(double)(pow(2.0,(double)Nbit)-1.0);
for (int i=0; i<N; i++)
{
sine_val=A*sin(PI*(double)i/(double)(N));
MedSine[i]=(int)(abs(floor(sine_val)));
}
// Affichage
Serial.begin(9600);
pinMode(3,OUTPUT);
}
void loop()
{
/*
SetCMD1(Trans);
SetCMD2(Trans);
SetCMD3(Trans);
SetCMD4(Trans);
delayMicroseconds(T0_us);
return;
*/
/*
delayMicroseconds(11);
digitalWrite(3, sinePolar[0]);
*/
// Prévisualisation des signaux du Bras 1 + sin(t)
/*
Serial.print(MedSine[i_sin[0]]); Serial.print(",");
Serial.print(i_sin[0]); Serial.print(",");
Serial.print(A*sPWM_l[0]); Serial.print(",");
Serial.println(-A*sPWM_r[0]);
*/
// Visualisation des signaux de l'onduleur
/*
Serial.print(sPWM_l[0]+0); Serial.print(",");
Serial.print(sPWM_r[0]+1); Serial.print(",");
Serial.print(sPWM_l[1]+2); Serial.print(",");
Serial.print(sPWM_r[1]+3); Serial.print(",");
Serial.print(sPWM_l[2]+4); Serial.print(",");
Serial.println(sPWM_r[2]+5);
*/
// Incrémentation du Timer: Compteur rapide (signal triangulaire)
TimerSPWM+=TimerStep;
if (TimerSPWM>N) TimerSPWM=0;
// Génération de la commande
for (int i=0; i<3; i++)
{
// 1. Incrémentation du Timer du signal : Compteur long (signal sinusoïdal)
i_sin[i]+=1;
if (i_sin[i]>N) i_sin[i]=0;
// 2. Inversion de la polarité de la période
if(!i_sin[i]) sinePolar[i]=!sinePolar[i];
// 3. Génération des signaux PWM
if(sinePolar[i]) // Période (+)
{
sPWM_l[i] =MedSine[i_sin[i]] > TimerSPWM;
sPWM_r[i] =false;
}
else // Période (-)
{
sPWM_l[i] = false;
sPWM_r[i] =MedSine[i_sin[i]] > TimerSPWM;
}
}
// Envoie des signaux au Port A
PORTA=(B00000001*sPWM_l[0])+ (B00000010*sPWM_r[0])+
(B00000100*sPWM_l[1])+ (B00001000*sPWM_r[1])+
(B00010000*sPWM_l[2])+ (B00100000*sPWM_r[2]);
}
void SetCMD1( int *pins)
{
static int I=0;
const bool Cmd[6][6]={{0,1,1,0,0,1},
{1,0,1,0,0,1},
{1,0,0,1,0,1},
{1,0,0,1,1,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0}};
for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++; I%=6;
return 0;
}
void SetCMD2( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[6]={B00011001,
B00101001,
B00100101,
B00100110,
B00010110,
B00011010};
PORTA=Cmd[I];
I++;
//I%=6; // Fréquence: +
//I=I*(I<6); // Fréquence: ++
if (I>=6)I=0; // Fréquence: +++
return 0;
}
void SetCMD3( int *pins)
{
static unsigned char I=0;
const bool Cmd[12][6]={
{0,1,1,0,0,0},
{0,0,1,0,0,1},
{0,0,1,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,1,0,0},
{1,0,0,1,0,0},
{0,0,0,1,1,0},
{0,0,0,1,1,0},
{0,1,0,0,1,0},
{0,1,0,0,1,0},
{0,1,1,0,0,0},
};
for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++;
if (I>=12)I=0;
return 0;
}
void SetCMD4( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[12]= {
B00011000,
B00001001,
B00001001,
B00100001,
B00100001,
B00100100,
B00100100,
B00000110,
B00000110,
B00010010,
B00010010,
B00011000
};
PORTA=Cmd[I];
I++;
if (I>=12)I=0;
return 0;
}
4 réponses sur « Projet Onduleur Triphasé #4: Commande sPWM (MLI) »
Bonjour, merci beaucoup pour ce travail magnifique..
Je me demande si vous pouvez nous donner le code arduino d’un onduleur monophasé.
Merci
Bonjour, voila série des projets ici: https://www.electronique-mixte.fr/projet-arduino/
Bonjour
Merci pour ces tutos que je trouve très bien faits.
Pourquoi le déphasage entre les 3 bras (I_Phase1,2,3) est de 60° alors qu’en tri les phases sont déphasées de 120°.
Je dois fabriquer un onduleur en tri pour produire du 115V 400 Hz et vos tutos constituent une tres bonne base de départ.
Merci !
Bonjour, avec plaisir. Le déphasage des signaux de commandes est diffèrent de celui des phases! Essaye d’observer l’ensemble des tutos depuis le début pour plus d’explications.