Go Down

Topic: temps d' instruction atmega328, DUE, ESP32 compiler IDE (Read 3115 times) previous topic - next topic

iutgeiisoissons

May 15, 2018, 02:24 pm Last Edit: May 04, 2020, 07:33 am 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.
Les Shadocks : L'ignorance ne s'apprend pas.

iutgeiisoissons

#3
Mar 31, 2020, 10:48 am Last Edit: May 23, 2020, 07:06 pm by iutgeiisoissons
Excellente idée, pour le comptage d'horloge
Sachant que le temps d'eteindre la led est souvent negligeable (5µs pour la nano) et été pris en compte précédement.

Il y a de nombreux d'autres temps à connaitre, Exemple Sur un arduino nano

- Un conversion analogique 10 bits dure environ combien de temps ?    110µs avec un prescaleur de 128
il est possible de diminuer ce temps   https://www.gammon.com.au/adc
- le temps une conversion DAC MCP4775   140µs
- Une ecriture PWM ? 7µs
- un serial.print("C")  d'un caractere  ?  10µs  donc de 10 caracteres 75µs
- un serial.println("C")  d'un caractere  ?  30µs  donc de 10 caracteres 92µs



Les LCD parallele
- Un affichage d'un caratere sur le LCD parralléle dure environ  300µs  

- Un affichage de 16 lettres consécutives sur le LCD parallèle dure environ  4.8ms=16* 300µs  cela est logique

- Un deplacement d'une ligne consecutive sur le LCD  parallèle dure environ  300µs  

Les LCD serie avec liaison I2C utilisant un PCF8575


- Un affichage d'une lettre sur le LCD I2C dure environ  1.4ms  
- Un affichage de 16 lettres consecutives sur le LCD I2C dure environ 22.4ms=16* 1.4ms  cela est logique
- Un deplacement d'une ligne consecutive sur le LCD  parallèle dure 1.4ms    

Le temps pour ecrire un byte avec la liasion I2C sur un PCF8574 est de 0.22ms

Conclusion,
Les temps sont évidemment bien plus courts sur un LCD avec une communication parallèle que sur un LCD avec communication série I2C. Le rapport est de 4.6 fois plus rapide pour le LCD parallele.

iutgeiisoissons

#4
May 03, 2020, 07:20 pm Last Edit: May 24, 2020, 09:21 am by iutgeiisoissons
ESP 32 a presque le prix d'un ATMEGA328 mais il bien plus puissant
Mais quels sont ces temps d'instruction avec le compilateur arduino ? quels sont les temps pour le OLED

Je n'ai pas trouvé grand-chose sur la toile sur les temps d'instructions
https://www.esp32.com/viewtopic.php?t=11678

Voici un heltec ESP32 lora32 qui peut être alimenté par batterie Lipo avec un Oled 128x64
voici comment télécharger les library
https://heltec-automation-docs.readthedocs.io/en/latest/esp32+arduino/quick_start.html
des exemples ici
https://github.com/HelTecAutomation/Heltec_ESP32
des exemples ici
https://platformio.org/lib/show/6051/Heltec%20ESP32%20Dev-Boards
La carte matérielle
https://heltec-automation-docs.readthedocs.io/en/latest/esp32+arduino/wifi_kit_32/hardware_update_log.html
Le brochage
https://resource.heltec.cn/download/WiFi_LoRa_32/WIFI_LoRa_32_V2.pdf
http://resource.heltec.cn/download/WiFi_Kit_32/WIFI_Kit_32_pinoutDiagram_V2.pdf

L'affichage sur le OLED est d'un int sur le oled dure 2ms
Pour afficher 1 caractère 3.6ms, mais 17 caractères 5ms
L'analogRead dure 10 µs   alors que pour atmega328 0.11ms
Un serial.print dure  8µs alors que pour atmega328 10µs

bref voici le code qui a permis de tester ces temps, les temps ont été mis en commentaire
Code: [Select]

#include "Arduino.h"
#include "heltec.h"

#define LED25     25  

 int counter=0;
 float mesure;

void setup() {
  pinMode(25, OUTPUT);
  
  Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Disable*/, true /*Serial Enable*/);

//  Serial.begin(9600);
  Serial.begin(115200);
  Heltec.display->flipScreenVertically();
  Heltec.display->setFont(ArialMT_Plain_10); //22 caracteres possible
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);
}


void loop() {
    counter++;
//    if ( digitalRead(25)== 1 ) {digitalWrite(25,LOW);}  else {digitalWrite(25,HIGH);}  //il y a une led broche 25
    Heltec.display->clear();  //tres court
        Heltec.display->drawString(0, 0, "IUT GEII Soissons");    // afficher 17 caractéres 5ms;  1 seul caractere 3.6ms
    Heltec.display->display();
        
 //   Heltec.display->drawString(0, 11, "counter" +String(counter));
 Heltec.display->drawString(0, 11, String(counter));   //250microseconde          
    Heltec.display->display();                         //affichage d'int 2ms
        delay(1);

 
    Serial.print(counter);       //8micro seconde      avec 115200 bauds
    Serial.println(";");
      
   digitalWrite(LED25,HIGH);
   mesure=analogRead(36);       //10micro seconde
   digitalWrite(LED25,LOW);
 
}





Il faudrait y mettre un afficheur LCD pour savoir si c'est bien plus rapide avec ESP32 ou pas



Go Up