Sur le robot du lien, vu qu'à chaque pas de temps tu multiplie i par Ki=0.001, en gros i est toujours quasi à 0. Donc pas "grave", sauf que tu avais en gros un controleur PD

UGV à base d'éléments de trottinette ou d'hoverboard
#321
Posté 11 avril 2023 - 10:32
Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...
Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.
#322
Posté 11 avril 2023 - 10:55
Sur le robot du lien, vu qu'à chaque pas de temps tu multiplie i par Ki=0.001, en gros i est toujours quasi à 0. Donc pas "grave", sauf que tu avais en gros un controleur PD
Je ne comprends pas.
La ligne entière des paramètres, c'est : float Kp = 0.5625, Ki = 0.001, Kd = 0.055;
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#323
Posté 11 avril 2023 - 11:01
Grace à ma fonction Trace(), j'ai récupéré les valeurs de Throttle (pwm) et de HallSpeed (Hz) avec une version précédente de mon programme où on a :
Throttle = map(analogRead(POT_PIN_IN),0,1023,0,255);
J'ai fait un tableau Excel, dans lequel, on peut voir que la roue commence à tourner à partir d'un PWM égal à environ 100 pour une fréquence d'environ 7,5Hz, et s'arrête de tourner pour un PWM égal à environ 150, et une fréquence d'environ 190Hz.
Je pense donc déterminer la vitesse de référence, variable Speed_Target, en la mappant ainsi : Speed_Target = map( Throttle, 0, 150, 0, 190)
Mais si on considère que ce moteur est différent de ceux montés sur le robot, on pourrait considérer qu'une bonne approximation serait l'égalité entre le PWM et la vitesse de référence. Avec, Speed_Target = Throttle
J'hésite.
Vitesse-data.txt 70,33 Ko
62 téléchargement(s)
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#324
Posté 11 avril 2023 - 11:05
la formule que tu utilises pour i est : i = Ki* (i+err)
Donc :
à t=0 : i=0
à t=1, i=0.001 * err(t=1)
à t=2, i=0.001 * (i + err(t=2)) = 0.001 * (0.001 * err(t=1) + err(t=2)) = 10^-6 * err(t=1) + 10^-3*err(t=2)
à t=3, i=...=10^-9 * err(t=1) + 10^-6*err(t=2) + 10^-3*err(t=3)
...
à t=n, i=somme(10^(-3*k) * err(t=k), pour k de 1 à n).
Autrement dit, le plus gros terme, c'est celui de t=n, qui a un coefficient 10^-3 (qui est déjà négligeable devant Kp=0.5625), et les autres sont tellement négligeables que je ne suis même pas sûr qu'ils ne soient pas supprimés par l'arrondi.
Donc en gros, c'est presque comme si Ki valait 0 (dans un vrai PID), donc il ne reste que le P et le D qui ont une influance non négligeable
Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...
Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.
#325
Posté 11 avril 2023 - 11:16
donc il ne reste que le P et le D qui ont une influance non négligeable
Ah, ok, j'ai compris.
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#326
Posté 11 avril 2023 - 12:44
Pour ton avant dernier message Oracid, l'avantage avec le PID, c'est que tu n'as pas besoin de connaitre de manière précise la relation entre PWM et vitesse. Tu choisis ta vitesse cible, et le PID s'occupe, comme par magie, d'adapter le PWM pour que tu obtienne la vitesse souhaitée.
Pour le réglage du PID, c'est "simplement" dire de quelle manière tu veux tenter de corriger la vitesse :
- P : si je suis trop lent, j'appuis sur l'accélérateur, si je suis trop rapide, j'appuie sur le frein (nb : si tu es pile à la bonne vitesse, tu laches l'accélérateur : tu vas donc naturellement ralentir). Un controleur avec que du P aura tendence à être toujours un peu trop lent (ou alors à osciller si Kp est trop grand et que ton robot a trop d'inertie)
- I : si ça fait un bout de temps que je suis en dessous de ma vitesse cible, j'accélère un peu (en voiture : sur du plat, tu garde ton accélérateur dans une position constante (=V_target). Quant tu arrives à une montée, cette position de l'accélérateur te donne une vitesse (<V_target) plus faible que souhaité. Après quelques secondes, tu te rends compte que tu vas pas assez vite, donc tu appuie un peu plus sur l'accélérateur)
- D : si ta vitesse est en train de monter vite, alors tu réduis les gaz (en voiture : tu sors de ville, et tu accélères pied au plancher pour atteindre les 80km. Si tu gardes le pied au plancher à 79.9 km/h, tu vas surement faire un excès de vitesse. Donc quand tu vois que ta vitesse augmente rapidement, tu appuie un peu moins fort sur l'accélérateur
Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...
Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.
#327
Posté 11 avril 2023 - 06:23
Ce n'est pas la première fois que je lis une analogie du PID avec l'accélérateur d'une voiture, mais c'est c'est la première que cette analogie est poussée jusqu'au détail de chaque paramètre.
Sandro, tu devrais écrire un livre sur le PID. Un livre du style, "Le PID pour les Nuls". Tu aurais un grand succès !
Merci Sandro
"l'avantage avec le PID, c'est que tu n'as pas besoin de connaitre de manière précise la relation entre PWM et vitesse. Tu choisis ta vitesse cible, et le PID s'occupe, comme par magie, d'adapter le PWM pour que tu obtienne la vitesse souhaitée."
Là, par contre, je suis largué !
J'ai extrapolé la droite du tableau Excel. Pour un PWM de Throttle=255, je trouve un Target_Speed, d'environ 350Hz.
Donc, dans le loop(), je peux faire :
Throttle = map( analogRead(POT_PIN_IN), 0, 1023, 0, 255);
Target_Speed = map( Throttle, 0, 255, 0, 350 );
puis, dans la fonction P_I_D() :
pid_Speed = map( (unsigned int) pid_Speed, 0, 350, 0, 255 );
puis dans le loop():
analogWrite(PWM_PIN_OUT, pid_Speed);
Peut-être, ne suis-je pas très clair.
Je teste cela demain et je publie la nouvelle version du programme en entier, ce sera peut-être plus clair.
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#328
Posté 12 avril 2023 - 07:05
Grace à ma fonction Trace(), j'ai récupéré les valeurs de Throttle (pwm) et de HallSpeed (Hz) avec une version précédente de mon programme où on a :
Throttle = map(analogRead(POT_PIN_IN),0,1023,0,255);
J'ai fait un tableau Excel, dans lequel, on peut voir que la roue commence à tourner à partir d'un PWM égal à environ 100 pour une fréquence d'environ 7,5Hz, et s'arrête de tourner pour un PWM égal à environ 150, et une fréquence d'environ 190Hz.
Je pense donc déterminer la vitesse de référence, variable Speed_Target, en la mappant ainsi : Speed_Target = map( Throttle, 0, 150, 0, 190)
Mais si on considère que ce moteur est différent de ceux montés sur le robot, on pourrait considérer qu'une bonne approximation serait l'égalité entre le PWM et la vitesse de référence. Avec, Speed_Target = Throttle
J'hésite.
Bonjour,
L'approximation "Vitesse donne PWM", même si elle est faite à vide au début (à refaire sur sa terrasse avec son robot, plus tard), peut être utilisée en complément de l'asservissement à base de PID.
PWM = PID(erreur_vitesse) + Kff * consigne_vitesse
avec Kff : le coefficient qui te permet d'approcher la valeur de PWM en fonction de la vitesse de consigne.
Note : FF pour Feed-Forward.
Evidemment, le terme ff ne marche pas à très basse vitesse. Mais ca permet d'approcher la vitesse d'évolution en condition "normale".
Avec la carte hoverboard, je constate aussi que le 'trou' dans la plage [0,50]. Le PID bien réglé va en grande partie compenser ce problème.
En général, je règle dans l'ordre :
1) Kff,
2) Kp,
3) Kd
4) optionnel Ki.
Avec ces moteurs et les contrôleurs BLDC pour EPDM, qui ont un PID intégré avec une faible bande passante, je me suis retrouvé à régler dans l'ordre :
1) Kff
2) Ki,
3) optionnel : Kp et Kd.
Les deux derniers ont conservé des valeurs faibles. Car ils apportent plus de problèmes que de véritables gains/performances.
Je suis preneur de votre retour d'expérience au niveau des réglages (et de vos valeurs, même si ca dépend de beaucoup de paramètres dont la cadence du PID et les unités de mesure/consigne employées).
Bon courage.
Patrick.
#329
Posté 12 avril 2023 - 08:39
Merci Patrick pour toutes ces précisions.
Actuellement, je travaille à vide sur mon banc de test, mais effectivement, j'ai bien conscience que lorsque le robot sera posé au sol, il faudra revoir les paramètres du PID.
Intéressant, le paramètre Kff. Je mets ça dans un coin de ma tête.
L'ordre de réglage des paramètres, oui, ça fait parti de la prise de tête.
Pour aujourd'hui, je vais continuer à mapper les PWM en Hz.
Dans cette page, conseillée par Mike, https://www.pm-robot...robot-autonome/ , il y a déjà quelques temps, on peut voir une fonction PID avec un calcul de i très classique.
Je n'arrive pas à faire l'équivalence entre ce que j'utilise dans mon programme, méthode conseillée par toi Sandro, et le calcul de ce programme.
Sandro : i = i+(Ki*err);
pm-robotix : errSum += error; i = errSum * ki;
Voici ce programme :
//Nos trois coefficients static int kP=100; static int kI=10; static int kD=50; int ComputePID(int error) { static int lastError=0; static int errSum=0; int P,I,D; errSum += error; //Somme les erreurs depuis le début errDif = error - lastError; //Calcule la variation de l'erreur lastError = error; P = error * kP; //Proportionnelle I = errSum * kI; //Intégrale D = errDif * kD; //Dérivée return P + I + D; //Le résultat est la somme des trois //composantes calculées précédemment }
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#330
Posté 12 avril 2023 - 11:09
Voici la dernière version de mon programme (V3).
Et voici la trace :
Dans le programme, notez que Kp = 1.02, Ki = 0.000, Kd = 0.00
Dans cette trace, on peut voir que les valeurs des variables Throttle et TargetSpeed sont respectivement très proches des valeurs des variables pidSpeed et pid. J'ai bloqué le potentiomètre pour Throttle=110 pwm.
Avec ma main gantée, j'ai freiné la roue. On s'en aperçoit grâce à la valeur de la variable HallSpeed qui vaut environ 33Hz et qui passe à 25Hz.
Mais les valeurs de pidSpeed et pid ne sont pas modifiées.
C'est trop beau que ce soit bon du premier coup, et en paramétrant seulement Kp=1.02
Il y a surement un loup. Pourquoi les valeurs de pidSpeed et pid ne varient pas ?
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#331
Posté 12 avril 2023 - 05:40
Si la vitesse réelle est différente de la vitesse consigne, et que la valeur de PWM donnée par la sortie PID ne varie pas de telle sorte à réduire l'erreur de vitesse .... c'est que ca ne marche pas du tout ! :-)
Pour tester ton PID, tu peux afficher :
1) consigne de vitesse
2) vitesse réelle
3) valeur PWM (=sortie PID).
#332
Posté 12 avril 2023 - 05:57
Tu peux supprimer un paquet de conversions de plages de valeurs, remonter PID() avant analogwrite() et limiter la plage de valeur en sortie du PID.
Pour mieux contrôler la vitesse (voir mon test en pente), tu peux exploiter le signe de la sortie du PID pour freiner la roue. Attention, au sens de rotation (inverser 0 et 1 si besoin).
void loop() { if (! digitalRead(pb)) { Serial.print("\n\t Operator Interrupt !!!"); delay(400); analogWrite(PWM_PIN_OUT,0); resetFunc(); } Throttle = analogRead(POT_PIN_IN); // the Throttle [0..1023] Target_Speed = map(Throttle,0,1023,0,max_Hz); // convert the Throttle into speed (Hz) if ( new_tick == prev_tick) { Period = 0; HallSpeed = 0; } // stop the wheel if no order P_I_D(); // convert speed error into signed WM [-255,+255] analogWrite(PWM_PIN_OUT, abs(pid_Speed)); // the PWM is determined by the | P_I_D() | if(pid_Speed >=0 ) // the DIRECTION is determined by the sign of P_I_D() digitalWrite(DIR_PIN_OUT, 0); else digitalWrite(DIR_PIN_OUT, 1); Trace(); } void P_I_D(){ err = Target_Speed - HallSpeed; // getting err p = Kp*err; i = i+(Ki*err); // note : limiter la valeur de i, par exemple : i = constrain(i+Ki*err,-255,255); d = Kd*(err-lastErr); lastErr = err; pid = p+i+d; // calculation of the PID pid_Speed = constrain(pid ,-255,255); // clamp [0..255[ }
#333
Posté 12 avril 2023 - 06:32
Merci Patrick. Je vais revoir tes propositions dès demain matin.
Pour ce soir, j'ai fait une nouvelle version, car effectivement cela ne fonctionne pas du tout.
Le gros problème, c'est que la première instruction de la fonction P_I_D(), err = Target_Speed - HallSpeed; ne fonctionne absolument pas.
j'ai tracé la variable err , c'est comme si la variable HallSpeed était toujours égale à 0.
Voici la trace:
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#334
Posté 13 avril 2023 - 07:36
Pour mieux contrôler la vitesse (voir mon test en pente), tu peux exploiter le signe de la sortie du PID pour freiner la roue.
J'ai fait une nouvelle version où j'ai bien pris en compte tes modifications, mais par contre, je ne comprends pas cette dernière remarque.
Pour l'instant, je ne vais pas m'occuper du changement de sens de rotation, pour faire au plus simple.
Néanmoins, cela ne fonctionne toujours pas. L'instruction, err = Target_Speed - HallSpeed; dans la fonction P_I_D() ne fonctionne pas.
La variable err est toujours égale à Target_Speed.
La nouvelle version :
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#335
Posté 13 avril 2023 - 09:05
Dans ta fonction de calcul du PID, tu écris :
err = Target_Speed - HallSpeed;
Juste avant l'appel PID(), tu écris :
if ( new_tick == prev_tick) { Period = 0; HallSpeed = 0; }
Et dans ta routine d'IT qui estime la vitesse courante, tu as :
prev_tick = new_tick ;
Effectivement, le calcul de l'erreur ne se passe pas comme prévu !
Patrick.
#336
Posté 13 avril 2023 - 10:49
Merci Patrick.
J'ai mis la ligne du if en commentaire, mais je pense qu'il va falloir la supprimer.
Dans la fonction P_I_D(), j'ai modifié cette ligne en pid_Speed = constrain(pid ,0,255); pour n'avoir que des valeurs positives. On verra plus tard pour le changement de direction.
Le résultat est plutôt encourageant. En basse vitesse, les variations de vitesses sont très importantes, mais à plus haute vitesse, il y a une certaine stabilisation. Je mets les 2 traces correspondantes.
Je suppose qu'il va falloir que je trouve les bonnes valeurs du PID pour éviter ces à-coups.
Avec : Kp = 2.1, Ki = 0.0, Kd = 0.0
Basse vitesse :
Haute vitesse :
Ma chaine YouTube : https://www.youtube..../oracid1/videos
#339
Posté 13 avril 2023 - 01:26
Avec Kp = 1.0, Ki = 0.0, Kd = 0.0
Trace de 0Hz à 100Hz. Le moteur ne tourne pas.
Trace de 100Hz à 200Hz
Ma chaine YouTube : https://www.youtube..../oracid1/videos
Répondre à ce sujet

2 utilisateur(s) li(sen)t ce sujet
0 members, 2 guests, 0 anonymous users