Cette page vous affiche les différences entre la révision choisie et la version actuelle de la page.
robotics:asservissement_vitesse [2013/02/26 22:39] gdo |
robotics:asservissement_vitesse [2013/03/18 14:30] (Version actuelle) ldo [Asservissement de vitesse d'un moteur] |
||
---|---|---|---|
Ligne 7: | Ligne 7: | ||
Nous utilisons un correcteur de type PID. Il faut appliquer la régulation à chaque moteur. \\ | Nous utilisons un correcteur de type PID. Il faut appliquer la régulation à chaque moteur. \\ | ||
- | {{:robotics:asservissement_vitesse_moteur.jpg?200|}} | + | {{:robotics:asservissement_vitesse_moteur.jpg?400|}} |
+ | === Implémentation === | ||
+ | **asservissement_vitesse()** doit être appelé régulièrement pour que la correction soit efficace (entre 5 et 20 ms). Si on tarde trop à corriger, le système ne sera pas réactif. | ||
+ | |||
+ | **lecture_codeurs()** fait une lecture des codeurs et met à jour **vitesse_moteur_droit** et **vitesse_moteur_gauche**. Pour que les vitesses restent cohérentes entre les appels, il faut appeler asservissement_vitesse() de manière très ponctuelle ou enregistrer le temps entre deux appels. Ici, asservissement _vitesse est appelé toutes les 5 ms. Il faut également lire les codeurs de manière synchrone pour avoir une bonne régulation. | ||
+ | |||
+ | **correcteur_PID()** retourne la commande a envoyé au moteur en fonction de l'erreur. | ||
+ | |||
+ | La structure PID contient les coefficients pour les 3 actions kp, ki et kd du correcteur, l'ancienne erreur (pour D) et le cumul des erreurs ti (pour I). | ||
+ | |||
+ | <code c> | ||
+ | |||
+ | typedef struct | ||
+ | { | ||
+ | signed short kp; | ||
+ | signed short ki; | ||
+ | signed short kd; | ||
+ | signed short ti; | ||
+ | signed short ancienne_erreur; | ||
+ | } PID; | ||
+ | |||
+ | /* pour regulation de vitesse */ | ||
+ | PID pid_vitesse_droite = | ||
+ | { 10, 0, 0, 0, 0 }; | ||
+ | |||
+ | PID pid_vitesse_gauche = | ||
+ | { 10, 1, 0, 0, 0 }; | ||
+ | |||
+ | /* lecture des compteurs */ | ||
+ | void | ||
+ | lecture_codeurs(void) | ||
+ | { | ||
+ | signed short d; | ||
+ | |||
+ | /* chargement de tous les compteurs simultanément */ | ||
+ | load_all_counters(); | ||
+ | |||
+ | /* lecture des compteurs un par un */ | ||
+ | |||
+ | /* moteur droit : vitesse */ | ||
+ | d = distance_totale_moteur_droit; | ||
+ | distance_totale_moteur_droit = read_counter_output(CODEUR_MOTEUR_DROIT); | ||
+ | vitesse_moteur_droit = (distance_totale_moteur_droit - d); | ||
+ | |||
+ | /* moteur gauche : vitesse */ | ||
+ | d = distance_totale_moteur_gauche; | ||
+ | distance_totale_moteur_gauche = -read_counter_output(CODEUR_MOTEUR_GAUCHE); | ||
+ | vitesse_moteur_gauche = (distance_totale_moteur_gauche - d); | ||
+ | } | ||
+ | |||
+ | /* calcule le signal de commande en appliquant un correcteur PID */ | ||
+ | signed short | ||
+ | correcteur_PID(signed short erreur, PID *s) | ||
+ | { | ||
+ | signed short p, i, d; | ||
+ | |||
+ | /* terme proportionel */ | ||
+ | p = erreur * s->kp; | ||
+ | |||
+ | /* terme integral */ | ||
+ | s->ti += erreur; // cumcul des erreurs | ||
+ | |||
+ | // limitation du terme integral | ||
+ | if (s->ti > LIMITE_TERME_INTEGRAL) | ||
+ | { | ||
+ | s->ti = LIMITE_TERME_INTEGRAL; | ||
+ | } | ||
+ | else if (s->ti < -LIMITE_TERME_INTEGRAL) | ||
+ | { | ||
+ | s->ti = -LIMITE_TERME_INTEGRAL; | ||
+ | } | ||
+ | i = s->ti * s->ki; | ||
+ | |||
+ | /* terme derive */ | ||
+ | d = erreur - s->ancienne_erreur; | ||
+ | d *= s->kd; | ||
+ | s->ancienne_erreur = erreur; // sauvegarde de l'ancienne erreur | ||
+ | |||
+ | return p + i + d; | ||
+ | } | ||
+ | |||
+ | /* regulation vitesse moteur droit et gauche | ||
+ | * consigne_vitesse_droite et consigne_vitesse_gauche sont | ||
+ | * les consignes de vitesse droite et gauche en [pulse/cycle] */ | ||
+ | void | ||
+ | asservissement_vitesse(signed short consigne_vitesse_droite, | ||
+ | signed short consigne_vitesse_gauche) | ||
+ | { | ||
+ | signed short erreur_vitesse_droite, erreur_vitesse_gauche; | ||
+ | signed short commande_vitesse_droite, commande_vitesse_gauche; | ||
+ | |||
+ | lecture_codeurs(); | ||
+ | |||
+ | /* regulation vitesse moteur droit */ | ||
+ | erreur_vitesse_droite = consigne_vitesse_droite - vitesse_moteur_droit; | ||
+ | commande_vitesse_droite = correcteur_PID(erreur_vitesse_droite, | ||
+ | &pid_vitesse_droite); | ||
+ | |||
+ | /* regulation vitesse moteur gauche */ | ||
+ | erreur_vitesse_gauche = consigne_vitesse_gauche - vitesse_moteur_gauche; | ||
+ | commande_vitesse_gauche = correcteur_PID(erreur_vitesse_gauche, | ||
+ | &pid_vitesse_gauche); | ||
+ | |||
+ | controle_moteurs(commande_vitesse_droite, commande_vitesse_gauche); | ||
+ | } | ||
+ | </code> | ||
==== Asservissement de vitesse du robot ==== | ==== Asservissement de vitesse du robot ==== | ||
En asservissant les deux moteurs séparément, on devrait théoriquement avoir la même réponse et le robot devrait rouler droit. Malheureusement, en pratique, 2 moteurs d'une même série ne sont pas exactement identiques (inertie, résistance...) donc même en appliquant la même consigne aux moteurs, les 2 vont réagir différemment. Si un des moteurs est plus réactif, il va accélérer plus vite que l'autre et le robot va tourner. | En asservissant les deux moteurs séparément, on devrait théoriquement avoir la même réponse et le robot devrait rouler droit. Malheureusement, en pratique, 2 moteurs d'une même série ne sont pas exactement identiques (inertie, résistance...) donc même en appliquant la même consigne aux moteurs, les 2 vont réagir différemment. Si un des moteurs est plus réactif, il va accélérer plus vite que l'autre et le robot va tourner. |