Savoir implémenter une commande générique polyphasée
Savoir synchroniser son code avec une horloge externe
Savoir implémenter la commande MLI ou sPWM (PWM de type sinusoïdal)
Savoir implémenter la commande décalée (deux techniques)
Savoir le schéma d’un onduleur triphasé
Savoir les caractéristiques d’un onduleur
Savoir choisir les transistors de la partie puissance
Savoir commander un onduleur triphasé
Savoir implémenter la commande d’un onduleur triphasé
Savoir augmenter les performances de son code & améliorer la fréquence maximale de l’onduleur
Etc.
Applications
Commande des Machines polyphasées
Réseau polyphasé
Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
Variateur de vitesse des machines asynchrones
Etc.
Principe de la synthèse de la commande
Réseau Triphasé (N=3)
Réseau 4-Phases (N=4)
Réseau 5-Phases (N=5)
Stratégie de la commande
Voir le tuto pour les détails techniques
Programme Arduino
La fonction getCmd()
int getCmd(unsigned long *cmdOut, int n_0, int numphase)
La fonction getCmd() permet de synthétiser la commande de l’onduleur en fonction de nombres de phases. Elle prend en entrée le nombre de phases (numphase), un tableau vide et sa taille. Puis, elle renvoie le même tableau rempli et le nombre de séquences dans le tableau. On fait appel à la fonction une seule fois, dans la fonction setup().
intgetCmd(unsignedlong*cmdOut,int n_0,int numphase){int n_out=0;int i,j;unsignedlong SyqT1=0x00000000, SyqT2=0x00000000, Syq0=0x00000000;//32-bits if((numphase<=1)||(numphase>15))return;for(i=0;i<n_0; i++) cmdOut[i]=0;/***************************************************//*********** Monophasé - Cas particulier ***********//***************************************************/if(numphase==2){
cmdOut[0]=0x00000001;//Serial.println(cmd[0], BIN); //1:B01
cmdOut[1]=0x00000002;//Serial.println(cmd[1], BIN); //2:B10
n_out=2;return n_out;}/***************************************************//********************* Polyphasé *******************//***************************************************/// A. Génération de la séquence principale
n_out=2*numphase;
SyqT1=0x00000000; Syq0=0x00000001;for(j=0;j<numphase; j++){
SyqT1|=Syq0;
Syq0= Syq0<<1;}
SyqT2=SyqT1<<(numphase);// B. Génération des séquences binaires unsignedlong T1i_B0, T2i_B0;unsignedlong T1i[numphase], T2i[numphase], T12i[n_out];for(int j=0;j<numphase; j++){
T1i[j]=0; T2i[j]=0;}
T1i[0]=SyqT1;T2i[0]=SyqT2;//Serial.print(T1i[0], BIN); Serial.print(" , "); Serial.println(T2i[0], BIN);for(j=1;j<numphase; j++){// 1. Extraction du bit b(0)
T1i_B0=(0x00000001&SyqT1);
T2i_B0=(0x00000001&SyqT2);// 2. Décalage à droite
T1i[j]=SyqT1>>1;
T2i[j]=SyqT2>>1;// 3. b(n-1) =b(0)
T1i[j]|=T1i_B0<<(n_out-1);
T2i[j]|=T2i_B0<<(n_out-1);// 4. Mise à jour des séqs Init
SyqT1=T1i[j];
SyqT2=T2i[j];}// Combinaision des tableaux int ii=0, jj=0;for(j=0;j<n_out; j++){if(j%2==0){
T12i[j]=T1i[ii];
ii++;//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);}if(j%2==1){
T12i[j]=T2i[jj];
jj++;//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);}}// C. Génération des séquences finales
Serial.println("****************************");
Serial.println("T1|T2|T3|T4|T5|T6|T7|T8|T9|... ");
Serial.println("****************************");unsignedlong cmd_i=0;for(i=0;i<n_out; i++){
cmd_i=0;for(j=0;j<n_out; j++)cmd_i|=(((T12i[j]>>i)&0x1)<<(j));
cmdOut[i]=cmd_i;for(int k=0;k<32;k++)Serial.print(((cmd_i>>k)&0x1));
Serial.println("");}
Serial.println("****************************");return n_out;}
La fonction setCmd()
void setCmd(unsigned long *cmdOut, int n_0)
la fonction setCmd() sert à transmettre la commande aux ports de sorties. Elle prend en entrée le tableau de commande généré par la fonction getCmd(), puis elle envoie une séquence par itérations de la boucle. La fonction doit être intégrée dans la boucle principale loop() ou dans une routine d’interruption. Elle peut transmettre la commande via 4 ports de 8-bits (PORTA, PORTB, PORC et PORD) au maximal (commande avec 15 phases ==> 32-bits). Ci-dessous la déclaration et la définition de la fonction.
voidsetCmd(unsignedlong*cmdOut,int n_0){staticint K=0;// Commenté les lignes non utilisées
PORTA=cmdOut[K]&0x000000ff;// (0) -(1*8-1) --LSB//PORTB=(cmdOut[K]>>8) &0x000000ff; // (8) -(2*8-1) //PORTC=(cmdOut[K]>>16)&0x000000ff; // (16)-(3*8-1) //PORTD=(cmdOut[K]>>24)&0x000000ff; // (24)-(4*8-1) --MSB // Affichage du contenu des ports sur 8-bits (A commenté) /*
for (int k=0;k<8;k++) Serial.print(((PORTA>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTB>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTC>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTD>>k)&0x1));Serial.print(",");
Serial.println("");
*/
K++;if(K==n_0) K=0;}
Le programme complet
/*
* Algorithme de la commande Symétrique Générique
* La commande peut etre codée sur 32 bits (15 Phases Maximales)
* via 4 ports sur 8-bits (µC 8-bits)
* (ou bien un bus sur 32-bits (µC 32-bits))
*
* PORTA: de (0) à (1*8-1) --LSB
* PORTB: de (8) à (2*8-1)
* PORTC: de (16) à (3*8-1)
* PORTD: de (24) à (4*8-1) --MSB
*
*/#defineT0_us333// Période de l'onduleur (Symétrique) : T~n*T0 (µs) #defineNphs15// Nb de phases [2,15]int n;// Nombre de séquences/ Période constint nCmd=35;// !!! Ne pas toucher! unsignedlong CmdTab[nCmd];// !!! Ne pas toucher! voidsetup(){// Pinout
DDRA =0xff; PORTA=0x00;//DDRB =0xff; PORTA=0x00;//DDRC =0xff; PORTA=0x00;//DDRD =0xff; PORTA=0x00;// Afficahge
Serial.begin(115200);// Synthèse de la commande getCmd()
n=getCmd(CmdTab, nCmd, Nphs);
Serial.print("Nseq=");Serial.println(n);}voidloop(){// Génération de la commande setCmd()setCmd(CmdTab, n);//delayMicroseconds(T0_us); }intgetCmd(unsignedlong*cmdOut,int n_0,int numphase){int n_out=0;int i,j;unsignedlong SyqT1=0x00000000, SyqT2=0x00000000, Syq0=0x00000000;//32-bits if((numphase<=1)||(numphase>15))return;for(i=0;i<n_0; i++) cmdOut[i]=0;/***************************************************//*********** Monophasé - Cas particulier ***********//***************************************************/if(numphase==2){
cmdOut[0]=0x00000001;//Serial.println(cmd[0], BIN); //1:B01
cmdOut[1]=0x00000002;//Serial.println(cmd[1], BIN); //2:B10
n_out=2;return n_out;}/***************************************************//********************* Polyphasé *******************//***************************************************/// A. Génération de la séquence principale
n_out=2*numphase;
SyqT1=0x00000000; Syq0=0x00000001;for(j=0;j<numphase; j++){
SyqT1|=Syq0;
Syq0= Syq0<<1;}
SyqT2=SyqT1<<(numphase);// B. Génération des séquences binaires unsignedlong T1i_B0, T2i_B0;unsignedlong T1i[numphase], T2i[numphase], T12i[n_out];for(int j=0;j<numphase; j++){
T1i[j]=0; T2i[j]=0;}
T1i[0]=SyqT1;T2i[0]=SyqT2;//Serial.print(T1i[0], BIN); Serial.print(" , "); Serial.println(T2i[0], BIN);for(j=1;j<numphase; j++){// 1. Extraction du bit b(0)
T1i_B0=(0x00000001&SyqT1);
T2i_B0=(0x00000001&SyqT2);// 2. Décalage à droite
T1i[j]=SyqT1>>1;
T2i[j]=SyqT2>>1;// 3. b(n-1) =b(0)
T1i[j]|=T1i_B0<<(n_out-1);
T2i[j]|=T2i_B0<<(n_out-1);// 4. Mise à jour des séqs Init
SyqT1=T1i[j];
SyqT2=T2i[j];}// Combinaision des tableaux int ii=0, jj=0;for(j=0;j<n_out; j++){if(j%2==0){
T12i[j]=T1i[ii];
ii++;//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);}if(j%2==1){
T12i[j]=T2i[jj];
jj++;//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);}}// C. Génération des séquences finales
Serial.println("****************************");
Serial.println("T1|T2|T3|T4|T5|T6|T7|T8|T9|... ");
Serial.println("****************************");unsignedlong cmd_i=0;for(i=0;i<n_out; i++){
cmd_i=0;for(j=0;j<n_out; j++)cmd_i|=(((T12i[j]>>i)&0x1)<<(j));
cmdOut[i]=cmd_i;for(int k=0;k<32;k++)Serial.print(((cmd_i>>k)&0x1));
Serial.println("");}
Serial.println("****************************");return n_out;}voidsetCmd(unsignedlong*cmdOut,int n_0){staticint K=0;// Commenté les lignes non utilisées
PORTA=cmdOut[K]&0x000000ff;// (0) -(1*8-1) --LSB//PORTB=(cmdOut[K]>>8) &0x000000ff; // (8) -(2*8-1) //PORTC=(cmdOut[K]>>16)&0x000000ff; // (16)-(3*8-1) //PORTD=(cmdOut[K]>>24)&0x000000ff; // (24)-(4*8-1) --MSB // Affichage du contenu des ports sur 8-bits (A commenté) /*
for (int k=0;k<8;k++) Serial.print(((PORTA>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTB>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTC>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTD>>k)&0x1));Serial.print(",");
Serial.println("");
*/
K++;if(K==n_0) K=0;}