MoteurSynchrone

De troyesGEII
Aller à : navigation, rechercher

Description du projet

Le but de notre projet est de piloter les trois phases d'un moteur synchrone par le biais du microcontrôleur ATMEGA 32u4 pour participer au challenge educeco.


Ce projet est quand même conséquent une fois que pour piloter un moteur il faut alimenter les bobines statoriques par des courants triphasés de pulsation ω, afin de créer un champ magnétique Bs tournant à la vitesse ωs.
Le courant dans le bobinage rotorique engendre un champ magnétique Br fixe par rapport au rotor.
L'interaction de ces deux champs crée un couple électromagnétique.
Le rotor est alors entraîné à la même vitesse que celle du champ statorique Bs: ω=ωs (Vitesse de synchronisme).
Si le rotor tourne à une vitesse différente, le couple change sans cesse selon que le champ statorique Bs précède ou suit le champ Br et le couple moyen est nul.
Le couple maximal est obtenu pour ξ=90°.

Composants utilisés

Moteur LMT Lehner 3080
Leh-lmt3080-1.jpg


Carte Arduino Leonardo avec microcontroleur 32u4

Etudes préliminaires

Dans un premier temps, il nous a fallu prendre connaissance et établir les différentes parties du projet, commençant par un schéma fonctionnel


Schéma fonctionnel

Etude de la carte

Nous commencerons par l'étude préliminaire des datasheets du Driver de MOS A4935 et du Microcontrôleur 32U4,ensuite nous établirons un schéma reliant le A4935 et le microcontrôleur, et enfin nous ferons la conception de la carte sur le logiciel Eagle.

Etude du codeur

Etude du code pour les MLI

La génération des signaux MLI est la partie l'une des parties les plus importantes, puisque ces signaux remplaceront les tensions triphasées nécessaires pour tourner un moteur.
Donc, il nous faut générer des MLI à la fréquence souhaitée (Quelques KHz).

Composants utilisés:

  • Carte Arduino Leonardo
  • Condensateurs
  • Résistances
  • Potentiomètre

Amélioration du système

Supervision

Etude et réalisation de la carte

Avant de commencer la fabrication de la carte il est important de savoir qu'est-ce qu'un Driver MOS et quel est son utilité.

Le A4935 est un composant conçu pour piloter des transistors MOS sur 3 phrases différentes. Il possède des alimentations séparées pour la logique et les sections analogiques de commande, une alimentation logique régulée de 3 à 5,5V avec une alimentation non régulée de 5,5 à 50V. Il possède également un certains nombre de fonction de protection contre les sous-tensions, les surchauffes et les défauts du pont de puissance. En plus de ces défaut il intègre des moniteurs drain-source pour chaque transistors externe afin de détecter les courts-circuits. Deux sorties FF1 et FF2 sont fournies pour signaler les défauts détectés à un contrôleur externe.

Les MLI

arduino leonardo pinout

Définition

Nous avons commencé le projet avec une carte demo, ce que nous a permis de faire de testes sur le moteur, pendant la réalisation de notre carte.
Pour la génération des MLI, d'abord nous avons commencé par une étude de la datasheet du microcontrôleur ATMEGA32u4.
La carte Arduino Leonardo, propose un timer (le Timer 4) avec une fréquence d'horloge de l'ordre de 64MHz, 3 sorties PWM avec ses complémentaires et un mode de génération de signaux appelé PWM6 permettant de contrôler un moteur brushless.
Nous avons donc utilisé ce timer pour générer 6 MLIavec une fréquence autour de 8kHz.

Description mode pwm

Comme tous les transistors ne peuvent pas être pilotés en même temps, il va falloir générer un temps mort afin d'éviter un court circuit.

Temps_mort


Aprés avoir étudié la datasheet, nous avons réussi à générer les signaux de tests par le code suivant :

Code MLI

int main()
{

DDRB|=(1<<PB5)|(1<<PB6);//  OCR4B 9 ET 10
DDRD|=(1<<PD6)|(1<<PD7);//  OCR4D 6 ET 12
DDRC|=(1<<PC6)|(1<<PC7);// OCR4A ET OPOSE 13 et 5

//pwm

TCCR4A|=(1<<PWM4A)|(1<<PWM4B);
TCCR4C|=(1<<PWM4D);





  //prediviseur:8
  TCCR4B|=(1<<CS42);


///Connection de complementarité entre les broches
TCCR4A|=(1<<COM4A0)|(1<<COM4B0);
TCCR4C|=(1<<COM4D0);


  OCR4C=255;//comparaison
  OCR4A=100; //rapport cyclique
  OCR4B=100;
  OCR4D=100;

// TEMPS MORT
  DT4 =0x80;

while(1)
{
  OCR4A++;
  OCR4B++;
  OCR4D++;
_delay_ms(20);
}

}

Filtrage

Nous avons ensuite utilisé un filtre passe bas afin de récupérer la valeur moyenne du signal.
Pour avoir une idée, utilisons un tableau Excel, partant de 36 valeurs (360° du cercle).

tableau mli



Ensuite, nous avons pris les valeurs des l'angle des trois tableaux et rajouté au code, avec un poentiomètre pour aider à faire varier la vitesse de rotation:

Pot.png














Code MLI

  #include"avr/io.h"

unsigned char tab_v1[36]={127,149,170,190,208,224,236,246,252,254,252,246,236,224,208,190,170,149,127,104,83,63,45,29,17,7,1,0,1,7,17,29,45,63,83,104};
unsigned char tab_v2[36]={236,224,208,190,170,149,127,104,83,63,45,29,17,7,1,0,1,7,17,29,45,63,83,104,127,149,170,190,208,224,236,246,252,254,252,246};
unsigned char tab_v3[36]={17,7,1,0,1,7,17,29,45,63,83,104,127,149,170,190,208,224,236,246,252,254,252,246,236,224,208,190,170,149,127,104,83,63,45,29};
int i;
int pot;
int valPot;


void setup()
{

DDRB|=(1<<PB5)|(1<<PB6);//  OCR4B 9 ET 10
DDRD|=(1<<PD6)|(1<<PD7);//  OCR4D 6 ET 12
DDRC|=(1<<PC6)|(1<<PC7);// OCR4A ET OPOSE 13 et 5


//init config timer : Une fois les fonctions Arduino utilisées, on doit mettre à 0 les valeurs des registres.
TCCR4A=0;
TCCR4B=0;
TCCR4C=0;


//pwm

TCCR4A|=(1<<PWM4A)|(1<<PWM4B);
TCCR4C|=(1<<PWM4D);





  //prediviseur:8
  TCCR4B|=(1<<CS42);


///Connection de complementarité entre les broches
TCCR4A|=(1<<COM4A0)|(1<<COM4B0);
TCCR4C|=(1<<COM4D0);


  OCR4C=255;//comparaison
  OCR4A=100; //rapport cyclique
  OCR4B=100;
  OCR4D=100;

// TEMPS MORT
  DT4 =0x80;
}
void loop() {
  pot=analogRead(A0);
  valPot=pot/32;
 
   if(i==36)i=0;i++;
 
  OCR4A=tab_v1[i]/8;
  OCR4B=tab_v2[i]/8;
  OCR4D=tab_v3[i]/8;
delay(valPot);

}

Le codeur Incrémental

MLI + codeur

Systeme.jpg












Après l'étude du codeur nous avons donc ressemblé les deux codes pour améliorer la façon de tourner.
Le codeur permet de connaître la position des aimants du rotor et donc celle du champ rotorique. Les information s qu'il fournit permettent au système de commande d'alimenter les enrôlements adéquats via les transistors.
Avec ces altérations le code est donc devenu un peu conséquent:


Code MLI + codeur

#include"avr/io.h"

unsigned char tab_v1[36]={127,149,170,190,208,224,236,246,252,254,252,246,236,224,208,190,170,149,127,104,83,63,45,29,17,7,1,0,1,7,17,29,45,63,83,104};
unsigned char tab_v2[36]={236,224,208,190,170,149,127,104,83,63,45,29,17,7,1,0,1,7,17,29,45,63,83,104,127,149,170,190,208,224,236,246,252,254,252,246};
unsigned char tab_v3[36]={17,7,1,0,1,7,17,29,45,63,83,104,127,149,170,190,208,224,236,246,252,254,252,246,236,224,208,190,170,149,127,104,83,63,45,29};
 int teta;
unsigned int pot;
unsigned int valPot = 0;

unsigned const int valeurMaximaleCapteur=499;
volatile int valeur;
volatile char change=0;

const uint8_t pinLedV = 11;


void Interrupt() {

change=1;
  if ( (bit_is_set(PINB, PB4) == 0))
  { //regarde le front montant
    
  
  if ( valeur == valeurMaximaleCapteur ) {
    valeur = 0;
  }
  else {
    valeur++;
  }
  }

  if ( (bit_is_clear(PINB, PB4) == 0))
  { //regarde le front descendant

  if ( valeur == 0) {
    valeur = valeurMaximaleCapteur;
  }
  else {
    valeur--;
  }
  }
 
}



void Interrupt1() {
  change=1;
  if ( bit_is_set (PIND, PD0) ) { //Top Tour
  valeur = 0;
  }
}






void setup() {


  //CONFIGURATION DES SORTIES
  DDRB|= (1<<PB5)|(1<<PB6);//9 et 10
  DDRD|= (1<<PD6)|(1<<PD7);//6//12
  DDRC|= (1<<PC6)|(1<<PC7);//13/5

  pinMode(pinLedV, OUTPUT);
  
// Codeur
  Serial.begin (9600);
  Serial.println ("Debut");
  

  

//attendre top tour
loop_until_bit_is_set (PIND,PD0);

  attachInterrupt(0, Interrupt1, CHANGE); //top tour
  digitalWrite(pinLedV,HIGH);
  
  attachInterrupt (1, Interrupt, RISING); //front montant
  delay(5000);

do
{
  pot=analogRead(A0);
}while(pot<980);
//init config timer
TCCR4A=0;
TCCR4B=0;
TCCR4C=0;

 
  // MODE PWM
  TCCR4A|=(1<<PWM4A)|(1<<PWM4B);
  TCCR4C|=(1<<PWM4D);
  //TCCR4D &=~ (1<<WGM41)|(1<<WGM40); // ON PEUT LAISSER CETTE CONFIGURATION
 
  TCCR4B|=(1<<CS41)|(1<<CS40);
 
  // TEMPS MORT
  TCCR4B|=(1<<DTPS41)|(1<<DTPS40);
 
  // CONNEXION DE COMPLEMENTARITE ENTRE LES BROCHES
  TCCR4A|=(1<<COM4A0)|(1<<COM4B0);
  TCCR4C|=(1<<COM4D0);


  //VALEUR MAXIMALE DU COMPTEUR
  OCR4C=255;//comparaison
  OCR4A=100; //rapport cyclique
  OCR4B=100;
  OCR4D=100;

   

  // TEMPS MORT
  DT4 =0x80;
 ///////////

 
}

void loop() {

static uint8_t cpt=0;
cpt++;
if (change!=0)
  {
  change=0;
  Serial.println (valeur); // angles lus par le codeur
  delay(20);
  
  int32_t angleRotor=(valeur*36)/250;
 
  pot=analogRead(A0);
  valPot=pot/8+1;

  teta=angleRotor+18;
  if (teta>35) teta=teta-36;


  if (cpt==0)
  {
    Serial.print (valPot); // angles lus par le codeur
    Serial.print(" ");
    Serial.print (angleRotor); // angles lus par le codeur
    Serial.print(" ");
    Serial.println (teta); // angles lus par le codeur
  }
 
  OCR4A=tab_v1[teta]/valPot;
  OCR4B=tab_v2[teta]/valPot;
  OCR4D=tab_v3[teta]/valPot;
  //delay(valPot);
  _delay_ms(1);

}

Amélioration du système

Jusqu'ici nous avons réussi à créer un champ tournant et engendrer la rotation du rotor. Mais notre système n'est pas tout à fait parfait.
Nous avons procédé à certaines altérations afin de l'améliorer :

Asservissement de courant