Go Down

Topic: Mesure de temps d'une instruction (Read 911 times) previous topic - next topic

iutgeiisoissons

May 15, 2018, 02:24 pm Last Edit: May 16, 2018, 05:28 pm by iutgeiisoissons Reason: ajout d'une carte Arduino DUE
Dans certains cas, nous sommes amenés à devoir réguler un système. On utilise dans ce cas un régulateur PID (Proportionnel Intégrale Dérivé)
Un PID est constitué d'additions, de soustractions, et de multiplication, ce qui nous amène d'abord à traiter en premier lieu les calculs de bases.




Vous avez ci-dessus un tableau récapitulant le temps que prend une carte arduino pour traiter une instruction. Les instructions sont basiques sauf pour le PID. Pour trouver ces valeurs, nous avons défini notre sortie LED sur la pin 13. Nous l'avons mise à 1 avant le calcul et remise à 0 après. On mesure ensuite le temps lorsque la sortie est à 1 en simulation sur ISIS ou en réelle grâce à un oscilloscope. On écrit sur un terminal pour vérifier si le calcul est correct.

Le programme de base est le suivant : la ligne de calcul est à changer ainsi que la déclaration en int ou float.

Code: [Select]
#define LED 13
int a = 10, b=5,c; //ligne de déclaration
void setup() {
 // put your setup code here, to run once:
pinMode(LED,OUTPUT);
Serial.begin(9600);
}

void loop() {
 // put your main code here, to run repeatedly:
  digitalWrite(LED, 1);
  c=a+b; //ligne de calcul
  digitalWrite(LED, 0);
  Serial.print(c);
  Serial.print("\n\r");
}



Soustraction
Code: [Select]
c=a-b

Multiplication
Code: [Select]
c=a*b


Division
Code: [Select]
c=a/b

/!\ si en int, la valeur sera arrondi a l'entier près.

Exposant
Code: [Select]

pow(a,b)



/!\ cette commande ne fonctionne correctement que si vous utilisez des floats. Si vous utilisez des entiers, il faudra « caster » le calcul c'est-à-dire forcer le résultat à être en float. On écrira donc
Code: [Select]
Pow(float(a),float(b));
Le cast ajoute du temps au calcul et il est donc plus rapide d'utiliser des floats.

PID
Nous n'utilisons que des floats pour le PID


Code: [Select]
#define LED 13
float c;

const float kp = 2;
const float ki = 1;
const float kd = 1;
byte PWM=0 ;
float erreurP = 0;
float erreur = 0;
float Integral = 0;
float derive = 0;
float Proportionnel = 0;
float output = 0;
float Setpoint=0;

void setup() {
 // put your setup code here, to run once:
pinMode(LED,OUTPUT);
Serial.begin(9600);
}

void loop() {
erreurP=erreur;                 //erreur precedente ou erreur erreur*Z^Ts  pour faire le calcul de la derive
erreur=Setpoint-a;
Proportionnel=kp*erreur;
Integral= Integral+erreur*ki;
if (Integral>=255) Integral=255;
derive=(erreur-erreurP)*kd;             //derive=(erreur-erreur*Z^Ts)/Ts   avec Ts=Tsampleur

output=Proportionnel+Integral+derive;   //ce n'est pas la peine de divisée par Ts car si Ts est petit cela donne des valeurs enormes
if (output>=255) {output=255;}
if (output<=0) {output=0;}
PWM=output;
analogWrite(PWM10,PWM);   //PWM
  digitalWrite(LED, 0);
  Serial.print(c);
  Serial.print("\t");
  Serial.println(";");
}



On peut remarquer que les temps de calculs sont plus rapides pour une arduino nano que pour une Mega. Sauf que la carte Méga possède plus de ports. Si vous cherchez la vitesse d'exécution, vous prendrez une nano, si vous avez besoin de beaucoup de pin, vous prendrez une méga.

A savoir que ce que nous avons fait peut être fait pour n'importe quelle instruction ou série d'instructions que vous voulez (pas forcément des calculs).

edit : Concernant le carte Arduino DUE, j'ai rencontré quelques problèmes : quelques difficultés à compiler mon programme à cause d'un fichier du logiciel (https://arduino.stackexchange.com/questions/24143/unable-to-upload-to-arduino-due-using-version-1-6-8-of-sam-tools-bossac-exe-thr aller sur ce site (en anglais) pour voir comment résoudre le problème si vous l'avez).
Cette carte est plus rapide que les autres comme on peut le voir (en écrivant en langage C/C++ comme j'ai pu voir les commentaires plus bas). Donc pour ceux qui ne veulent pas mettre les mains dans l'assembleur et qui veulent juste écrire leur ligne de code.

bilbo83

Bonjour,

Vous tenez compte de la durée du "digitalWrite(LED, 0)" ?

68tjs

digitalWrite(LED, 0) --> Environ 60 cycles horloge système.

Perso pour mesurer le temps d'une instruction j'utilise le compteur d'un timer. (registre TCNTx)
Selon la valeur du temps à mesurer on peut ajuster la valeur du pré-diviseur d'horloge système.

Une fois le timer configuré l'utilisation est simple.
TCNTx= 0 ;  // Raz du compteur pour ne pas avoir à gérer les débordement
instruction();
Mesure = TCNTx;   // Mesure contient le nombre de cycles de l'horloge du timer

La précision maximale est obtenue avec un pré-diviseur de 1, le résultat est directement en nombre de cycle horloge système.

_pepe_

#3
May 15, 2018, 03:59 pm Last Edit: Aug 19, 2018, 02:16 am by _pepe_
Supprimé

_pepe_

#4
May 15, 2018, 04:52 pm Last Edit: Aug 19, 2018, 02:16 am by _pepe_
Supprimé

Go Up