MoteurSynchrone2019
Sommaire
Partie 1:Projet
Description
L’objectif principal de ce projet était de piloter les trois phases d’un moteur synchrone à l'aide d’un microcontrôleur ou d’un FPGA. Pour cela il a fallu dans un premier temps comprendre le projet, faire une étude afin de définir les différentes tâches à réaliser pour mener à bien le projet. Après compréhension et étude du projet les différentes grandes tâches que l'on a défini furent :
- La programmation des MLI OU PWM
- L’étude et la programmation du capteur de position (codeur incrémental)
- L’étude et la réalisation de la carte
- La supervision
- La fabrication des pièces mécaniques
Matériel
La liste du matériel utilisé est la suivante:
DESIGNATION | LOGICIEL |
---|---|
Carte Arduino leonardo | Freecad |
Driver de MOS A4935 | Arduino |
codeur incrémental | Eagle |
moteur synchrone | QT céator |
RaspberryPi | LTSpice |
Imprimante 3D | Excel |
Partie 2: Fabrication de la carte électronique
Saisie du schéma
Pour fabriquer une bonne carte électronique , on doit se focaliser sur les points suivants:
- Comment fonctionne le driver ?
- Comment programmer le microcontrôleur ?
Les premières informations que nous avons récupéré sont grâce au schéma fonctionnel suivant:
Le composant A4935 sert à piloter des transistors MOS sur 3 phases différentes. Le but est de déterminer les valeurs des différents composants qui lui seront associés.
Il faudra également déterminer quels signaux logiques, et sur quelles entrées ceux-ci iront afin de choisir un mode de fonctionnement approprié.
Pour faire notre schéma , il a fallu faire connaissance de la datasheet du microcontrôleur ATMEGA32u4 (http://ww1.microchip.com/downloads/en/devicedoc/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf) et celle du driver A4935 Fichier:A4935-Datasheet (3).pdf
Routage
Il est évident d'essayer de respecter les consignes de bases pour fabriquer une bonne carte électronique.
Vu le nombre de composants à placer on se retrouve avec beaucoup de vias.
Les pistes en sortie des composants A4935 et ATMEGA32U4 sont les moins larges possibles afin de ne pas avoir de contact entre les différentes pattes. On a mis les noms des composants afin de pouvoir les repérer plus simplement, sans forcément avoir le board à portée. Le composant A4935 et les transistors n'étant pas présents de base dans les librairies d'Eagle, on a du les créer pour l'occasion. On a commencé par placer les plus petits composants avec de la pâte à braser, suivit d'un passage au four. Le reste des composants (potentiomètres, borniers) sont soudés de manière normale. Les pattes de ce composant étant extrêmement petites, plusieurs complications se sont rajoutées afin d'éviter les liaisons non voulues entre les pattes.
Test de la carte
Après la réalisation de la carte, on a pu faire quelques tests afin de dépanner les éventuelles erreurs
1er test
Vérification de la communication avec le microcontrôleur.
Dans un terminal on a lancé la commande
- avrdude -c avrisp2 -P usb -p m32u4
Liaison série entre le PC et la carte
Rien de plus simple que d'écrire ce bout de programme!!! .
void setup() { Serial.begin(9600); } void loop() { Serial.println("coucou"); }
Communication entre la carte et le codeur
Afin de connaitre la position du moteur à tout instant, on utilise le codeur rotatif. Pour tester la communication entre ces deux , on a repris le programme du codeur rotatif relaté dans la partie codeur rotatif mais cette fois avec les pattes compatibles à notre carte.
Et pour faire cette partie, on a utilisé le matériel suivant:
- nappe de 1m à 2m
- connecteur molex
- barrette mâle-femelle sécable
- gaine thermorétractable
- pince à dénuder
Partie 3: Programmation
L'objectif de la programmation est de pouvoir contrôler le pilotage du moteur par le biais d'un microcontrôleur. Nous allons ici utiliser l'Arduino Leonardo. Nous avons fait ce choix à cause des caractéristiques de son microcontrôleur(ATMEGA32u4) principalement le timer 4 avec:
- trois sorties PWM et leurs complémentaires
- une fréquence d'horloge allant à 64Mhz
- une grande vitesse de chronométrage et de comptage
- une haute résolution et une grande précision
Le travail se fera en plusieurs étapes. D'abord, nous allons générer des MLI, ensuite mesurer les valeurs instantanées de l'angle au rotor grâce au codeur incrémental et enfin faire une supervision du pilotage du moteur.
Générer des MLI
Le moteur qui fait objet de notre étude est un moteur brushless triphasé ci-contre. Ce moteur est alimenté par une tension triphasée déphasée chacune de 2π/3 et nous disposons d'une tension d'alimentation continue.Il faut donc veiller à transformer cette tension continue en tension sinusoïdale. Pour ce fait, nous allons générer trois MLI en faisant usage du timer 4 du microcontrôleur. Une MLI (Modulation de largeur d'impulsions ou PWM pulse width modulation) est un signal logique qui vaut soit 0 ou 1 dont on peut varier le rapport cyclique et pour lequel la fréquence est fixe. Elle permet de faciliter la commande des transistors dont nous ferons usage pour piloter notre moteur. Ici, nous aurons besoin de trois MLI et de leurs opposées donc six MLI au total pour commander trois demi-pont fonctionnant par paire. Pour éviter que deux transistors de la même paire fonctionnent simultanément, on fera appel aux entrées xHI et xLO du driver.
Partir des notions de base
La liste du matériel utilisé est la suivante:
DESIGNATION | QUANTITE | VALEUR |
---|---|---|
led | 6 | |
resistance | 6 | 330Ω |
resistance | 6 | 10KΩ |
condensateur | 6 | 150nF |
carte arduino | leonardo | |
platine d'essai |
Dans un premier temps, il a fallu prendre connaissance de la datasheet (http://ww1.microchip.com/downloads/en/devicedoc/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf) du microcontrôleur.Nous avons ensuite fais des tests sur platine d’essai afin de visualiser la forme du signal obtenu, la fréquence, de régler le temps de commutation entre les transistors sur un oscilloscope et d’avoir une idée visuelle des MLI grâce au clignotement des leds. Le programme suivant nous a permis de réaliser ses différents tests.
int main()
{
//CONFIGURATION DES SORTIES
DDRB|= (1<<PB5)|(1<<PB6);
DDRD|= (1<<PD6)|(1<<PD7);
DDRC|= (1<<PC6)|(1<<PC7);
//CHOIX DU MODE PWM
TCCR4A|=(1<<PWM4A)|(1<<PWM4B);
TCCR4C|=(1<<PWM4D);
//TCCR4D &=~ (1<<WGM41)|(1<<WGM40); // ON PEUT LAISSER CETTE CONFIGURATION
// CHOIX DU PRESCALER DIVISION PAR 1024
TCCR4B|=(1<<CS41)|(1<<CS40);
//TCCR4B &=~ (1<<CS42);(1<<CS41);(1<<CS40)(1<<CS43);
// DIVISION DU TEMPS MORT *8
TCCR4B|=(1<<DTPS41)|(1<<DTPS40);
// CONNEXION DE COMPLEMENTARITE ENTRE LES BROCHES
TCCR4A|=(1<<COM4A0)|(1<<COM4B0);
//TCCR4A &=~(1<<COM4A1)|(1<<COM4B1);
TCCR4C|=(1<<COM4D0);
//TCCR4C &=~(1<<COM4D1);
//VALEUR MAXIMALE DU COMPTEUR
OCR4C=255;
// TEMPS MORT
DT4 |= 1<< DT4L1;
while(1)
{
OCR4A++;
OCR4B++;
OCR4D++;
_delay_ms(20);
}
}
Le signal obtenu à l’oscilloscope est le suivant :
Filtre passe-bas
Apres cette étape, il a fallu réaliser un filtre passe-bas afin de récupérer la valeur moyenne du signal. Nous obtiendrons alors trois signaux de forme sinusoïdale. La fréquence des MLI générées est de 15Khz, nous avons réalisé un filtre passe-bas avec une fréquence de coupure de 100Hz. Nous avons faire une petite simulation sur Excel et le resultat est ce qui suit:
Certains calculs ont également été effectués afin de choisir la valeur des composants qui permettrait d'avoir la fréquence de coupure de 100Hz prédéfinie. On a réalisé un filtre simple pour un premier test. Les valeurs sont répertoriées dans le tableau ci-dessus.
Le programme a ainsi été modifié afin de prendre en compte le filtre et les valeurs prises par l'angle au stator du codeur (cette partie sera détaillée plus bas).On a ensuite ajouté un potentiomètre afin de contrôler l'amplitude de la tension et le rapport cyclique des MLI et on obtient ce qui suit:
volatile int val = 0; //use dans tout le programme const int valMaxCapteur = 1000; //valeur max de l'angle pour HEDS-5540-A01 (voir datasheet pour d’autre encodeur de la même famille)
// DECLARATION DES VARIABLES // TABLEAUX
const uint8_t tabA[34]= {120,142,163,182,199,214,225,232,235,234,229,220,207,191,173,153,131,109,88,67,49,33,21,11,6,5,8,15,26,40,58,77,98,120}; const uint8_t tabB[34]= {225,214,199,182,163,142,120,98,77,58,41,26,15,8,5,6,11,20,33,49,67,87,109,131,152,173,191,207,219,229,234,235,232,225}; const uint8_t tabD[34]= {33,20,11,6,5,8,15,26,41,58,77,98,120,142,163,182,199,214,225,232,235,234,229,220,207,191,173,153,131,109,88,67,49,33}; int i=0; int valpot; int valtabA,valtabB,valtabD; void Interrupt1(){ if ( bit_is_set (PINE,PE6) ){ //Top Tour val = 0; }else{ if ( (bit_is_set(PIND,PD4) == 0) ){ //regarde le front montant if ( val == valMaxCapteur ){ //on regarde si on a la valeur max val = 0; }else{ val++; } }else{ if(val == 0){ //on regarde si on à la valeur min val = valMaxCapteur; }else{ val--; } } } }
void Interrupt2(){ if ( bit_is_set (PINE,PE6) ){ val = 0; }else{ if ( (bit_is_clear(PIND,PD4) !=0)){ //regarde le front descendant if ( val == 0 ){ //on regarde si on a la valeur min val = valMaxCapteur; }else{ val--; } }else{ if(val == valMaxCapteur){ //on regarde si on à la valeur max val = 0; }else{ val++; } } } }
void setup() { Serial.begin (9600); Serial.println ("Start"); attachInterrupt (1, Interrupt1, RISING); //l'interruption pour pouvoir lire le font montant attachInterrupt (0, Interrupt2, FALLING); //l'interruption pour pouvoir lire le font descendant
//CONFIGURATION DES SORTIES DDRB|= (1<<PB5)|(1<<PB6); DDRD|= (1<<PD6)|(1<<PD7); DDRC|= (1<<PC6)|(1<<PC7);
// MISE A ZERO DES REGISTRES TCCR4A = 0; TCCR4B = 0; TCCR4C = 0; //CHOIX DU MODE PWM TCCR4A|=(1<<PWM4A)|(1<<PWM4B); TCCR4C|=(1<<PWM4D); // CHOIX DU PRESCALER DIVISION PAR 1024 TCCR4B|=(1<<CS41)|(1<<CS40); // DIVISION DU TEMPS MORT *8 TCCR4B|=(1<<DTPS41)|(1<<DTPS40); // CONNEXION DE COMPLEMENTARITE ENTRE LES BROCHES TCCR4A|=(1<<COM4A0)|(1<<COM4B0); TCCR4C|=(1<<COM4D0); //VALEUR MAXIMALE DU COMPTEUR OCR4D=255; // TEMPS MORT DT4 |= 1<< DT4L1;
//DECLARATION DE L'ENTREE A3 pinMode(A3,INPUT);
delay(5000); }
void loop() { if (i==33) i =0; else i++;
valpot = analogRead(A3); valtabA= ((valpot/8) * int(tabA[i]))/(1024/8); OCR4A = uint8_t(valtabA); valtabB= ((valpot/8) * int(tabB[i]))/(1024/8); OCR4B = uint8_t(valtabB); valtabD= ((valpot/8) * int(tabD[i]))/(1024/8); OCR4D = uint8_t(valtabD); //_delay_ms (1); Serial.print("valpot :"); Serial.print(valpot); Serial.print(" "); Serial.print("valtabA :"); Serial.println(valtabA);
Serial.println("Angle :"); Serial.println (val); //lire sur la console les angles lu par le codeur
delay(250); //delay qui permet de nous laisser du temp pour lires les valeurs }
Les signaux visualisés à l'oscilloscope sont indiqués sur la figure suivante:
Codeur incrémental
Pour savoir quelle est la position du moteur en tout instant, on utilise un codeur rotatif. On utilise un HEDS-5540 de la famille Avao technologie pour nous donner les informations. On y place les fils sur l'arduino avec le fil noir pour le GND, le fil vert pour le Vcc, et les fils rouges, bleus et jaunes servent à donner, transmettre les informations du moteur à l'arduino Leonardo. Pour pouvoir utiliser les informations, on implante un programme arduino pour lire les informations du codeur. Pour cela, on a deux voies qui servent à détecter si le moteur va dans un sens ou dans un autre, et une voie qui permet de détecter le Top tour du moteur.
On va expliquer comment on arrive à lire et exploiter les informations du codeur :
Dans un premier temps, il fallait apprendre à lire les informations sur arduino, puis on doit gérer l'incrémentation et la décrémentation pour avoir un visuel de ce que fait le moteur avec des valeurs. Enfin, il fallait que le codeur puisse revenir à zéro pour savoir quand le moteur fait un tour complet.
Programme du codeur rotatif
Le void setup permet de configurer l'arduino en donnant la vitesse et configurant les fonctions utiles au programme.
void setup() { Serial.begin (9600); Serial.println ("Start"); attachInterrupt (1, Interrupt1, RISING); //l'interruption pour pouvoir lire le front montant attachInterrupt (0, Interrupt2, FALLING); //l'interruption pour pouvoir lire le front descendant delay(5000); }
Le void loop sert juste à afficher les valeurs lues par le codeur.
void loop(){ Serial.println (val); //lire sur la console les angles lus par le codeur delay(250); //delay qui permet de nous laisser du temps pour lire les valeurs }
Le Interrupt sert à l'incrémentation, ou la décrémentation pour la seconde fonction, et qui enregistre les valeurs données par le codeur.
void Interrupt1(){ if ( bit_is_set (PINC,PC6) ){ //Top Tour val = 0; }else{ if ( (bit_is_set(PIND,PD4) == 0) ){ //regarde le front montant if ( val == valMaxCapteur ){ //on regarde si on a la valeur max val = 0; }else{ val++; } }else{ if(val == 0){ //on regarde si on a la valeur min val = valMaxCapteur; }else{ val--; } } } }
A noter que les PIN peuvent être changés suivant le besoin de l'utilisateur
Tests: Carte Demo
Dans cette partie du travail, notre carte était en cours de fabrication, on a donc fait usage de la carte demo A4935 fournie par le fabricant. Cette carte nous a permis de faire des tests et d'ajuster au fur et à mesure notre programme.
Après avoir mis en commun les deux programmes précédents, l’étape suivante était de trouver la formule juste pour les angles du stator et du rotor mesurent 90 degrés afin que le couple soit au maximum. Nous sommes partis du principe que: angle_stator = angle_rotor + offset et avons ajouté un second potentiomètre afin de pouvoir régler un offset approximativement correct. A la fin du test, ce potentiomètre a été retiré.
Ensuite nous avons essayer de faire un démarrage manuel suivant certaines contraintes du moteur. Ce qui,nous a amené à contrôler en permanence le fonctionnement correct du codeur grâce à l'oscilloscope.
Trois conditions sont nécessaires pour un démarrage optimal du moteur:
- le potentiomètre contrôlant le rapport cyclique des MLI doit être mis à zéro
- nous devons faire un tour complet du codeur
- les défauts relevés par le driver doivent avoir été supprimés
Afin d’éliminer les défauts, nous avons tenu compte de la partie de la datasheet relative à la gestion des défauts du composant A4935.
Après documentation, pour supprimer les défauts, nous devons mettre le reset du composant à zéro comme indiqué dans la table de vérité ci-dessus.
Durant les tests, on s'est aperçu qu'a partir d'une certaine valeur, le courant devenait instable. Il nous revient alors de faire l'asservir afin de contrôler la vitesse et le couple. On va alors se servir de l'amplificateur de courant que renferme le driver. Nous sommes partis d'une simple mesure de courant grâce aux résistances de shunt entre les pins CSP et CPN du driver. Le courant faible mesuré sera ainsi amplifié à la sortie CSOUT. Malheureusement, ce signal n'est pas parfait, on va réaliser un filtre passe-bas actif avec une fréquence de coupure 700Hz.
Pour dimensionner notre filtre, on a effectué des calculs sur la base des composants existants déjà sur la carte demo.
Tous les composants restent inchangés sauf la résistance Rf qui sera remplacée par un condensateur en parallèle avec une résistance comme la figure ci-dessus. Les nouvelles valeurs sont consignées dans le tableau suivant:
DESIGNATION | VALEUR |
---|---|
R15 | 75K |
R16 | 3,9K |
R14 | 75K |
R11 | 8,2K |
R12 | 8,2K |
R2 | 10k |
condensateur | 100nF |
Après les calculs et la réalisation du filtre, nous n'avons pas eu les résultats attendus car le signal obtenu oscillait. On a ensuite pensé diviser les valeurs par deux, le résultat était le même. Finalement, nous avons opté pour une simulation sur LTspice.
Supervision
Pour visualiser ce que fait le moteur, on utilise une carte Raspberry Pi 3. La principale difficulté est de pouvoir communiquer entre l'arduino, qui récupère les informations en binaire du moteur, à la Raspberry, qui traite des informations en numérique. On utilise pour cela un composant qui permet de transformer les informations binaires en numériques et inversement. Il faut aussi configurer la carte Raspberry pour qu'elle puisse recevoir ces informations. Pour cela nous nous aidons de ce lien pour configurer la Raspberry Pi ( https://spellfoundry.com/2016/05/29/configuring-gpio-serial-port-raspbian-jessie-including-pi-3-4/ ).
Etape 1
Pour vérifier la bonne connexion entre l'arduino et la Raspberry Pi, on utilise dans l'invite de commande à l'aide du minicom. On effectue ces tests avec de simples programmes. Pour pouvoir communiquer entre l'arduino et la Raspberry Pi, il faut configurer la vitesse avec les Serial. Sur QtCreator, on utilise la bibliothéque QtSerialPort ( https://doc.qt.io/qt-5/qserialport.html ) et QioDevice ( https://doc.qt.io/qt-5/qiodevice.html ), pour pouvoir utiliser la transmission de données. Dans le .h on ajoute dans le public slot une fonction pour pouvoir analyser les données reçues puis en private une valeur serial qui sera utiliser dans le .cpp. Dans le .cpp, on définit dans un premier temps l'utilisation QSerialPort pour qu'il soit à la même vitesse de transmission que l'arduino, puis on demande avec la fonction DataToRead de lire les informations données par l'arduino.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); serial.setPortName(QString("/dev/ttyAMA0")); //Permet de lire sur quelle entrée on communique serial.setBaudRate(9600); //Vitesse de 9600 baud/s //serial.setParity(QSerialPort::MarkParity); //Mettre un bit de Parité pour vérifier l'information connect(&serial, SIGNAL(readyRead()), this, SLOT(dataToRead())); //connect(&objet use,SIGNAL("prendre ceux proposé"),this,SLOT("notre fonction à use") serial.open(QIODevice::ReadOnly); //Permet de lire les informations de l'arduino }
void MainWindow::dataToRead(){ char c; while (serial.waitForReadyRead()) //On attend les infos à transmettre pour l'use dans la boucle { serial.getChar(&c); qDebug() << c; } }
Etape 2
On doit faire envoyer les valeurs depuis l'arduino à la Raspberry en continu. Pour cela nous allons créer un message qui comportera un caractère de début, ici #, puis les valeurs séparées par un ; et enfin un $ pour montrer la fin du message et qu'il n'y a pas eu de problème lors de la transmission du message.
void setup() { Serial.begin (9600); Serial1.begin (9600); delay(5000); } void loop() { val = analogRead(A3); //pouvoir lire les infos du potentiomètre sur l'arduino Serial.print("#"); //pour pouvoir avoir le début du message Serial1.print("#"); Serial.print (val); //lire sur la console les angles lus par le codeur Serial1.print(val); Serial.print("$"); //pour avoir la fin du message Serial1.print("$"); delay(250); //delay qui permet de nous laisser du temps pour lire les valeurs }
Dans QtCreator, dans la fonction DataToRead, on demande au programme de décoder les valeurs transmises par l'arduino puis de les afficher dans un display en affichage numérique.
NB : On peut mettre des qDebug() pour vérifier que le programme passe dans toute la boucle et ne soit pas coincé ce qui expliquerai pourquoi il y a des ralentissements ou freeze de l'écran de la Raspberry Pi.
void MainWindow::dataToRead(){ char c; while (serial.bytesAvailable() >3){ //On attend les infos à transmettre pour l'use dans la boucle serial.getChar(&c); qDebug() <<"lit char"; if (c=='#'){ //Permet de repérer le début du message bool messageValide = true; QString message; //Permet de ranger les infos de l'arduino dans une variable int i = 0; qDebug() << "ok debut !"; do{ //on lit le getChar tant qu'on a pas le '$' serial.getChar(&c); qDebug() <<"LIT CHAR"; if (c!='$'){ //Si on a pas le '$' alors on range les infos ds message message.append(c); i++; //On incrémente i à chaque passage dans la boucle ( sécurité ) qDebug() << "RECU: " << message; //On regarde dans la console les valeurs qui passent } if (i == 5){ //Si i > 4 alors on a une erreur messageValide = false; qDebug() << "FAUX"; } }while(c!='$'); //Si on a '$' alors on affiche le message if (messageValide==true){ //Si on a le message qui est bon alors on affiche le nombre ( sécurité ) ui->Affichage_nombre->display(message); //display permet d’utiliser le QLCNumber ( PS : ne pas oublier de l’incure ) qDebug() << "Affichage"; }else{ qDebug() << "ERREUR"; } }else{ qDebug()<<" recu : "<<c; } } }
La méthode est la même lorsque l'on rajoute des valeurs sur l'arduino puis qu'elle est décodée sur Qt.
Etape 3
Ensuite il était prévu que l'on puisse commander le fonctionnement du moteur en envoyant une donné depuis Qt à l'arduino. Dans un premier il faut configurer la partie qui devaient envoyer cette donnée en créant une fonction qui va écrire à l'arduino, ici DataToWriteOn pour allumer le moteur (dans le principe) et DataToWriteOff pour l'éteindre.
serial.open(QIODevice::ReadWrite); //Permet de lire les informations de l'arduino et d'émettre les infos pour l'arduino
Cette ligne à changer permet de lire et d'envoyer des données par l'arduino.
void MainWindow::dataToWriteON(){ serial.write("o"); qDebug() << "ON"; }
Même principe avec la fonction DataToWriteOff.
Ensuite sur arduino nous devons pouvoir lire cette information et, si nous pouvions le finir, donner l'information qui s’arrêterait ou s’allumerait suivant ce qu'on lui a demandé. Dans le void loop on rajoute juste cette ligne qui permettrait d'effectuer nos actions sur le moteur.
if( Serial1.available() > 0 ) { //Permet de savoir quand on reçoit une valeur incomingByte = Serial1.read(); //permet de mettre cette valeur dans une variable if ( incomingByte == 'o'){ //si on a 'o' alors on met ON sur la console arduino Serial.println ("ON"); } if ( incomingByte == 'f'){ //si on a 'f' alors on met OFF sur la console Serial.println ("OFF"); } }
Pour vérifier si on a bien les valeurs qui se transmettent, ici ON ou OFF, on prend un oscilloscope que l'on branche au patte du composant permettant de faire le switch entre numérique et analogique.
Etape 4
Pour finir, nous devons pouvoir visualiser la position du champ rotorique et statorique du moteur pour s'assurer qu'il ne s'emballe pas. Pour cela nous allons utiliser la librairie QGraphicscene ( http://tvaira.free.fr/projets/activites/activite-qt-dessin.html et https://doc.qt.io/qt-5/qgraphicsscene.html ) pour pouvoir les afficher. Une fois avoir déclaré les librairies dans Qt, on crée notre scene graphique dans le .cpp.
void MainWindow::paintEvent(QPaintEvent *event){ QPainter ellipsePainter(this); QPen pen; pen.setWidth(1); pen.setBrush(Qt::SolidPattern); ellipsePainter.setPen(pen); ellipsePainter.drawEllipse(100-75,100-75,150,150); //2 premiers servent à placer le cercle - 2 derniers servent à la largeur puis hauteur du cercle QPainter myline(this); QPen linePen(Qt::red); linePen.setWidth(5); myline.setPen(linePen); myline.drawLine(100,100, 100+x,100+y); //2 premiers servent à positionner le point (x1,y1) - 2 derniers servent à positionner l'autre extrémiter (x2,y2) QPainter myline_2(this); QPen linePen_2(Qt::blue); linePen_2.setWidth(4); myline_2.setPen(linePen_2); myline_2.drawLine(100+x_2,100+y_2, 100+x,100+y); }
NB : x, y, x_2 et y_2 sont des variables déclarées en private dans le .h pour pouvoir s'en servir dans tout le programme.
Les valeurs de x, y, x_2 et y_2 sont récupérées depuis les informations transmises de l'arduino. On les utilise à la fin de la boucle de la fonction DataToRead.
valDial = dial1.toInt(); //Permet de convertir de char à int valDial2 = dial2.toInt(); if (dialValide==true){ ui->dial->setValue(valDial); //On montre la position valDial sur dial ui->dial_2->setValue(valDial2); radians = ((2*M_PI)*valDial) / 34 ; //permet de convertir une valeur numérique en radian (34->2pi rad et x -> y rad) radians_2 = ((2*M_PI)*valDial2) / 34 ; //Calcul du cos et du sin pour les renvoyer au paintEvent x = 42 * qCos(radians); y = 42 * qSin(radians); x_2 = 77 * qCos(radians_2); y_2 = 77 * qSin(radians_2); } repaint(); //permet de le rafraîchir la fenêtre
Le calcul consiste en une fonction de trigonométrie pour connaitre l’hypoténuse et donc le trait qui permet de savoir quelle est la position du moteur. On effectue ainsi le calcul à la fin de la fonction DataToRead avant de l'envoyer à la fonction paintEvent. On a une fonction repaint() qui nous permet de rafraîchir la scene graphique et ainsi avoir la position en temps réel.
Voilà le résultat final avec deux affichages numériques pour la tension donnée et l'angle du moteur. Deux leds numériques qui nous préviennent lors du défaut du moteur. Deux boutons qui devaient servir à faire fonctionner ou arrêter le moteur sans intervention physique. Deux représentations graphiques, l'une avec des potentiomètres numériques et l'autre avec le Qgraphicscene, pour observer la position du moteur.
Partie 4: Mécanique
Description du travail à réaliser
Après les tests à vide du moteur on se doit de le tester en charge. Le but de cette partie était de réaliser des pièces d'accouplement et un support afin de connecter la charge au moteur et de réaliser des tests.
- il fallait démonter le moteur ci-contre afin de le remplacer par le notre.
à l'aide de clé plate, d'un jeu de btr et de quelques tournevis on a démonté le moteur
- trouver une solution pour monter et accoupler notre moteur pour effectuer les tests.
le problème qui se posait était de trouver comment faire pour que notre moteur de petite taille soit à la bonne hauteur afin que l'axe du moteur coïncide avec celui de la charge et trouver aussi une solution pour effectuer l'accouplement du moteur à la charge afin qu'il puisse l’entraîner en rotation. Donc pour se faire nous avions d'abord compris comment l'ancien moteur le faisait puis nous avons récupéré les pièces utiles,fait des mesures à l'aide d'un pied à coulisse mais pour la mesure de la hauteur entre plateau et l'axe de la charge nous sommes allés en GMP pour récupérer une colonne de mesure qui était beaucoup plus pratique q'un pied à coulisse.
- il fallait fabriquer les différentes pièces utiles au montage du moteur.
Après mesure il me fallait réaliser dans un premier temps les croquis des pièces (roue dentée et un support moteur) à la main puis dans un deuxième temps réaliser la conception sur freecad des pièces puis enfin les faire imprimer en 3D.
- Assemblage du moteur + alternateur et test.
Pour le maintien du support moteur, nous avons utilisé la solution vis écrous bien sur qui avait été récupéré sur l’ancien support et pour la roue dentée qui était fixée sur l'axe du moteur nous avons utilisé une vis de pression afin qu'il soit bien fixé sur l'arbre du moteur. Pour la liaison entre le moteur et la charge c'est-à-dire entre leur roue dentée, nous avons utilisé la encore la même qui a servit pour l'autre moteur ce qui a donné le résultat suivant.
Ressources
Composants utilisés
Nom | Boitier/valeur | Documentation/information |
---|---|---|
ATMEGA 32u4 microcontrôleur | CMS | ATMEGA32U4-AU datasheet |
Driver A4935 | CMS |
Fichier:A4935-Datasheet (3).pdf et on a du créé une librairie puisque le composant n'existait pas |
Régulateur de tension | Traversant | connecté avec des condensateurs de 100nF |
ICSP | Traversant | broches de programmation MISO MOSI et SCK correspondent aux numéros de pattes 11,10 et 9 pour l'atmega32u4. |
USB | Traversant | on a du utiliser l'USB puisque les pattes qu'on devait relier au codeur(RX et TX) étaient déjà utilisées |
QUARTZ | 16MHz | Avec une résistance de 1M |
6 Transistors | CMS | le composant n'existait pas donc on l'a créé |
4 Condensateurs de découplage | 680nF | |
6 Résistances | 100K | GHA-GLA-GHB-GLB-GHC-GLC |
Potentiomètres | Traversant | avec une résistance de 50k |
Diodes | Traversant | |
4 LEDS | CMS | Avec des résistances de 330 |
Douille | Traversant | Alimentation |
3 Résistances | 2,K | résistances de tirage reliées au codeur |
2 Résistances | 47K | reliées à FF1 et FF2 avec des leds afin de détecter les défauts |
Condensateurs | 100n et 10u(polarisé) | patte Vreg et alimentations |
Résistances de shunt | 0 | connexion entre le microcontroleur et ALO-BLO-CLO , la patte CSP aussi |
2 boutons poussoirs | Traversant | |
Cosses poignards | Traversant |
Les différentes valeurs des condensateurs se calculent à partir des informations que l'on trouve dans la datasheet de l'A4935.
On a pas pu avoir les valeurs des composants du filtre passe-bas.
Fichier Eagle
Chiffrage de la carte électronique
Après simulation sur le site jlcpb , on a pu avoir une petite carte double face à 6$20.