Catégories
Arduino Onduleur Projets Arduino Projets électroniques Variateur de vitesse

Onduleur triphasé #5: Trigger externe – Horloge Externe

Objectifs

  • 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

  • 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.

Projets annexes

Ci-dessous les liens qui vont vous permettre de mieux comprendre et pratiquer la notion des interruptions.

Pourquoi une horloge externe ?

La synthèse d’une période (inverse de la fréquence) par l’intermédiaire des temporisations matérielles (Timers) ou logicielles (delay()) n’est pas assez précises. En effet, les performances de l’oscillateur de la carte Arduino peuvent dériver dans le temps à cause de la température. Et par conséquent, la gestion efficace du temps. L’idée consiste à synchrones le code avec une source externe indépendante.

Schéma Onduleur triphasé Trigger externe – Horloge Externe 1

Fonctionnement

L’idée consiste à lancer le programme via le front montant (ou descendant) d’une horloge externe en utilisant une interruption externe. L’horloge sera branchée directement dans une entrée digitale de la carte dédiée au déclenchement de l’interruption. En résumé, le programme sera équivalent à une boucle loop() qui se lance chaque période de l’horloge externe. On distingue deux configurations.

Horloge lente

La fréquence d’horloge externe doit être choisie en tenant en compte du temps d’exécution du programme a synchronisé. En effet, il faut que l’horloge soit assez lente par rapport à la durée d’exécution du programme comme il est indiqué dans la figure ci-dessous. Par exemple Tp=10ms, alors il faut choisir Tt>2*Tp=20ms dans le cas idéal.

Onduleur triphasé Trigger externe – Horloge lente

Horloge rapide

Si l’horloge est trop rapide par rapport à la durée d’exécution du programme, alors la priorité sera donner au programme. Autrement dit, les fronts montants apparus durant l’exécution du programme seront ignorés. Les fronts ne seront pris en compte qu’à la fin d’exécution du programme (voir la figure ci-dessous).

Onduleur triphasé Trigger externe – Horloge rapide

Pour obtenir une bonne synchronisation, essaye d’utiliser Tt>=2*Tp.

 

Programme (Trigger)

unsigned char State=0x00; 

void setup()
{
DDRA =0xff;PORTA=State;
}

void loop()
{
State=0xff*(!State);
PORTA=State;
delayMicroseconds(8);
}

Programme (Program)

/*
* 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 (foramt 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;

// Cogade 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)));
}

// Afficahge
Serial.begin(9600);
pinMode(3,OUTPUT);

// Configuration de l'Interruption (Trigger Externe)

// Câblage du pin et configuration en entrée: INT0 => PD0 (pin 21 de la carte)
DDRD =0x00; // Port D en entrée

// Activation de l'interruption globale (registre SREG)
SREG|=0x80;

// Validation de l'interruption INT0 (Registre EIMSK)
EIMSK|=0x01; // INT0

// Choix du mode de détection: Front montant dans INT0
EICRA|=0x01;
}

void loop(){}


//ISR(_VECTOR(1)) // Ou _VECTOR(2)
ISR(INT0_vect)
{
//SetCMD1(Trans);
//SetCMD2(Trans);
//SetCMD3(Trans);
SetCMD2(Trans);




/*********** sPWM ***********/
// 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;
}

On verra dans le prochain tuto la commande générique d’un onduleur polyphasée. N’oublie pas me laisser un commentaire :

Laisser un commentaire