Go Down

Topic: Impact attachInterrupt sur PID (contrôleur) (Read 571 times) previous topic - next topic

Vincent_TH

Bonjour à tous,
Depuis plusieurs semaines, un problème me bloque sur ma MEGA 2560. Je veux contrôler en position un mobile sur un rail. Il est mis en mouvement par un moteur Pololu 30 :1 équipé d'un encoder. Pour connaitre la position du mobile, j'utilise à la fois l'encoder et un capteur infra-rouge sharp. Pour l'encoder, j'utilise la fonction attachInterrupt -> position moteur -> position mobile.
Mon problème est simple :
Même si je cadence mon PID à 50 ms (discret), la fonction attachInterrupt vient mettre le bazar dans mon PID en lui faisant perdre les pédales… C'est comme si la fonction attachInterrupt crée des interruptions fortes sur mon PID et les termes I et D, n'aiment pas du tout (il saute des pas où les pas durent plus longtemps…).
De façon, plus générale, j'ai constaté les mêmes problèmes lorsque j'utilise les fonctions basiques comme Serial.print (très utile pour calibrer le PID en visualisant les sorties sous « Processing »), ou encore des capteurs utilisant l'i2c.
Je pense que c'est un problème courant lorsque qu'on couple des contrôleurs (PID ou autre) avec des capteurs utilisant les interruptions sur Arduino. De façon générale comment vous vous en sortez ?
Merci par avance pour le coup de main
Vincent


rjnc38

il faut faire le bilan des PWM, timers et interrupt utilisés pour voir s'il y a conflit

Vincent_TH

Bonjour,
Merci pour les infos, effectivement les fonctions « fast read » peuvent aider. Mais de façon plus générale, y a-t-il un moyen de cadencer un arduino en temps réel fort. Comme sur les contrôles (ECU) des moteurs des voitures. Où avec une horloge (interne ou externe), on donne un temps d'échantillonnage, et toutes les fonctions doivent s'exécuter pendant ce temps sans empiéter sur les autres (en évitant/maitrisant de base les overrun). Car un grand nombre de fonctions de base de l'Arduino (Serial.print, PulsIn (même avec les timeout), les lib i2c ou spi… toutes fonctions qui ont besoin d'interruptions), ne permettent pas ce fonctionnement optimal.
Merci par avance pour vos conseils / réponses
Vincent

3Sigma

C'est ce que fait FlexiTimer2: cadencement sur la base d'une interruption timer.
En revanche, je ne connais pas de librairie qui permet de gérer les overrun et compagnie (ce qui ne veut pas dire que ça n'existe pas).

Vincent_TH

Bonjour à tous,
J'ai fini par trouver une solution qui marche très bien et qui évite les lib (temps réel) pas très stables qu'on trouve pour Arduino… C'est assez simple en réalité… Je veux cadencer mon code à plusieurs pas d'échantillonnage (10 ms / 100 ms / 1000 ms). Alors j'ai créé un temps courant avec la fonction « millis() ». Puis crée pour chaque « schedule » un test « if » dans la partie « loop ».  Exemple :
void loop()
{
  Temps_courant = millis() ;
  Te_100 = Temps_courant - Temps_fin100 ;
  if (Te_100 >= 100)
  {
  Code des actions à faire
  }
}
On fait au tant de boucle « if » qu'on veut à la suite fonction des différents cadencements qu'on désir. Il faut juste vérifier que la somme des instructions dans un « if » ne dépasse pas le temps alloué. Par exemple ici les 100 ms (pour ça dans le « if », faire un Serial.print(Te_100) qui doit toujours être égal à 100)
Avec cette méthodo, vous pouvez mettre des attacheInterupt / Wire (i2c) / Serial.print avec vos contrôleurs les plus avancés comme du PID  sans aucun risque qu'une interruption vienne tuer votre pas de calcul de PID… et foute en l'air votre régulation.
Merci à tous pour vos conseils précieux
Vincent

3Sigma

Bonjour,

Je ne comprends pas bien: si ton PID est cadencé avec cette méthode, le code exécuté sur interruption de type attachInterrupt sera plus prioritaire et sera exécuté jusqu'à la fin avec le risque de te faire perdre ton cadencement de PID.
Je ne vois donc pas bien où est l'amélioration, mais j'ai sans doute mal compris quelque chose.

Go Up