Aller au contenu


Photo
- - - - -

PID - un banc de test


  • Veuillez vous connecter pour répondre
16 réponses à ce sujet

#1 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 04 novembre 2023 - 12:04

Le PID, c'est comme le piano. Ce n'est pas parce que l'on sait comment cela fonctionne que l'on sait en jouer.

 

J'ai découvert une vidéo de Ian Carey qui propose un banc de test extrêmement facile à réaliser qui permet de s'entrainer à modifier les variables pour bien les maitriser.

L'idée de Ian Carey, avec un Arduino Nano, est de générer une tension de référence (target) sur une sortie PWM au travers d'un filtre Passe Bas. Puis cette tension est réinjectée dans une entrée analogique. C'est ça, le truc génial !

Dans cette vidéo, j'ai également découvert l'influence très importante de dt (delta time) dans le calcul du PID.

 

J'ai modifié son filtre en reprenant un filtre calculé par Sando, avec R=470 et C=100µF. Ce filtre fonctionne parfaitement et génère très peu d'oscillations.

 

J'ai réécrit le programme de Ian Carey à ma manière. Avec 25 lignes de code, j'ai un PID qui fonctionne très bien.

 

Il y a quand même des choses que je ne m'explique pas dans le programme Ian Carey.

Dans la fonction setup(), il initialise l'abscisse à 0 et target , dans une boucle. J'ai voulu supprimer cette boucle, mais le "dessin" caractéristique du début du feedback, disparaissait. Il s'agit de cette oscillation à peu près symétrique sur la ligne de target. En fait, sa boucle camouflait ce problème.

J'ai alors eu l'idée de remplacer cette boucle par une temporisation de 5000ms,  init_time .

J'aimerais bien savoir pourquoi, il est nécessaire de patienter pendant 5 secondes pour avoir ce début d'oscillations.

C'est important, car dans la vraie vie, on peut se demander si on lance le processus immédiatement ou si on doit attendre un petit moment avant que le feedback atteigne la bonne position.

 

Je génère donc l'axe des abscisses et le target dans la fonction loop(). De plus, je génère une ligne symétrique aux abscisses par rapport à la ligne du target. Cela pour que le Plotter Arduino ne zoom pas en fonction des valeurs du feedback.

Je paramètre également un délai à la fin de la fonction loop()loop_time . Ce paramètre est très important car, il détermine le dt , et donc le calcul du PID.

 

Le Plotter Arduino est assez sensible, mais je pense avoir trouver le bon code.

Après avoir lancer le programme, il faut attendre les 5 secondes d'initialisation avant de voir apparaitre le feedback. Il est préférable de cocher "Interpolate" pour avoir une oscillation plus "fluide".

Je pense que l'utilisation du Plotter a une grande influence dans le dt à cause du temps d'exécution des Serial.print() , mais ce délai n'impacte pas négativement le calcul du PID, car si je diminue la variable loop_time , le résultat est impacté négativement.

Il me semble donc nécessaire que le PID soit déterminer dans un lapse de temps minimum, incompressible.

 

Le schéma du banc de test sur une breadbord.

Fichier joint  Schema01_bb.jpg   151,71 Ko   1 téléchargement(s)

 

Le résultat avec mon code.

Fichier joint  PID01.jpg   107,5 Ko   1 téléchargement(s)

 

Mon code :


// Program inspired from the code of Ian Carey https://www.youtube.com/@careyian - 03/11/2023
const int INPUT_PIN = A0;
const int OUTPUT_PIN = DD5;
 
float dt, last_time = 0, init_time = 5000, loop_time = 200, target = 60.00, kp = 0.76, ki = 0.191, kd = 0.0009;
 
void setup(){
  Serial.begin(115200);
  analogWrite(OUTPUT_PIN, 0);
  delay(init_time);
}
 
void loop(){
  float now = millis(); dt = (now - last_time) /1000.00; last_time = now;
  float feedback = map(analogRead(INPUT_PIN), 0, 1024, 0, 255);
  float error = target - feedback;
  float output = pid(error);
  analogWrite(OUTPUT_PIN, (int)output);
  Serial.print(target); Serial.print(","); Serial.print(target*2); Serial.print(","); Serial.print(feedback); Serial.print(","); Serial.println(0);
  delay(loop_time);
}
 
float pid(float error){
  static float integral, previous = error;
  float P = kp * error;
  float I = ki * (integral = integral + error * dt);
  float D = kd * (error - previous) / dt;
  return P + I + D;
}
 
La vidéo de Ian Carey
 
Son code :

// code de Ian Carey https://www.youtube.com/@careyian
// https://youtu.be/RZW1PsfgVEI?si=yrka40X2lhyUlicM
// https://gist.github.com/careyi3/02a57dfd3a62a96d46171489c83488bd#file-pid-ino
 
const int INPUT_PIN = A0;
const int OUTPUT_PIN = DD3;
 
double dt, last_time;
double integral, previous, output = 0;
double kp, ki, kd;
double setpoint = 75.00;
 
void setup()
{
  kp = 0.8;
  ki = 0.20;
  kd = 0.001;
  last_time = 0;
  Serial.begin(9600);
  analogWrite(OUTPUT_PIN, 0);
  for(int i = 0; i < 50; i++)
  {
    Serial.print(setpoint);
    Serial.print(",");
    Serial.println(0);
    delay(100);
  }
  delay(100);
}
 
void loop()
{
  double now = millis();
  dt = (now - last_time)/1000.00;
  last_time = now;
 
  double actual = map(analogRead(INPUT_PIN), 0, 1024, 0, 255);
  double error = setpoint - actual;
  output = pid(error);
 
  analogWrite(OUTPUT_PIN, output);
 
  // Setpoint VS Actual
  Serial.print(setpoint);
  Serial.print(",");
  Serial.println(actual);
 
  // Error
  //Serial.println(error);
 
  delay(300);
}
 
double pid(double error)
{
  double proportional = error;
  integral += error * dt;
  double derivative = (error - previous) / dt;
  previous = error;
  double output = (kp * proportional) + (ki * integral) + (kd * derivative);
  return output;
}

 



#2 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 13 novembre 2023 - 02:43

Faire un filtre passe-bas pourrait en rebuter, quelques uns.

Alors, toujours, en restant dans le même esprit minimaliste que la version précédente, je me suis dit qu'il était peut-être possible de faire encore plus simple.

J'ai donc eu l'idée de générer une fréquence sur une pin, et de la réinjecter sur une autre pin.

Pour générer cette fréquence, j'ai choisi la pin 12 en sortie, et pour la pin en entrée, j'ai choisi la pin 2 qui autorise les interruptions.

Et plutôt que d'utiliser un Arduino Nano et un Breadboard, j'ai préféré un Arduino Uno qui permet de fixer un petit câble de connexions entre ces deux pins.

 

Difficile de faire plus minimaliste pour se lancer dans l'étude du PID. 

 

J'ai également légèrement modifié mon programme pour qu'il soit encore plus simple.

D'autant que, plutôt que de se fixer sur la fréquence, j'ai préféré me fixer sur la période qui est légèrement plus simple à programmer.

 

Le résultat de la courbe du PID est plus conforme à l'orthodoxie et dessine une courbe qui part de 0 et se stabilise rapidement en atteignant la consigne.

Ci-dessous, on peut voir un résultat pour une période 90ms, mais le résultat est tout aussi correcte dans une plage que j'ai testée, de 20ms à 100ms.

 

J'ai bien envie de faire une vidéo, alors avant de publier une bêtise, n'hésitez à me faire part de vos remarques, sur le code.

 

Fichier joint  Plotter01.jpg   99,07 Ko   0 téléchargement(s)Fichier joint  DSC_4082-S-2.jpg   100,27 Ko   0 téléchargement(s)

 

Le code.

// Minimalist workbench PID, based on a frequency period - 11/11/2023
volatile unsigned long feedback, tic, tac=millis();
float prvTime = 0, dt;
float periodTarget = 90.00, kp = 0.30, ki = 6.00, kd = 0.002;
 
void setup(){
  Serial.begin(115200);
  pinMode(12, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2), interrupt, RISING);
}
 
void loop(){
  float time = millis(); dt = (time - prvTime) /1000.00; prvTime = time;
  float pid = PID();
  digitalWrite(12, HIGH); delay(pid/2); digitalWrite(12, LOW); delay(pid/2);
  Serial.print(periodTarget); Serial.print(","); Serial.print(feedback); Serial.print(","); Serial.print(140); Serial.print(","); Serial.println(0);
}
 
float PID(){
  static float errorSum, previousError;
  float error = periodTarget - feedback;
  float P = kp * error;
  float I = ki * (errorSum = errorSum + (error * dt));
  float D = kd * (error - previousError) / dt;  previousError = error;
  return P + I + D;
}
 
void interrupt(){
  tic = millis();
  feedback = tic - tac;
  tac = tic;
}


#3 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 13 novembre 2023 - 10:33

 

 

Et plutôt que d'utiliser un Arduino Nano et un Breadboard, j'ai préféré un Arduino Uno qui permet de fixer un petit câble de connexions entre ces deux pins.

 

Difficile de faire plus minimaliste pour se lancer dans l'étude du PID. 

 

 

Tu aurais pu utiliser une nano et mettre un fil femelle femelle ;) 
En changeant de pin et en prenant le pin 3 à la place du 12 tu aurais même pu mettre un simple cavalier entre 2 et 3 vu qu'ils sont côte à côte ;) 

Ensuite si tu veux quelque chose d'un peu plus " drôle " tu peux choisir une broche PWM ( comme par hasard 3 est aussi une broche PWM ;) ) et chercher à modifier la valeur de pwm pour avoir un temps à l'état haut qui correspond à ce que tu souhaites ( par contre oui dans ce cas il va te falloir mettre ton interruption en " CHANGE " et non plus en RISING ... Et bien compter que le temps à l'état haut dans ton interruption ... ) Il va aussi peut être te falloir changer la fréquence de PWM sur le Timer 2 dans ce cas ... Bref tu peux éventuellement proposer cela dans un deuxième temps ;)


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#4 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 14 novembre 2023 - 08:30

Pour le Nano, il me semble que les broches sont vraiment trop courtes pour un fil femelle/femelle. Et puis, le Uno est souvent considéré comme étant l'Arduino de référence de tout débutant.

J'ai choisi la pin 12, parce que le fil se positionne naturellement dessus. Bien sûr, la pin 3 est plus proche, mais la photo aurait été moins spectaculaire avec un cavalier.

 

J'avais bien pensé au PWM, mais le code aurait été légèrement plus compliqué.

Et puis, ici, je voulais axer la démo sur le PID et non sur le PWM qui est, me semble t-il, un sujet en soi. Mais pour mon UGV, c'est effectivement, le sujet !

 

Sinon, le code ? Pas de loup caché ?



#5 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 15 novembre 2023 - 08:57

Et voilà, la vidéo :

 



#6 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 10 décembre 2023 - 11:54

 

 

Mon code :


// Program inspired from the code of Ian Carey https://www.youtube.com/@careyian - 03/11/2023
const int INPUT_PIN = A0;
const int OUTPUT_PIN = DD5;
 
float dt, last_time = 0, init_time = 5000, loop_time = 200, target = 60.00, kp = 0.76, ki = 0.191, kd = 0.0009;
 
void setup(){
  Serial.begin(115200);
  analogWrite(OUTPUT_PIN, 0);
  delay(init_time);
}
 
void loop(){
  float now = millis(); dt = (now - last_time) /1000.00; last_time = now;
  float feedback = map(analogRead(INPUT_PIN), 0, 1024, 0, 255);
  float error = target - feedback;
  float output = pid(error);
  analogWrite(OUTPUT_PIN, (int)output);
  Serial.print(target); Serial.print(","); Serial.print(target*2); Serial.print(","); Serial.print(feedback); Serial.print(","); Serial.println(0);
  delay(loop_time);
}
 
float pid(float error){
  static float integral, previous = error;
  float P = kp * error;
  float I = ki * (integral = integral + error * dt);
  float D = kd * (error - previous) / dt;
  return P + I + D;
}
 

je note un peu tard une petite erreur dans la fonction pid. 
Il manque une petite ligne 

float pid(float error){
  static float integral, previous = error;
  float P = kp * error;
  float I = ki * (integral = integral + error * dt);
  float D = kd * (error - previous) / dt;
  previous = error; // La ligne qui manquait ...
  return P + I + D;
}

Que tu as bien rajouté dans ta version final ;) 
( On pourrait peut être "masquer mon message " et corriger ton message pour intégrer la ligne ni vu ni connu ;) )


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#7 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 11 décembre 2023 - 08:11

Le code de référence, celui que je montre dans la vidéo à 0'38", est ici : https://www.robot-ma...-test/?p=119892

Dans la ligne qui définit la variable D, à la fin, on peut voir previousError = error;

float PID(){
  static float errorSum, previousError;
  float error = periodTarget - feedback;
  float P = kp * error;
  float I = ki * (errorSum = errorSum + (error * dt));
  float D = kd * (error - previousError) / dt;  previousError = error;
  return P + I + D;
}

Toi, tu fais référence au code qui se trouve plus haut dans le fil, ici : https://www.robot-ma...-test/?p=119805

Mais là également, l'instruction se trouve dans la définition de la variable previous, en static, dans la première ligne.

float pid(float error){
  static float integral, previous = error;
  float P = kp * error;
  float I = ki * (integral = integral + error * dt);
  float D = kd * (error - previous) / dt;
  return P + I + D;
}

Mais pas de souci, au contraire, je te remercie d'avoir jeter un coup d'œil au code.

Et d'ailleurs, si tu trouves un loup dans le code de ce post, https://www.robot-ma...board/?p=120002, je t'en remercie par avance.

 



#8 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 15 décembre 2023 - 03:00

Le code de référence, celui que je montre dans la vidéo à 0'38", est ici : https://www.robot-ma...-test/?p=119892

Dans la ligne qui définit la variable D, à la fin, on peut voir previousError = error;

float PID(){
  static float errorSum, previousError;
  float error = periodTarget - feedback;
  float P = kp * error;
  float I = ki * (errorSum = errorSum + (error * dt));
  float D = kd * (error - previousError) / dt;  previousError = error;
  return P + I + D;
}

 

 

Oui on est d'accord ce code est bien correct :) 


 

 


Toi, tu fais référence au code qui se trouve plus haut dans le fil, ici : https://www.robot-ma...-test/?p=119805

Mais là également, l'instruction se trouve dans la définition de la variable previous, en static, dans la première ligne.

float pid(float error){
  static float integral, previous = error;
  float P = kp * error;
  float I = ki * (integral = integral + error * dt);
  float D = kd * (error - previous) / dt;
  return P + I + D;
}

Mais pas de souci, au contraire, je te remercie d'avoir jeter un coup d'œil au code.

 

Oui en effet c'est bien à ce code dont je fait référence et justement puisque tu as déclaré ta variable en static le travail " previous = error " ne sera fait uniquement la première fois que la fonction est appelée... 

Pour s'en convaincre il suffit de faire un petit essai tout simple  : 

 

void setup() {
  Serial.begin(115200);
  testStatic(42);
}

void loop() {
  testStatic(10);
}

void testStatic(uint8_t val) {
  static uint8_t test = val;
  Serial.println(test);
}

Tu verras que la réponse sera toujours 42 ;) 


Sinon autre point de détail : 

 

 

 

Et d'ailleurs, si tu trouves un loup dans le code de ce post, https://www.robot-ma...board/?p=120002, je t'en remercie par avance.

 

 

Je n'ai pas trouvé de problème spécifique dans ton code, mais j'ai une petite remarque qui ne te concerne pas directement, mais plutôt de manière générale toute personne lisant ces lignes : 

Il peut parfois être tentant de regrouper deux ou même trois petites lignes de code sur la même ligne pour réduire le nombre total de lignes pour pouvoir dire "le code est super court, il fait seulement 63 lignes si on exclut les espaces..." Cependant, regrouper deux lignes de code sur la même ligne n'améliore souvent pas la lisibilité.

 

Pour illustrer davantage ce point, c'est un peu comme si on remplaçait toutes nos variables par a, b, c, d, etc., juste pour dire : "Mon code ne fait que tant de caractères..." Cela ne rend pas le code plus lisible (au contraire, c'est même le principe de l'obfuscation du code).

D'ailleurs, au contraire (et comme tu le fais déjà parfois aussi Oracid), il est parfois préférable de diviser une ligne de code en plusieurs lignes pour améliorer la lisibilité.

 

En général, il faut trouver un équilibre pour le cerveau humain. 
D'un côté, chaque ligne doit contenir une seule information à comprendre, associée à un commentaire bref. Si le commentaire commence à expliquer plusieurs opérations, il serait judicieux de diviser la ligne en plusieurs lignes.
D'un autre côté, il ne faut pas avoir trop de lignes de code pour permettre au cerveau de comprendre facilement le code dans son ensemble.
Souvent, la création de fonctions avec des noms explicites est la meilleure solution, ce que tu fais déjà (par exemple, la fonction PID()).

Bref une remarque un peu hors sujet, mais j'avais envie de l'écrire quelque part. Peut-être qu'un jour, on déplacera ce message vers un sujet plus adapté.


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#9 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 15 décembre 2023 - 08:34

Concernant une variable déclarée en static, tu as parfaitement raison. C'est pour cela que j'ai modifié mon code.

 

Quand à mettre plusieurs instructions sur la même ligne, je pense que si les instructions sont liées par leur destination, alors il n'y a pas de raison de ne pas les mettre sur une même ligne. Bien au contraire, je pense qu'ainsi, on gagne en lisibilité. Et le lecteur doit s'interroger quand il voit une concaténation de plusieurs instructions sur une même ligne. Il comprend qu'elles sont liées.

 

Pour moi, un nombre de lignes important est la principale raison du manque de lisibilité d'un programme.

C'est d'ailleurs pour cette raison que je ne suis pas fan de Python.



#10 TNERA

TNERA

    Membre occasionnel

  • Membres
  • Pip
  • 100 messages

Posté 06 janvier 2024 - 07:22

Hey Ho, everyone!  I have been traveling and missed all the fun about PID!

 

@Oracid, Good work on the demonstration video on YouTube, I just watched it. It is a really tough topic to put on video.

 

One question came to mind.  When tuning PID controllers, consideration is made to the requirements of the response. That is, how much time is required to get to setpoint, is overshoot allowed, how much, and how fast must the signal dampen down to the setpoint.  (apologies, if you all have already discussed this).  It seemed in your example that an overshoot of the setpoint is not allowed. Was this the case?  just curious.



#11 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 10 janvier 2024 - 11:39

I guess it's best if the set point is reached as quickly as possible.
From what I have seen I think it is best if the set point is not exceeded, but it must depend a lot on the configuration and in my opinion this is not a real probleme.


#12 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 262 messages
  • Gender:Male

Posté 10 janvier 2024 - 06:09

@Oracid : as far as I remember, the fastest way to reach the setpoint (and stay there, not just cross it before overshooting) is to have some oscillations (so some overshoot). Reaching the setpoit without overshoot takes a bit longuer. But sometimes oscillations are not desired, so it's better to take a bit more time to settle but avoid overshoot/oscillations.


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.


#13 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 11 janvier 2024 - 09:58

Thank you for your comment Sandro.
Yes, it seems to me that it depends on the goal.
If we apply a PID to a temperature sensor, there should not be much damage if it is exceeded.
On the other hand, exceeding speed on an electric motor can be problematic.


#14 pmdd

pmdd

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 945 messages
  • Gender:Male

Posté 21 avril 2024 - 08:50

Bonjour à tous

 

je furète dans les coins à la recherche de mon projet projet. Dans les potentiels il y a un suiveur de ligne ultra rapide. A ce sujet là, concernant le PID (il y a peut-être déjà la réponse quelque part ici...) , et j'imagine que c'est possible, est-il donc possible et intéressant d'avoir des potentiomètres pour affiner, directement sur le robot , les différents paramètres du PID ?

 

Bon c'est une question préalable, avant que je me penche éventuellement dessus. J'ai des lointains souvenirs de mon projet de fin d'études d'ingé, le pilotage PID d'une pompe à chaleur... ça fait...40 ans  :crazy:  



#15 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 262 messages
  • Gender:Male

Posté 21 avril 2024 - 10:02

Affiner les paramètres du PWM par potentiomètre, pourquoi pas, mais ça présente la difficulté de pouvoir reproduire le réglage.

 

Après, si tu veux faire du suivit de ligne ultra rapide (et pas juste rapide) avec des virages serrés (ie assez pour ne pas pouvoir les passer à vitesse max) avec une caméra pour anticiper la ligne, alors je ne suis pas sûr qu'un contrôleur PID soit le plus adapté. Des contrôleurs que je connais, celui qui me semblerait le plus adapté serait un contrôleur par modèle prédictif (ie un contrôleur qui "simule" la position à t+delta_t pour tous les paramètres possibles, et choisit la meilleure combinaison, ie le plus loin devant sans trop d'erreur par rapport à la ligne et à l'orientation de la ligne). NB : j'ai rapidement vu ça en cours, mais j'ai pas vraiment d'expérience dans ce type de controleur.

Mais je penses que déjà avec du PID, on peut faire de belles choses.


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.


#16 pmdd

pmdd

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 945 messages
  • Gender:Male

Posté 21 avril 2024 - 11:08

Affiner les paramètres du PWM par potentiomètre, pourquoi pas, mais ça présente la difficulté de pouvoir reproduire le réglage.

 

Après, si tu veux faire du suivit de ligne ultra rapide (et pas juste rapide) avec des virages serrés (ie assez pour ne pas pouvoir les passer à vitesse max) avec une caméra pour anticiper la ligne, alors je ne suis pas sûr qu'un contrôleur PID soit le plus adapté. Des contrôleurs que je connais, celui qui me semblerait le plus adapté serait un contrôleur par modèle prédictif (ie un contrôleur qui "simule" la position à t+delta_t pour tous les paramètres possibles, et choisit la meilleure combinaison, ie le plus loin devant sans trop d'erreur par rapport à la ligne et à l'orientation de la ligne). NB : j'ai rapidement vu ça en cours, mais j'ai pas vraiment d'expérience dans ce type de controleur.

Mais je penses que déjà avec du PID, on peut faire de belles choses.

Exact, la reproduction du réglage est un inconvénient, mais pour la mise au point (pour affiner vs le comportement du robot en "réel" cela me semble plus facile

 

Pour ce qui est de la notion d'ultra-rapide, c'est relatif...je voulais dire ultra-rapide pour moi... 

 

mais ce n'est qu'une piste que j'explore pour mon futur projet. Je suis attiré aussi par l'analyse d'image, mais je sais que ce sont les concours qui peuvent me booster.



#17 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 6 769 messages
  • Gender:Male

Posté 21 avril 2024 - 06:26

Mais je penses que déjà avec du PID, on peut faire de belles choses.

Sandro a bien raison !

 

Tu n'iras certainement pas aussi vite que ce que l'on peut voir sur YouTube, mais par exemple, pour concourir à la TRR, avec ton imagination et ta persévérance, tu ne seras certainement pas ridicule.

Les potentiomètres ? Oui, c'est pas mal. Avec des 10 tours, ce serait encore mieux.






0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users