Commande de moteurs à courant continu et pas à pas par FPGA L’objectif de cette séance est de commander un moteur à courant continu puis un moteur pas à pas par l’association de la carte de développement DE2 et d’une carte auxiliaire intégrant les circuits de puissances. A travers la synthèse de ces projets, nous nous familiariserons avec la notion de machine d’état. 1 Descriptif de la carte auxiliaire Nous utilisons pour notre carte auxiliaire un circuit L298, au sein duquel sont implantés deux ponts en H, associé à la logique de commande, comme l’indique la structure interne de ce circuit sur la figure suivante : Comme on peut le noter sur la figure précédente, les diodes de puissance ne sont pas intégrées dans le L298, il faut les ajouter sur la carte, comme le montre la figure suivante. Il est alors possible de commander deux moteurs à courant continu (sortie OUT1-OUT2 ou bien OUT3-OUT4) ou un moteur pas à pas bipolaire deux phases (les deux phases étant connectée respectivement en OUT1-OUT2 et OUT3-OUT4). Denis Rabasté 1/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA L’alimentation Vss en 5V (partie commande) est faite directement par la carte DE2, tandis que l’alimentation de puissance Vs se fait par les entrées « + » et « masse » de la carte auxiliaire via une source externe, avec une tension dépendant des moteurs utilisés (maximum 46 V). Une diode de protection évite l’inversion de polarité de l’alimentation (mais crée une chute de tension de 0,7 V). Deux résistances « shunt » RS1 et RS2 permette de mesurer le courant passant par les transistors de puissance. Les bornes du FPGA reliées au circuit L298 sont données en annexe. 2 Alimentation de puissance de la carte et mesure Pour alimenter la partie puissance le la carte, respecter le protocole suivant : - utiliser pour Vs une alimentation stabilisée incluant une limitation de courant ; - l’alimentation étant déconnectée de la carte, régler sa sortie à 6 V ; - mettre la sortie en court-circuit et limiter le courant à 0,5 A ; - supprimer le court-circuit et relier maintenant l’alimentation à la carte auxiliaire. Pour effectuer des mesures à l’oscilloscope, on placera les sondes aux points tests prévus à cet effet, et uniquement sur ces points. Les parties du schéma associées à ces points tests sont donnés en annexe. 3 Mise en œuvre de la commande d’un moteur à courant continu 3.1 Descriptif du programme Nous allons tester notre carte en pilotant un moteur à courant continu. Nous implantons pour cela dans le FPGA de la carte DE2, le programme correspondant au descriptif suivant : div_50 H INPUT VCC H PIN_N2 C_OUT S PIN_R24 inst3 OUTPUT MLI Seq bp_imp PIN_G26 BP1 BP2 H BP1 BP2 INPUT VCC INPUT VCC PIN_N23 RST IMP_BP1 IMP_BP2 CONS[7..0] PIN_M19 OUTPUT S_MLI NS_MLI OUTPUT S_MLI NS_MLI OUTPUT NS_MLIB PIN_M23 PIN_R20 VCC inst BP1 clock RST reset BPLUS BMOINS H C_EN CONS[7..0] inst5 S_MLIB inst4 OUTPUT LED_BP2 PIN_W19 OUTPUT LED_BP1 PIN_AE22 OUTPUT LED_RST PIN_AA20 PIN_N24 OUTPUT ENA OUTPUT ENB PIN_K25 RST INPUT VCC PIN_W26 Ce programme génère en sortie un signal modulé en largeur d’impulsion, « S_MLI » est envoyé sur l’entrée In1 du circuit L298, tandis que son complémentaire « NS_MLI » est envoyé sur l’entré In2. L’entrée ENA du L298 est fixée au niveau logique 1. Les mêmes signaux « S_MLIB » « NS_MLIB » et Vcc sont envoyés sur les commandes du second pont via les entrées In3, In4 et ENB. Les signaux modulé en largeur d’impulsion sont obtenus en comparant la valeur d’un signal de consigne « CONS[7..0] » sur huit bits, à la valeur de sortie d’un compteur huit bits, incrémenté par le signal d’horloge à 50 Mz lorsque le signal d’autorisation C_EN (Clock Enable), à environ 5 MHz le permet. Le cycle complet de 28=256 impulsions, correspond alors a une fréquence de découpage de 5 MHz/256, soit environ 20 kHz. Denis Rabasté 2/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA Le signal C_OUT (alimentant C_EN) à 5 MHz est obtenu par la division par 10 de l’horloge à 50 MHz de la carte DE2, par le bloc « div_50 ». Grâce au bloc séquenceur « SEQ », ce programme test va permettre de régler 5 vitesses différentes pour le moteur, en fonction de l’appui sur les boutons poussoir BP1 et BP2 (ce qui générera les signaux BPLUS et BMOINS) de la carte DE2. Pour passer à la vitesse supérieure ou inférieure ; ces 5 vitesses correspondent à 5 valeurs de la consigne « CONS » et donc à 5 valeurs de rapport cyclique aux bornes du moteur. On établi sans difficulté que le rapport cyclique α est donné par l’expression : α= CONS/255, et la tension moyenne aux bornes du moteur par la relation classique d’un pont en H : Umoy = Vs (2 α-1) Vs étant la tension d’alimentation du pont Les 5 valeurs de consigne imposées par le séquenceur sont : - 0, ce qui correspond à une vitesse maximale du moteur en sens négatif (α=0, Umoy=-Vs) ; - 64, soit la moitié de la vitesse maximale du moteur, en sens négatif (α=0,25, Umoy=-Vs/2) ; - 128, soit une vitesse nulle (α=0,5, Umoy=0) ; - 192, soit la moitié de la vitesse maximale en sens positif (α=0,75, Umoy=Vs/2) ; - 255, soit la vitesse maximale en sens positif (α=1, Umoy=Vs). Le fonctionnement du séquenceur a été décrit par la machine d’état suivante (voir le sujet sur la machine d’état pour plus de précisions) : Le passage d’un état au suivant, se fait à chaque coup d’horloge en testant les boutons poussoir : - pour augmenter la vitesse (en valeur relative), il faut vérifier la condition BPUS . BMOINS (ce qui se traduit par « BPLUS & ~BMOINS » dans la syntaxe de description de machine d’état au sein de Quartus), - pour diminuer la vitesse, il faut vérifier la condition BMOINS . BPLUS ; une réinitialisation de la machine d’état, par appui sur le bouton poussoir « RST », place celleci dans l’état E128, qui correspond à l’arrêt du moteur ; Remarques : l’utilitaire de description de machine d’état de Quartus impose que les conditions de passage d’un état à l’autre soit exclusives (deux conditions ne peuvent être valides en même temps) ; on ne peut donc avoir comme conditions BPLUS pour une branche et BMOINS pour l’autre. L’horloge du système fonctionnant à 50 MHz, les informations BPLUS et BMOINS sont testées 50 millions de fois par secondes ; pour un fonctionnement correct, un appui sur les boutons poussoirs correspondants, doit donc durer une impulsion d’horloge. Denis Rabasté 3/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA Le bloc « BP_IMP » a pour rôle de convertir le NL0 de durée aléatoire, obtenu lors de l’appui sur les boutons poussoir BP1 et BP2, en signaux au NL1 de durée 20 ns (soit une période de l’horloge à 50 MHz). Le bloc « BP_IMP » peut être vu comme un détecteur de front descendant. Comme on peut le voir sur le schéma général associé au programme, les différents boutons poussoirs sont associés à des DEL, afin d’en visualiser l’appui. 3.2 Mise en œuvre Ouvrir un nouveau projet dans Quartus. Proposer un programme VHDL permettant de synthétiser les blocs « div_50 » et « MLI » ; simuler les solutions obtenues. Etudier la syntaxe VHDL du bloc BP_IMP donné en annexe et dans le dossier ressource « ressources/TP_Quartus/TP6_mcc_pap/mcc » et simuler le fonctionnement du programme. Synthétiser le séquenceur « Seq » à l’aide de l’utilitaire de Quartus (voir le cours sur les machines d’état) et simuler le résultat. Regrouper ces sous ensembles dans un schéma général, compiler le projet et programmer le FPGA sans alimenter la carte auxiliaire et vérifier à l’oscilloscope que le fonctionnement est bien celui attendu. Connecter le moteur et l’alimentation suivant le protocole indiqué au chapitre 2, et tester le fonctionnement. En cas de problèmes, on trouvera des exemples de solutions dans le dossier ressource et en annexe. 4 Mise en œuvre de la commande d’un pas à pas 4.1 Descriptif du programme Le programme implanté dans le FPGA de la carte DE2 est associé au schéma suivant : div_1s INPUT VCC H C_EN H PIN_N2 C_OUT S OUTPUT PH[3..0] PIN_M19 PIN_M23 PIN_R24 PIN_R20 inst2 SEQ DECODEUR C_EN RST INPUT VCC PIN_W26 Sens INPUT VCC PIN_G26 P_demiP INPUT VCC RST PIN_N23 Sens P_demiP clock C_EN reset S P inst PH[3..0] ETAT[3..0] BCD[3..0] OUTPUT SEG[6..0] PIN_AF10 PIN_AB12 PIN_V13 PIN_V14 PIN_AC12 PIN_AD11 PIN_AE11 inst1 OUTPUT LED_RST PIN_AA20 OUTPUT LED_SENS PIN_AE22 OUTPUT SEG[6..0] LED_p_demip PIN_W19 VCC OUTPUT ENA PIN_N24 OUTPUT ENB PIN_K25 Le bloc « div_1s » nous génère un signal d’horloge de période 1 secondes, en divisant par 50 millions l’horloge à 50 MHz de la carte DE2. Cette horloge d’une seconde va commander un séquenceur, permettant au moteur de fonctionner dans un sens ou dans l’autre suivant que le bouton poussoir relié à l’entrée « Sens » est appuyé ou non, et en mode « pas entiers une phase » ou en mode « demi-pas » suivant que le bouton poussoir associé à l’entrée « P_demiP » est appuyé ou non. La sortie « PH[3..0] » du séquenceur envoie les signaux adéquat sur les entrées In1 à In4 du circuit L298, suivant les chronogrammes représentés ci-dessous : Denis Rabasté 4/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA Fonctionnement en mode pas entier une phase (un seul sens de rotation représenté) Fonctionnement en mode demi-pas (un seul sens de rotation représenté) Un bouton poussoir associé à l’entrée « RST » permet de réinitialiser le séquenceur. Des diodes électroluminescentes de la carte DE2 permettent de visualiser l’appui sur ces boutons. On notera que le séquenceur est rendu synchrone grâce à une entrée d’autorisation d’horloge « C_EN ». Contrairement au programme précédent, le rapport de division de l’horloge étant important, cette option est ici indispensable. La machine d’état suivant décrit le fonctionnement de notre séquenceur : Comme indiqué précédemment, le passage d’un état à l’autre se fait : - uniquement si « C_EN » est au NL1 quel que soit les états, - dans un sens ou dans l’autre suivant l’entrée « S », - en passant par tous les états, ou juste les états pairs, suivant l’entrée « P ». La sortie « PH[3..0] du séquenceur commande les entrés Inx du L298, tandis que la sortie « ETAT[3..0] » permet de visualiser le numéro de l’état actif, et de l’indiquer sur un afficheur 7 segments de la carte DE2, grâce au bloc « DECODEUR », réalisant la conversion BCD / 7 segments. Denis Rabasté 5/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA 4.2 Mise en œuvre Ouvrir un nouveau projet sous Quartus, importer le diviseur de projet précédent, le sauvegarder dans le nouveau projet afin d’éviter que sa modification n’affecte l’étude précédente, et modifier le programme pour répondre au nouveau cahier des charges. Proposer un programme VHDL pour le décodeur. Synthétiser le séquenceur à l’aide de l’utilitaire de Quartus et tester la solution obtenue. Regrouper les sous ensembles en un schéma général et programmer le FPGA sans alimenter la carte auxiliaire, vérifier au niveau de l’afficheur que le fonctionnement est bien celui attendu (dans un sens dans l’autre, en mode pas entier, demi-pas). Connecter la sonde de l’oscilloscope sur les points tests correspondants aux entrées In1 et In4 et vérifier l’effet des différents modes de fonctionnement. Connecter le moteur et l’alimentation suivant le protocole indiqué au chapitre 2, et tester le fonctionnement. En cas de problème, on trouvera un exemple de solution en annexe et dans le dossier ressources « ressources/TP_Quartus/TP6_mcc_pap/pap » Annexe 1 : connectique de la carte Broche du L298 sur la carte auxiliaire Broche du FPGA sur la carte DE2 Nom de la borne sur la carte DE2 Borne du connecteur GPIO_1 Carte DE2 Repère sur la carte DE2 Couleur sur la carte auxiliaire 5 : In1 6 : EnA 7 : In2 10 : In3 11 : EnB 12 : In4 M19 N24 M23 R24 K25 R20 GPIO_1[4] GPIO_1[10] GPIO_1[3] GPIO_1[13] GPIO_1[0] GPIO_1[14] 5 13 4 16 1 17 IO_B4 IO_B10 IO_B3 IO_B13 IO_B0 IO_B14 Blanc Vert Jaune Jaune Vert Blanc Denis Rabasté 6/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA Annexe 2 : Programmes associés à la commande d’un moteur à courant continu Block BP_IMP : détecteur de front descendant LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; --les paquetages std_logic_1164 et std_logic_unsigned de la bibliothèque ieee --permettent respectivement l'utilisation du type std_logic et l'addition avec ce type --à chaque appui sur les boutons poussoirs (NL0 sur la carte DE2), -- les sorties correspondantes génère une impulsion unique --d'un seul coup d'horloge (détection du front descendant) ENTITY bp_imp IS port ( H BP1, BP2 IMP_BP1, IMP_BP2 : IN STD_LOGIC; : IN STD_LOGIC; : OUT STD_LOGIC); END bp_imp; ARCHITECTURE arch OF bp_imp IS SIGNAL BP10, BP11, BP20, BP21 : STD_LOGIC; BEGIN -- à chaque front d'horloge, le niveau de l'entrée BPx est affecté à BPx0 -- au coup d'horloge suivant BPx0 est affectée à BPx1 -- une fonction ET entre BPx0 et le complémentaire de BPx1 permet de détecter le front descendant sur BPx PROCESS (H) BEGIN IF (H'EVENT AND H = '1') THEN BP10<= BP1; BP11<= BP10; BP20<= BP2; BP21<= BP20; END IF; END PROCESS; IMP_BP1<=BP11 AND NOT BP10; IMP_BP2<=BP21 AND NOT BP20; END arch; Block div_50 : division de l’horloge LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; --les paquetages std_logic_1164 et std_logic_unsigned de la bibliothèque ieee --permettent respectivement l'utilisation du type std_logic et l'addition avec ce type --H est le signal d'horloge à 50 MHz --S est un signal de rapport cyclique 1/2, résultant de la division de l'horloge --C_OUT est le signal de retenue qui passe au NL1 lorsque le compteur est plein --le rapport de division dépend du modulo M --ajuster en conséquence le nombre de bits du compteur interne X Denis Rabasté 7/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA --pour notre application on souhaite un signal à environ 256*20 kHz --il faut donc diviser par 10, ce qui nécessite 4 bits pour X ENTITY div_50 IS port ( H C_OUT S : IN STD_LOGIC; : OUT STD_LOGIC; : OUT STD_LOGIC); END div_50; ARCHITECTURE archdiv OF div_50 IS SIGNAL X : STD_LOGIC_VECTOR (3 downto 0); CONSTANT M : INTEGER :=10 ; BEGIN PROCESS (H) BEGIN --compteur modulo M IF (H'EVENT AND H = '1') THEN IF X >= M-1 THEN X <= (others=>'0'); --mise à 0 de tous les bits de X ELSE X <= X + 1 ; END IF; END IF; END PROCESS; --à la moitié du comptage on change la valeur de S (rapport cyclique 1/2) S<='1' when X>=M/2 else '0'; --mise à 1 de la retenue lorsque X passe à 0 C_OUT<='1' when X=M-1 else '0'; END archdiv; Block MLI : Modulateur de largeur d’impulsion LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; --les paquetages std_logic_1164 et std_logic_unsigned de la bibliothèque ieee --permettent respectivement l'utilisation du type std_logic et l'addition avec ce type ENTITY MLI IS --génération d'un signal MLI et son complémentaire en S_MLI et NS_MLI --l'horloge H incrémente un compteur X , si C_EN l'autorise --la sortie du compteur X est comparée à la consigne CONS port ( H C_EN CONS S_MLI NS_MLI : IN STD_LOGIC; : IN STD_LOGIC; : IN STD_LOGIC_VECTOR(7 DOWNTO 0); : OUT STD_LOGIC; : OUT STD_LOGIC); END MLI; ARCHITECTURE archdiv OF MLI IS SIGNAL X : STD_LOGIC_VECTOR (7 downto 0); CONSTANT M: INTEGER :=256 ; Denis Rabasté 8/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA BEGIN PROCESS (H) BEGIN --compteur modulo M IF (H'EVENT AND H = '1') THEN IF C_EN='1' then IF X >= M-1 THEN X <= (others=>'0'); --mise à 0 de tous les bits de X ELSE X <= X + 1 ; END IF; END IF; END IF; END PROCESS; --lorsque la consigne devient supérieure au comptage S_MLI passe au NL1 S_MLI <='0' when X>= CONS else '1'; NS_MLI <='1' when X>= CONS else '0'; END archdiv; Annexe 3 : Programmes associés à la commande d’un moteur pas à pas Block div_1s LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; --les paquetages std_logic_1164 et std_logic_unsigned de la bibliothèque ieee --permettent respectivement l'utilisation du type std_logic et l'addition avec ce type ENTITY div_1s IS --H est le signal d'horloge à 50 MHz --S est un signal de rapport cyclique 1/2, résultant de la division de l'horloge --C_OUT est le signal de retenue qui passe au NL1 lorsque le compteur est plein --le rapport de division dépend du modulo M --ajuster en conséquence le nombre de bits du compteur interne X --pour notre application on souhaite un signal à 1 Hz --il faut donc diviser par 50 000 000, ce qui nécessite 26 bits pour X (2^26=67 108 864) port ( H C_OUT S : IN STD_LOGIC; : OUT STD_LOGIC; : OUT STD_LOGIC); END div_1s; ARCHITECTURE archdiv OF div_1s IS SIGNAL X : STD_LOGIC_VECTOR (25 downto 0); CONSTANT M: INTEGER :=50000000 ; BEGIN PROCESS (H) Denis Rabasté 9/10 IUFM Aix Marseille Commande de moteur à courant continu et pas à pas par FPGA BEGIN --compteur modulo M IF (H'EVENT AND H = '1') THEN IF X >= M-1 THEN X <= (others=>'0'); --mise à 0 de tous les bits de X ELSE X <= X + 1 ; END IF; END IF; END PROCESS; --à la moitié du comptage on change la valeur de S (rapport cyclique 1/2) S<='1' when X>=M/2 else '0'; --mise à 1 de la retenue lorsque X passe à 0 C_OUT<='1' when X=M-1 else '0'; END archdiv; Bloc DECODEUR -- la bibliothèque ieee contient les paquetages dont la déclaration suit library ieee; --ce paquetage permet l'utilisation des types STD_LOGIC et STD_LOGIC_VECTOR use ieee.std_logic_1164.all; -- permet d'utiliser le type STD_LOGIC_VECTOR avec des entiers use ieee.std_logic_unsigned.all; entity DECODEUR is port (BCD SEG end DECODEUR; 0 ------------l 0 l -5 l l1 -l l ---------l 6 l -4 l l2 -l l -----------3 : in STD_LOGIC_VECTOR (3 downto 0); : out STD_LOGIC_VECTOR ( 6 downto 0) ); architecture ARCH_DEC of DECODEUR is begin -- attention les leds s'allument pour une sortie à 0 SEG <= "1000000" when BCD=0 else "1111001" when BCD=1 else "0100100" when BCD=2 else "0110000" when BCD=3 else "0011001" when BCD=4 else "0010010" when BCD=5 else "0000010" when BCD=6 else "1111000" when BCD=7 else "0000000" when BCD=8 else "0010000" when BCD=9 else "1111111" ; end ARCH_DEC ; Denis Rabasté 10/10 IUFM Aix Marseille