Outils pour utilisateurs

Outils du site


arduinoisr

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
arduinoisr [2017/11/06 20:47]
bvandepo [Exercice 1 : Utilisation de la librairie Serial]
arduinoisr [2020/01/27 16:43] (Version actuelle)
bvandepo
Ligne 61: Ligne 61:
 Dans l'​onglet "​Outils",​ accédez au menu "Port Série"​ et cliquez sur la valeur /​dev/​ttyACM0 ou /​dev/​ttyUSB0. Accédez aussi eu menu "​Carte"​ et vérifiez que la valeur sélectionnée est "​Arduino Uno". Dans l'​onglet "​Outils",​ accédez au menu "Port Série"​ et cliquez sur la valeur /​dev/​ttyACM0 ou /​dev/​ttyUSB0. Accédez aussi eu menu "​Carte"​ et vérifiez que la valeur sélectionnée est "​Arduino Uno".
 ==== Votre premier sketch ==== ==== Votre premier sketch ====
-Maintenant que l'editeur ​est lancé, nous pouvons entrer dans la fenêtre le programme suivant+Maintenant que l'éditeur ​est lancé, nous pouvons entrer dans la fenêtre le programme suivant
    
 <file cpp blink.ino>​ <file cpp blink.ino>​
Ligne 99: Ligne 99:
  
 ==== Précautions à prendre avec la plateforme et l'IDE ==== ==== Précautions à prendre avec la plateforme et l'IDE ====
-<color red>​Sauvegarder vos fichiers en LOCAL sur la machine dans le dossier /​home/​IUT/"​login"/​Sketchbook/ et copier ces fichiers vers le disque réseau /​mnt/​ponsan..../​ A CHAQUE FIN DE SEANCE!!!</​color>​+<color red>​Sauvegarder vos fichiers en LOCAL sur la machine dans le dossier /​home/​IUT/"​login"/​Arduino/ et copier ces fichiers vers le disque réseau /​mnt/​ponsan..../​ A CHAQUE FIN DE SEANCE!!!</​color>​
   * Sauvegarder vos programmes sous des noms différents pour chaque exercice   * Sauvegarder vos programmes sous des noms différents pour chaque exercice
   * Lors de la sauvegarde, une fenêtre apparaît pour demander quels noms donner au programme. Si vous ne faites pas attention, cette fenêtre peut passer en arrière plan et l'IDE Arduino ne répondra plus à aucune sollicitation tant que vous n'​aurez pas ré-ouvert cette fenêtre.   * Lors de la sauvegarde, une fenêtre apparaît pour demander quels noms donner au programme. Si vous ne faites pas attention, cette fenêtre peut passer en arrière plan et l'IDE Arduino ne répondra plus à aucune sollicitation tant que vous n'​aurez pas ré-ouvert cette fenêtre.
Ligne 107: Ligne 107:
  
  
-===== Exercice 1 : Utilisation de la librairie Serial ===== + 
-===Comment gérer l'​absence de déboggeur===+=====Comment gérer l'​absence de débogueur=====
 Nous allons utiliser la librairie Serial pour échanger des caractères ASCII entre le PC et la carte Arduino de manière bidirectionnelle. Vous pouvez accéder au descriptif de cette librairie en sélectionnant le menu "​Aide"​ puis le menu "​Référence"​. Nous allons utiliser la librairie Serial pour échanger des caractères ASCII entre le PC et la carte Arduino de manière bidirectionnelle. Vous pouvez accéder au descriptif de cette librairie en sélectionnant le menu "​Aide"​ puis le menu "​Référence"​.
  
-Le deboggage ​de votre application pourra se faire à l'aide d'​affichage vers la console MAIS il faut tenir compte du fait que le code ainsi modifié ne sera pas exactement le même code que celui sans les appels d'​affichage.+Le debogage ​de votre application pourra se faire à l'aide d'​affichage vers la console MAIS il faut tenir compte du fait que le code ainsi modifié ne sera pas exactement le même code que celui sans les appels d'​affichage.
  
 Egalement, vous pourrez utiliser des broches du microcontroleur pour indiquer l'​entrée ou la sortie d'une portion de code, afin de tester précisement le timing. Egalement, vous pourrez utiliser des broches du microcontroleur pour indiquer l'​entrée ou la sortie d'une portion de code, afin de tester précisement le timing.
  
-==== Description de l'​application === 
  
-L'​application à programmer ​doit implémenter ​le comportement suivant :+===== Exercice 1 : Utilisation de la librairie Serial ===== 
 + 
 +<color #​FF0000>​**Repérer sur le schéma électrique de la carte les broches réservées pour la communication série. Ces brôches ne devront pas être utilisées pour une autre fonction!**</​color>​ 
 + 
 +L'​application à programmer ​implémente ​le comportement suivant :
  
   - Configurer l'UART pour une communication 8N1 à 9600Bauds (Serial.begin)   - Configurer l'UART pour une communication 8N1 à 9600Bauds (Serial.begin)
Ligne 129: Ligne 132:
    
  
-  
 <file cpp TP11.ino>​ <file cpp TP11.ino>​
 void setup()  ​ void setup()  ​
Ligne 140: Ligne 142:
 { {
   char car ;   char car ;
-  if (Serial.available()){+  if (Serial.available()>0){
      car = Serial.read();​      car = Serial.read();​
      if ( (car>​='​a'​) && (car<​='​z'​) )      if ( (car>​='​a'​) && (car<​='​z'​) )
Ligne 149: Ligne 151:
 </​file> ​ </​file> ​
  
-==== Utilisation de la console série ===+{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_tns/​TODO.jpg}} Compiler et charger ce programme sur la carte. 
 +==== Utilisation de la console série ​sur le PC ====
  
 L'IDE arduino dispose d'une console série permettant de visualiser les caractères envoyés par l'​Arduino sur son port périphérique matériel. Pour accéder à la console série, il suffit de cliquer sur la loupe en haut à droite de l'​éditeur de code. L'IDE arduino dispose d'une console série permettant de visualiser les caractères envoyés par l'​Arduino sur son port périphérique matériel. Pour accéder à la console série, il suffit de cliquer sur la loupe en haut à droite de l'​éditeur de code.
Ligne 166: Ligne 169:
 Les caractères émis par l'UART HARD du Arduino doivent ensuite s'​afficher dans la partie basse de la fenêtre. Les caractères émis par l'UART HARD du Arduino doivent ensuite s'​afficher dans la partie basse de la fenêtre.
  
 +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_tns/​TODO.jpg}} Vérifier la communication avec la carte Arduino en utilisant le programme chargé ​ précédemment.
 +
 +===== Exercice 2 : Accès bas niveau aux broches du microcontroleur=====
 +
 +Les fonctions Arduino pinMode(...) et digitalWrite(...) sont compatibles avec différentes cartes équipées de différents microcontroleurs. Ceci permet d'​écrire des programmes Arduino compatibles avec différentes cartes mais représente un coût non négligeable en terme de vitesse d’exécution,​ ce qui peut conduire à de la gigue (Jitter: the deviation from true periodicity of a presumably periodic signal) lorsque l'on souhaite construire ​ un signal à l'aide du microcontroleur.
 +
 +Analyser les fichiers suivants pour repérer comment les fonctions d'​accés aux broches sont implémentées pour le ATMEGA328P:
 +  /​usr/​share/​arduino/​hardware/​arduino/​cores/​arduino/​wiring_digital.c
 +  /​usr/​share/​arduino/​hardware/​arduino/​cores/​arduino/​Arduino.h
 +  /​usr/​share/​arduino/​hardware/​arduino/​variants/​standard/​pins_arduino.h
 +
 +En vous aidant de la doc de l'​ATMEGA328P et de ces fichiers, repérer les registres du microcontroleur permettant l’accès direct aux broches. Attention, les registres de ce microcontroleur ne sont pas adressables bit par bit, il faut donc effectuer des opérations logiques (& | ^ ...) et des masques pour intervenir individuellement sur une broche.
 +
 +
 +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_tns/​TODO.jpg}} Ecrire un programme le plus simple possible permettant de générer un signal carré de rapport cyclique 50% et de période la plus courte possible. On autorisera ici à écrire une boucle while(1) dans la fonction loop(). Afin d'​obtenir un rapport cyclique de 50%, vous pourrez faire appel à l'​instruction suivante qui génère un délai de 62.5ns (soit 1 cycle à 16Mhz):
 +  __asm__("​nop\n\t"​); ​
 +
 +<ifauth @prof>
 +===Solution:​===
 +Avec DigitalWrite,​ impossible d'​obtenir des périodes inférieures à 10us. Avec accès via registres, le signal généré est de période 0.5us soit de fréquence 2Mhz:
 +<file cpp carre.ino>​
 +    void setup()  ​
 +    {
 +      pinMode(8, OUTPUT); ​  
 +    }
 +    void loop()
 +    {
 +    while(1) {
 +      PORTB &= ~0x01 ;
 +      __asm__("​nop\n\t"​); ​
 +      __asm__("​nop\n\t"​); ​
 +      PORTB |= 0x01 ;
 +      }
 +    }
 +</​file>​
 +</​ifauth>​
 +
 +===== Exercice 3 : Gestion du temps sur le  microcontroleur=====
 +La gestion du temps peut se faire généralement de deux manières:
 +  - La plus simple consiste à faire appel à des boucles d'​attente durant lesquelles le processeur perd du temps à ne (quasiment) rien faire. La plus petite durée d'​attente possible est obtenue en exécutant l'​instruction assembleur NOP. Les fonctions Arduino delay(...) et delayMicroseconds(...) utilisent ce principe pour des durées plus longues exprimées en millisecondes et en microsecondes. Le problème est que les temps d'​attente s'​ajoutent à la durée d'​exécution des instructions (de calcul etc...) ce qui conduit à une mauvaise maîtrise du temps.
 +  - La seconde méthode consiste à faire appel à un périphérique intégré au microcontroleur:​ le TIMER, qui va (dé)compter des périodes d'un signal de référence,​ généralement l'​horloge système du microcontroleur (ou un signal générée à partir du signal de référence mais dont la fréquence aura pu être prédivisée par un facteur entier réglable). Pour générer un signal périodique,​ le timer pourra être configuré en mode rechargement automatique. Afin de générer des périodes plus longue que ce qu'il est possible d'​obtenir juste avec le prédiviseur et le timer, il est possible de mettre ​ en cascade un facteur de prédivision,​ un facteur de timer matériel suivi d'un facteur de compteur logiciel, ce dernier étant réalisé à l'aide d'une variable et d'​opérations de calcul. ​
 +
 +N.B. Pour des facteurs de division non entiers, il est possible de rattraper l'​erreur en ajoutant ou retranchant de temps en temps une valeur comme on le fait avec le 29 février pour les années bissextiles.
 +
 +Dans le cas de l'​utilisation d'un timer servant à déclencher l'​exécution d'une tâche périodique,​ il est possible de mettre en oeuvre deux approches:
 +  - La **scrutation** consiste à venir tester l'​état d'un indicateur (bit d'un registre) régulièrement afin de détecter le débordement du timer par exemple. Cette approche permet d'​intégrer le code de la tâche périodique à l'​intérieur du programme principale mais ne permet pas une très bonne maîtrise du temps, ce qui peut conduire à de la gigue.
 +  - L'​**interruption** consiste à interrompre l'​exécution de la tâche en cours (généralement le programme principal) pour aller exécuter un programme spécifique à l'​événement qui l'a déclenchée. L'​exécution du programme qui a été interrompu reprend généralement à la fin de l'​exécution du programme d'​interruption. Cette approche permet généralement une meilleure maîtrise du temps séparant l'​occurence de l'​événement et l'​exécution du programme associé mais nécessite des précautions ainsi qu'une configuration adéquate. Afin de vérifier le bon réglage du timer ainsi que le temps passé dans le programme d'​interruption (qui doit être inférieur à la période entre deux interruptions),​ nous conseillons d'​utiliser une broche du microcontroleur qui sera par exemple mise à 1 à l'​entrée dans le programme d'​interruption puis remise à 0 au moment de la sortie.
 +
 +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_tns/​TODO.jpg}} Dans un premier temps, modifier votre programme précédent pour générer un signal de rapport cyclique 50% et de période ​ 624us à l'aide de la fonction delayMicroseconds(...). Vérifier à l'​oscilloscope le signal obtenu et adapter votre programme.
 +
 +<ifauth @prof>
 +===Solution:​===
 +<file cpp carre2.ino>​
 +       void setup()  ​
 +    {
 +         ​pinMode(8,​ OUTPUT); ​  
 +    }
 +    void loop()
 +    {
 +    while(1) {
 +      PORTB &= ~0x01 ;
 +      __asm__("​nop\n\t"​); ​
 +      __asm__("​nop\n\t"​); ​
 +      delayMicroseconds(311); ​      
 +      PORTB |= 0x01 ;
 +      delayMicroseconds(311); ​      
 +      }
 +    }
 +</​file>​
 +</​ifauth>​
 +
 +{{http://​homepages.laas.fr/​bvandepo/​files/​iut/​tp_tns/​TODO.jpg}} Ensuite, générer le même signal en faisant appel à l'​interruption TIMER. Conseil: utiliser le timer 2 et lire la documentation de l'​ATMEGA328P pour sa configuration. ​
 +
 +
 +<ifauth @prof>
 +===Solution:​===
 +<file cpp carre3.ino>​
 +//624us de période=312us de demi période (entre chaque interruption)
 +//                =156*32*62.5ns
 +void setupTimer2(){
 +  TCCR2A = 0;// set entire TCCR2A register to 0
 +  TCNT2  = 0;//​initialize counter value to 0 
 +  OCR2A = 156-1;// (must be <256)
 +  // turn on CTC mode
 +  TCCR2A |= (1 << WGM21);
 +  //​prescaler= 1/32 , see p162 https://​docs.google.com/​viewer?​a=v&​pid=sites&​srcid=ZGVwaW5mb25hbmN5Lm5ldHxtaW5lc3xneDo0NjFmYzI1NTdkZDU2YmE2
 +  TCCR2B = (1 << CS21)|(1 << CS20);
 +  // enable timer compare interrupt
 +  TIMSK2 |= (1 << OCIE2A); ​
 +}
 +// TIMER ISR VECTOR and configuration
 +ISR(TIMER2_COMPA_vect){
 +     PORTB ^= 0x01 ;
 +}
 +void setup() ​   ​
 +    {
 +    pinMode(8, OUTPUT); ​  
 +    cli();//​stop interrupts
 +    setupTimer2();​ // setup interrupt with prescaler (see datasheet for prescaler value, and reload value)
 +    sei();//​allow interrupts
 +    }
 +void loop()
 +    {
 +    }
 +</​file>​
 +</​ifauth>​
 +
 +===== Exercice 4 : Gestion des bits sur le  microcontroleur=====
 +Le signal numérique a générer sur la broche est généralement issu d'une valeur sur plusieurs bits qui est **sérialisée**. Ceci revient, à chaque période bit, à extraire la valeur du bit (depuis une variable par exemple) et a appliquer un signal dépendant de ce bit sur la broche.
 +
 +
 +
 +=====Programme d'​exemple=====
 +<file cpp exemple.ino>​
 +
 +
 +//macro à activer pour afficher des infos de debug dans le programme, la commenter sinon
 +//#define DEBUG
 +
 +    //int led = A2; //si le shield RS232 est présent ​
 +    int led =   3; //si le shield RS232 n'est pas présent, pour utiliser la led de la carte UNO
 +    // the setup routine runs once when you press reset:
 +    void setup() {                ​
 +      // initialize the digital pin as an output.
 +      pinMode(led,​ OUTPUT); ​    
 +       ​Serial.begin(9600); ​
 +      Serial.println("​Hello,​ world?"​);​ // Envoi de la chaîne terminée par un saut de ligne
 +   
 +    }  ​
 +     ​unsigned int compteur=0;
 +    // the loop routine runs over and over again forever:
 +    void loop() {
 +      /*
 +      compteur=compteur+1;​
 +      digitalWrite(led,​ HIGH); ​  // turn the LED on (HIGH is the voltage level)
 +      delay(3); ​
 +        Serial.println("​+"​);​ // Envoi de la chaîne terminée par un saut de ligne
 +      ​
 +      //if (false)// wait for a second
 +      {
 +        digitalWrite(led,​ LOW);    // turn the LED off by making the voltage LOW
 +       ​delay(200); ​              // wait for a second
 +       ​Serial.println("​."​);​ // Envoi de la chaîne terminée par un saut de ligne
 +
 +      }
 +
 +      Serial.println(compteur);​
 +*/
 +
 +#ifdef DEBUG
 +  Serial.println("​je debuggue"​);​
 +#endif
 +  ​
 +/*
 +
 +char car;
 +  if (Serial.available()>​0){
 +         car = Serial.read();​
 +         if ((car%2)==0) //est ce que le code ascii est pair?
 +           ​digitalWrite(led,​ HIGH); ​  
 +         else
 +           ​digitalWrite(led,​ LOW);   
 +           
 +
 +  }
 +  */
 +
 +  /* génère un signal de fréquence 102kHz)
 + ​digitalWrite(led,​ HIGH); ​
 + ​digitalWrite(led,​ LOW);    ​
 + */
 +
 +
 + //la broche 3 de l'​arduino est connectée au bit 3 du port D
 +
 +   /* génère un signal de fréquence 841.5kHz)
 +    PORTD|=0x8; // met à 1 le bit 3 du port D
 + ​PORTD&​= ~0x8;  // met à 0 le bit 3 du port D
 +    */
 +
 +
 +/* génère un signal de fréquence 2,​664MHz) ​   ​
 +    while(1){
 + ​PORTD|=0x8;​ // met à 1 le bit 3 du port D
 + ​PORTD&​= ~0x8;  // met à 0 le bit 3 du port D
 +    }
 +    */
 +
 +// génère un signal de rapport cyclique 50% de fréquence 2MHz)    ​
 +while(1){
 + ​PORTD|=0x8;​ // met à 1 le bit 3 du port D
 + ​__asm__("​nop\n\t"​); ​
 + ​__asm__("​nop\n\t"​); ​
 + ​PORTD&​= ~0x8;  // met à 0 le bit 3 du port D
 +    }
 +
 +    ​
 +    }
 +
 +
 +</​file>​
arduinoisr.1509997625.txt.gz · Dernière modification: 2017/11/06 20:47 par bvandepo