LOCODUINO

Les Timers

Les Timers (I)

Les bases

.
Par : Christian

DIFFICULTÉ :

Un timer est un registre à l’intérieur du microcontrôleur qui s’incrémente (ou se décrémente) chaque fois qu’il reçoit une impulsion d’un signal d’horloge. Ce signal d’horloge peut être propre au microcontrôleur ou bien extérieur à celui-ci. Un timer est donc un compteur capable de compter le temps qui s’écoule, d’où son nom anglais de timer counter. Dans ce qui suit, le timer est toujours employé dans un mode où il s’incrémente, mais dans d’autres modes, il peut se décrémenter. On peut télécharger la documentation du constructeur sur ce lien : https://ww1.microchip.com/downloads....

Si le registre du timer comporte 8 bits, il est alors capable de compter de 0 à 255 (en hexadécimal, de 00 à FF). Lorsqu’il arrive à 255 (FF), un coup d’horloge supplémentaire devrait le faire passer à 256 (soit 100 en hexadécimal), ce qui n’est pas possible puisque le registre n’a que 8 bits. Le registre passe donc à 0 ; on dit qu’il subit un débordement (Overflow en anglais) [1], mais ce débordement entraîne la mise à 1 d’un bit bien particulier dans un registre de contrôle associé au timer. Ce bit est appelé un flag (drapeau en anglais) et indique que le timer vient de compter jusqu’à 256, ce qui permet d’attirer l’attention du programmeur, un peu comme ces boîtes aux lettres américaines qui possèdent un petit drapeau qui se dresse chaque fois que le facteur a déposé du courrier à l’intérieur.

L’intérêt d’un timer est qu’il compte sans cesse et que pendant ce temps, le programme peut réaliser autre chose, ce qui n’est pas possible si on utilise la fonction delay() qui est bloquante et qui ne permet pas de faire autre chose pendant ce temps d’attente. Le temps que le timer met pour compter 256 coups dépend bien sûr de la fréquence de l’horloge ; à 16 MHz (fréquence du microcontrôleur utilisé dans les modules Arduino), c’est très rapide, mais il est possible de diviser cette fréquence d’horloge grâce à des circuits internes au microcontrôleur appelés prédiviseur (prescaler en anglais). On peut alors diviser la fréquence de base (16 MHz) par 8, 32, 64, 128, 256 ou 1024 ; pour cela, il faut utiliser intelligemment d’autres registres de contrôle associés au timer. Par exemple, si on règle de prédiviseur pour diviser la fréquence par 1024, le timer comptera donc à une fréquence de 15625 Hz.

Comme pour tout registre, on peut lire la valeur d’un timer ou bien écrire une valeur particulière dans le timer. Mais ce qui est surtout important, ce sont les registres de contrôle associés au timer car ce sont eux qui permettent de modifier le comportement du timer et de contrôler ce qu’il fait. Il faut donc bien les connaître pour bien savoir les utiliser et la lecture de la documentation liée au microcontrôleur est souvent indispensable.

Timers du microcontrôleur de l’Arduino

Le module Arduino Uno est construit autour du microcontrôleur AVR ATmega328P d’Atmel qui possède 3 timers :

  • Le timer0, sur 8 bits, utilisé par les fonctions delay(), millis() et micros(). Il commande également des PWM (Pulse Width Modulation ou Modulation par Largeur d’Impulsion) sur les broches 5 et 6.
  • Le timer1, sur 16 bits, qui compte de 0 à 65535 (0 à FFFF en hexadécimal) et qui est utilisé par la bibliothèque Servo ou bien pour de la PWM sur les broches 9 et 10.
  • Le timer2, sur 8 bits, qui est utilisé par la fonction Tone() ou bien pour de la PWM sur les broches 3 et 11.

Le langage d’Arduino fait donc appel aux timers du microcontrôleur mais ceci reste transparent pour le programmeur. D’ailleurs, dans la majorité des applications, le langage d’Arduino est souvent très suffisant et permet de développer des applications sans avoir besoin de faire appel à l’architecture du microcontrôleur. Néanmoins, dans quelques cas particuliers, il peut être intéressant de savoir programmer les timers ; dans cet article, nous allons évoquer l’utilisation des timers comme compteur de temps, même si ceux-ci sont capables de faire bien d’autres choses.

Les registres de contrôle

Le tableau suivant donne les différents registres de contrôle associés à chaque timer ; nous verrons le rôle de chaque registre tout en nous limitant à ce qui est vraiment à connaître pour réaliser un premier exemple.

Timer 0Timer 1Timer 2Rôle
TCNT0 TCNT1L TCNT2 Timer (bit 0 à 7)
- TCNT1H - Timer (bit 8 à 15)
TCCR0A TCCR1A TCCR2A Registre de contrôle
TCCR0B TCCR1B TCCR2B Registre de contrôle
- TCCR1C - Registre de contrôle
OCR0A OCR1AL OCR2A Output Compare (bit 0 à 7)
- OCR1AH - Output Compare (bit 8 à 15)
OCR0B OCR1BL OCR2B Output Compare (bit 0 à 7)
- OCR1BH - Output Compare (bit 8 à 15)
- ICR1L - Input Capture (bit 0 à 7)
- ICR1H - Input Capture (bit 8 à 15)
TIMSK0 TIMSK1 TIMSK2 Interrupt Mask
TIFR0 TIFR1 TIFR2 Interrupt Flag

ASSR Asynchronous Status Register
GTCCR General Timer/Counter Control Register

Le timer1 est un timer de 16 bits et est donc constitué de deux registres de 8 bits, l’un donnant les bits 0 à 7, l’autre donnant les bits 8 à 15.

Pour se repérer dans ce tableau, il faut savoir que TCNT signifie Timer/Counter (Register), TCCR Timer/Counter Control Register, OCR Output Compare Register, ICR Input Capture Register, TIMSK Timer/Counter Interrupt Mask Register et TIFR Timer/Counter Interrupt Flag Register. OCR et ICR ont des rôles particuliers dont nous ne parlerons pas dans ce premier article. TIMSK et TIFR servent pour que le timer puisse générer des interruptions [2] comme nous le verrons dans un autre article.

Exemple d’utilisation simple

Nous allons maintenant nous intéresser au timer 2 dans son rôle le plus simple, compter le temps, et aux registres de contrôle qui y sont associés. Ce que nous allons dire reste bien entendu valable pour les timers 0 ou 1. Pour mieux comprendre, nous prendrons comme exemple le clignotement d’une DEL à 1 Hz, ce qui signifie que toutes les 500 ms (demi-période), il faut inverser la DEL, c’est-à-dire l’allumer si elle est éteinte et l’éteindre si elle est allumée.

Ralentir ou accélérer le timer

Nous avons vu qu’il était facile de ralentir un timer : il suffit d’utiliser le prédiviseur pour diviser la fréquence du signal d’horloge. Pour faire cela, il suffit de positionner certains bits du registre TCCR2B. À partir de là, notre compteur comptera de 0 à 255 (cela lui prendra un certain temps) puis passera en débordement, c’est-à-dire qu’il repartira de 0 après avoir positionné le flag TOV2 (Timer/Counter 2 Overflow Flag) à 1. Il s’agit là du bit 0 du registre TIFR2. Chaque fois que le bit 0 du registre TIFR2 passe à 1, cela signifie que notre timer a compté un certain laps de temps (connu) ; il suffit alors de repositionner le flag TOV2 à 0 et d’incrémenter un compteur (une variable) pour continuer ce processus. Lorsque ce compteur arrive à une certaine valeur, c’est que le temps à attendre s’est écoulé.

Pour accélérer un timer, il faut le faire déborder avant qu’il ait compté 256 coups : pour cela, il suffit de partir d’une valeur différente de 0 pour effectuer le comptage puisqu’il est possible d’écrire dans le registre du timer.

On voit maintenant comment il faut opérer pour faire clignoter notre DEL. Le timer part de 0 et s’incrémente jusqu’à 255, puis recommence de 0 vers 255 en ayant positionné le flag TOV2 à 1. Il suffit de surveiller ce flag ; chaque fois qu’il est à 1, on repositionne le flag à 0 et on incrémente un compteur. Lorsque ce compteur arrive à une certaine valeur, on a atteint 500 ms et il faut agir sur la DEL. Pour que le timer ait ce comportement, il doit être utilisé en mode normal ; dans ce mode, le timer compte en incrémentant, et le flag est positionné à 1 chaque fois que le timer repasse par 0.

Pour que le timer soit en mode normal, il faut que les trois bits appelés WGM20 , WGM21 et WGM22 soient à 0, ce qui nécessite d’aller écrire dans 2 registres (WGM2 pour Waveform Generation Mode du timer 2). En effet, WGM20 et WGM21 sont les bits 0 et 1 du registre TCCR2A, et WGM22 est le bit 3 du registre TCCR2B. Les bits 0 à 2 de ce même registre sont appelés CS20 , CS21 et CS22 et servent à régler le prédiviseur suivant le facteur de division souhaité (CS2 pour Clock Select du timer 2). Tout cela sera plus clair sur un exemple.

Calcul théorique du comptage

Le timer 2 sera utilisé en le faisant compter à la fréquence de 62500 Hz (fréquence d’horloge divisée par 256). Un cycle d’horloge dure donc 16 µs (l’inverse de la fréquence). Pour avoir 500 ms (500000 µS), il faut compter 500 000 µs / 16 µs = 31250 fois. Cette valeur est décomposable en 125 * 250. Le timer doit compter 250 fois pour déborder ; il suffit de le faire partir de la valeur 6. Chaque fois qu’il déborde, une variable compteur est incrémentée ; quand cette variable atteint 125, on a bien 500 ms qui se sont écoulées et on agit sur la DEL.

Initialisation des registres de contrôle

Pour que le timer soit en mode normal, il faut que WGM20 , WGM21 et WGM22 soient à 0. On positionne ces bits à 0 dans deux registres TCCR2A et TCCR2B par une instruction adéquate (bitClear dans le langage Arduino). Pour que le prédiviseur divise par 256, il faut que le bit CS22 soit égal à 1, le bit CS21 soit égal à 1 et le bit CS20 soit égal à 0 ; il suffit d’écrire la valeur binaire 0b00000110 dans le registre TCCR2B. Heureusement pour nous, le compilateur d’Arduino connaît les noms des registres et les noms des bits.

La dernière chose à savoir, c’est que pour réinitialiser le flag TOV2 par logiciel, il faut écrire à 1 le bit 0 du registre TIFR2 ; l’instruction est bitSet (et non bitClear comme on aurait pu le croire).

Programme

Voici le programme, écrit avec le langage Arduino :

/*
 * Clignotement d'une DEL (LED en anglais) à 1 Hz par timer 2.
 */
const byte Led = 13; // Pour utiliser la LED du module
#define LedToggle digitalWrite (Led, !digitalRead(Led))
  
void setup ()
{
  pinMode (Led, OUTPUT);
  bitClear (TCCR2A, WGM20); // WGM20 = 0
  bitClear (TCCR2A, WGM21); // WGM21 = 0 
  TCCR2B = 0b00000110;      // Clock / 256 soit 16 micro-s et WGM22 = 0
  TIFR2 = 0b00000001;       // TOV2
  TCNT2 = 256 - 250;        // Chargement du timer à 6
}
 
byte varCompteur = 0; // La variable compteur
 
void loop () {
  if (bitRead (TIFR2, 0) == 1) {       // Flag TOV2 mis à 1 ?
    TCNT2 = 256 - 250;         // Rechargement du timer à 6
    bitSet (TIFR2, TOV2);      // Remise à zéro du flag TOV2 (voir texte)
    if (varCompteur++ > 125) { // Incrémentation et a atteint 125 ?
      varCompteur = 0;         // On recommence un nouveau cycle
      LedToggle;             // Inversion de la LED
    }
  }
}

Conclusion

Nous avons vu qu’un timer est un registre compteur qui s’incrémente (ou se décrémente) à chaque impulsion d’une horloge qui peut être celle du microcontrôleur divisée par un certain nombre pour la ralentir. Lorsque le timer déborde, un flag est positionné à 1 dans un registre de contrôle. En surveillant ce flag, on peut compter le temps qui s’écoule jusqu’à obtenir une durée déterminée. On peut lire la valeur du timer et on peut écrire une valeur dans le timer. Plusieurs registres de contrôle sont associés au timer et permettent de modifier son comportement et de suivre son débordement. La connaissance de ces registres de contrôle et du rôle joué par chacun des bits les composant est indispensable au programmeur qui veut utiliser les timers. Pour cela, une lecture assidue de la documentation du constructeur est indispensable.

L’intérêt d’un timer pour compter le temps qui s’écoule est que le programme peut réaliser autre chose pendant ce temps. Dans l’exemple donné, il suffit de surveiller le flag TOV2 pour connaître l’écoulement du temps ; ceci est possible parce que le programme ne fait rien d’autre que de surveiller. Nous verrons dans un prochain article que le débordement du timer peut engendrer une interruption ; le programme peut alors faire autre chose et être interrompu pour traiter l’événement. Nous verrons aussi que les timers peuvent faire d’autres choses grâce aux autres registres de contrôle comme OCR ou ICR. Mais tout ceci est une autre histoire.

[1Voir à ce propos l’article « Types, constantes et variables ».

[2Voir l’article « Les interruptions (1) »

91 Messages

  • Les Timers (I) 13 janvier 2015 20:00, par Gérard

    Cet article à l’avantage d’expliquer simplement le fonctionnement des timers.
    Pour aller plus loin que ce qui est décrit ici, il est intéressant de combiner timer et interruptions ; en effet, le timer associé aux interruptions permet de faire une action à intervalle régulier sans "polluer le programme principal" avec des lectures régulières du flag de passage par zéro.

    Voici le même programme que celui présenté dans l’article mais en utilisant l’interruption de débordement. Vous pourrez voir qu’il n’y a que deux choses en plus : l’instruction sei() qui autorise les interruptions et ISR() qui désigne où doit pointer le vecteur d’interruption

    /*
      Timer et interruptions
     */
    
    const byte Led = 13; // LED du module
    #define LedToggle digitalWrite (Led, !digitalRead(Led))
    
    byte Compteur = 0;  //Compteur pour interruption
    
    void setup(){
    
      // Initialise le Timer 2 pour déclencher les interruptions à intervalle régulier
      TCCR2A = 0; //default 
      TCCR2B = 0b00000110; // clk/256 est incrémenté toutes les 16uS  
      TIMSK2 = 0b00000001; // TOIE2 
      sei();               // autorise les interruptions
      
    }
    
    // Boucle principale
    void loop() {
     
      
    }
    
    // routine d'interruption du timer
    ISR (TIMER2_OVF_vect) 
    {  
      // 256-6 --> 250X16uS = 4mS  
      // Recharge le timer pour que la prochaine interruption se déclenche dans 4mS
      TCNT2 = 6;
      
      if (Compteur++ == 250) {
        //250*4mS = 1S - la Led est allumée 1 S et éteinte 1 S
        Compteur=0;  
        LedToggle;
      }  
    } 

    Répondre

    • Les Timers (I) 13 janvier 2015 20:18, par Christian Bézanger

      Bonjour Gérard,

      Ceci sera l’objet du deuxième article (les interruptions par débordement) et le troisième sera consacré aux interruptions par output compare.

      C’est un sujet qui peut paraître difficile à ceux qui n’ont jamais pratiqué, donc je voulais y aller lentement.

      Répondre

    • Les Timers (I), usage 13 avril 2017 14:58, par PIVAR

      Voila , c’est pour savoir si je pense bien : le timer est mis en route au départ ; on a pas de "timer.start ou timer.stop" ; ce sont les variables qui seront mises dans les interruptions qui seront incrémentées ou non, selon certaines conditions , qui feront office de timer.start ou stop ; le timer continuant à vivre sa vie ..
      Enfin , c’est comme cela que je vais essayer de faire fonctionner , ce qui permettrai d’avoir plusieur timer (multiples) avec un timer de base

      Répondre

    • Les Timers (I) 11 avril 2021 21:50, par fofana salif

      Bonjour
      par rapport a votre programme j’arrives pas voir ou est ce que vous avez incrémenter la variable compteur ??

      Répondre

      • Les Timers (I) 12 avril 2021 10:20, par Christian

        Ligne 33 : l’incrémentation est faite avant de comparer à 250.

        Répondre

  • Les Timers (I) 7 décembre 2015 10:55, par Arnaud

    Bonjour,

    Tout d’abord, félicitations pour la qualité et le contenu de votre site internet !

    J’aurais une petite question concernant les timers :

    J’ai essayé vos 2 codes (avec IF et avec interruption) sur une carte Arduino UNO et tout fonctionne parfaitement. Par contre, quand j’essaye le code avec IF sur le simulateur du site https://123d.circuits.io/, la fréquence de sortie ne correspond pas à celle souhaitée alors que quand j’utilise l’interruption ça fonctionne.

    Merci d’avance.

    Voir en ligne : 123D et Arduino

    Répondre

    • Les Timers (I) 11 décembre 2015 13:55, par Christian

      Bonjour Arnaud,

      Je n’ai aucune expérience du simulateur 123D que vous citez ; je ne pourrai donc pas expliquer pourquoi cela ne fonctionne pas de la même façon.

      Les programmes donnés dans la série sur les timers ont été testés et fonctionnent (avec contrôle à l’oscilloscope si nécessaire). Pour ce qui concerne le simulateur, s’il est bien conçu, il doit contenir les différents registres du microcontrôleur. Il faut donc vérifier que tous ces registres soient bien écrits tels que cela est demandé dans mon programme. En dehors de cette piste, je ne vois pas quoi répondre d’autre.

      J’espère que vous arriverez à comprendre l’origine du problème et à le solutionner.

      Christian

      Répondre

  • Les Timers (I) 16 juillet 2016 11:09, par Mathieu

    Bonjour.

    Je me mets tout juste à l’arduino, pour initier mon fils à la programmation. Jusqu’à présent, je ne programmais qu’en assembleur sur PIC. Il est donc tout à fait possible que je raconte n’importe quoi :-)

    J’ai regardé votre code mais une chose me chagrine :

    • On initialise le compteur varCompteur à 0, puis au bout de 4 ms, on a un débordement de TOV2 ce qui permet d’entrer dans le if. On y trouve alors :

    if (varCompteur++ > 125)

    D’après mes souvenirs d’école, cette ligne teste si varCompteur = 126 (car >125) PUIS l’incrémente (post incrément), ce qui signifierait, d’après moi, que la condition n’est vraie qu’au 127ème passage. Ne faudrait-il pas utiliser : if (++varCompteur == 125) (pre incrément à la place du post incrément et == à la place de >) ou bien if (varCompteur++ == 124) ?

    Répondre

    • Les Timers (I) 18 juillet 2016 11:11, par Christian

      Telle que l’instruction est écrite, je pense que la variable est d’abord incrémentée avant d’être comparée à 125.
      Donc, le programme fonctionne et a été inspiré d’un programme de l’EPFL (Ecole Polytechnique Fédérale de Lausanne) dans son MOOC sur les µC.
      Néanmoins, si on cherche à obtenir un signal parfaitement calibré, seul son examen à l’oscilloscope permettra d’ajuster le seuil de comparaison (124 ou 125). C’est un peu le même problème avec la PWM si on cherche un rapport cyclique de 50% : faut-il mettre 127 ou 128 comme moitié de 255 ?
      Je n’ai jamais vu la notation ++VarCompteur, mais je ne connais pas toutes les subtilités de C++ : pour moi, ce n’est pas possible (mais je peux avoir tort). Par contre, on doit pouvoir écrire if(varCompteur == 125).
      Dieu merci, pour nos trains électriques, une telle précision n’est jamais vraiment nécessaire mais vous avez eu raison de poser la question. Dans le quatrième article sur les Timers, les signaux PWM obtenus en manipulant les Timers ont été analysés à l’oscilloscope et donnaient les résultats escomptés. Mais pour cet article, j’avoue n’avoir pas contrôlé la fréquence exacte, n’ayant pas d’oscilloscope.

      Répondre

      • Les Timers (I) 7 novembre 2017 01:32, par Claude

        Bonjour,
        Dans l’instruction if (varCompteur++ > 125), l’incrémentation se fait après la comparaison ; on veut que le programme effectue la boucle 125 fois et comme on commence à 0, la dernière doit être 124 ; il faut donc écrire if (varCompteur++ > 123) ; on peut le vérifier en ajoutant dans la boucle après LedToggle :

        maintenant= micros() ;
        Serial.println(maintenant - debut) ;
        debut=maintenant ;

        où debut et maintenant sont deux variables de type long.
        En tous cas bravo pour votre tuto !

        Répondre

  • Les Timers (I) 18 juillet 2016 21:08, par Mathieu

    Bonsoir.

    Merci pour cette réponse.

    Je ne pense pas qu’un oscilloscope soit suffisamment précis pour distinguer si l’on est à 500ms ou bien à 504 ou même 508ms.

    N’y-a-t-il pas un simulateur pour arduino dans lequel on puisse suivre le temps d’exécution ?

    Comment récupérer l’assembleur généré par le compilateur afin de voir si ++var et var++ sont traités différemment ?

    Répondre

    • Les Timers (I) 19 juillet 2016 21:38, par Dominique

      Les instructions ++var et var++ sont des instructions du langage C qui existe depuis les années 80. D’après Wikipedia, Il a été écrit par Dennis Ritchie, créateur du langage, et Brian Kernighan en 1978 pour réaliser un compilateur. En 1988, une seconde édition a présenté l’ANSI C, orienté vers les programmeurs.

      On trouve facilement le livre The_C_Programming_Language gratuitement en format pdf.

      L’IDE Arduino ne fait qu’utiliser le compilateur gcc qui est complètement stable depuis des années.

      La différence entre les instructions n’a donc rien à voir avec l’Arduino.

      Regardez le menu référence dans votre IDE.

      ++var incrémente la variable var AVANT de s’en servir
      var++ incrémente la variable var APRES s’en être servi. (donc au tour suivant dans la boucle que vous donnez comme exemple).

      Elles sont donc traitées différemment !

      Répondre

      • Les Timers (I) 20 juillet 2016 12:03, par Christian

        Merci Dominique pour ces précisions.
        Comme je l’ai déjà dit, je ne suis pas un pro en langage C puisqu’on peut tout à fait programmer des Arduinos en se contentant des fonctions de base décrites dans la page arduino.cc/en/Reference/HomePage.
        Dans certains cas, la connaissance des subtilités du C permet de faire plus rapidement, voir plus précisément. Mais ceci ne concerne pas forcément les débutants qui peuvent déjà réaliser bien des animations en n’ayant qu’une connaissance restreinte du langage.

        Répondre

  • Les Timers (I) 6 octobre 2016 20:23, par Reibel Daniel

    Bonjour
    Merci pour ce tuto tres interessant.
    Neanmoins etant en possession d’une M0PRO, donc d’un micro different de la UNO, le code propose est il compatible ? Et si non, comment adspter le code ? (Je n’ai pas teste)

    Bien Cordialement
    Daniel

    Répondre

  • Les Timers (I) 7 octobre 2016 10:39, par Christian

    Bonjour Daniel,

    Je ne connais pas la MOPRO mais vous dîtes que le µC est différent de celui de la carte UNO.
    Il y a donc peu de chance que le code fonctionne sans être adapté car très certainement, les registres liés au timer ne seront pas les mêmes.
    La première chose à faire est donc de se procurer la documentation concernant le µC. On la trouve sur le site du constructeur. Ensuite, il faut prendre son courage à deux mains pour étudier et comprendre comment fonctionne les timers du µC : ce travail demande de la persévérance, parfois on a l’impression de ne pas comprendre un point mais celui-ci s’éclaircit au fur et à mesure de la lecture du document et on peut alors revenir en arrière. Bien sûr, il faut lire l’anglais ou bien se faire aider (on peut aussi essayer les traducteurs automatiques comme Google mais le résultat n’est pas toujours optimal même si des progrès ont été réalisés ces dernières années).
    Le principe des timers reste le même pour tous les µC : un timer n’est jamais qu’un compteur qui s’incrémente ou se décrémente à chaque nouveau cycle de l’horloge. Le timer est "relié" à des registres (case mémoire) qui modifie le fonctionnement du timer en fonction de ce qu’ils contiennent. C’est ce que j’ai montré dans la série d’articles. Si vous comprenez le rôle de ces registres, vous maîtrisez la fonctionnement du timer et ce quel que soit le modèle et la marque du microcontrôleur.
    Je vous souhaite bon courage et vous verrez que cette étude est passionnante : elle vous apprendra plein de choses et vous donnera l’avantage de maitriser ce qui se passe sous le capot du µC !
    Cordialement.

    Christian

    Répondre

  • Les Timers (I) 13 novembre 2016 10:00, par michael

    Dans la doc Arduino, il est dit que les 3 derniers bits du TCCR2B sont CS2, CS1 et CS0. Pour diviser par 256, il est dit qu’on doit avoir 1/0/0 sur ces 3 bits. Dans votre code, si je lis bien, vous avez mis 1/1/0, ce qui correspond à une horloge externe sur front descendant... Je ne comprends pas...

    Répondre

    • Les Timers (I) 13 novembre 2016 16:18, par Christian

      Bonjour Michael,

      Pourriez-vous me dire où vous avez lu dans la doc que la valeur des trois derniers bits devait être 1/0/0 ?

      Si vous ouvrez la datasheet de l’ATmega328P du constructeur Atmel, on peut y lire en page 162, à l’avant dernière ligne du tableau 17-9, que les valeurs 1/1/0 divisent par 256.

      Dans le setup du programme, quatrième ligne, c’est donc bien ce que je rentre (0b00000110) dans TCCR2B.
      De plus, j’ai téléchargé le programme de l’article et je l’ai essayé sur un module Uno ; j’ai bien compté 60 allumages en 1 minute, soit une fréquence de 1 Hz. Le programme fonctionne donc comme il est prévu.

      J’espère que ceci répond à votre question mais n’hésitez pas à me recontacter si nécessaire.

      Cordialement.

      Christian

      Répondre

      • Les Timers (I) 13 novembre 2016 17:05, par michael

        Sur ce site : http://letsmakerobots.com/node/28278
        Et dans la doc de l’ATmega1280 puisque ma carte est une MEGA.(page 130 tableau 16-9)
        Est-ce à ce point différent entre UNO et MEGA ?

        Répondre

        • Les Timers (I) 14 novembre 2016 14:59, par Christian

          Bonjour Michael,

          La carte ATMega2560 est basée sur le µC ATmega2560 d’Atmel, qui est donc différent du µC ATmega328P des cartes Uno. Or, ce qui est fait pour l’un ne peut pas forcément s’adapter à l’autre, un peu comme la distribution d’un moteur 4 cylindres est différente de celle d’un 6 cylindres.

          Vous citez le tableau 16-9 en page 130 de la doc Atmel que j’ai téléchargée pour avoir la dernière version (c’est toujours mieux) : ce tableau parle des bits CS02, CS01 et CS00, donc pour le timer 0 du µC ATmega2560.

          Enfin, concernant le site que vous indiquez, la table 16-5 est donnée pour les trois bits CS12:0, ce qui concerne le timer 1 et non le timer 2 comme dans mon article.

          Si vous choisissez le timer 2 du µC de la carte Mega, le tableau de la doc Atmel 20-9 en page 186 indique que pour diviser par 256, les trois bits du TCCR2B doivent être 1/1/0. En conséquence, mon programme devrait aussi fonctionner pour une carte Mega, mais je n’en ai pas sous la main pour le vérifier.

          Je pense néanmoins que vous avez compris le principe et qu’il vous sera donc possible d’adapter mon programme à votre carte Mega.

          Dites-moi si mon programme fait bien clignoter la LED 13 à la fréquence de 1 Hz sur votre carte Mega.

          Bien cordialement.

          Christian

          Répondre

  • Les Timers (I) ,commentaire 8 avril 2017 01:00, par PIVAR

    je fais du soft pour des bécanes de labo (on a commencé par du python sur Rasp ; ça marche mais les timers sont >=1ms et le programme reste accessible à l’utilisateur ; l’interface ecran avec boutons , labels , graphiques est correcte) ; je vais recevoir un ard mega dans 2 semaines pour voir ce que l’on peut en tirer ; interface réalisée en B4J qui doit causer avec arduino par usb , celui ci doit piloter les vannes et moteurs pas à pas
    Donc , à cause du timer je tombe sur ce site que je vais deguster lentement comme une sucette ; félicitations , c’est très bien fait (vous pourriez le relier et le vendre , j’en prendrai un)

    Répondre

    • Les Timers (I) ,commentaire 8 avril 2017 12:40, par Christian

      Bonjour PIVAR,

      Content que cet article vous ait plus ; j’ai aussi pris beaucoup de plaisir à écrire cette série sur les Timers.

      Je vous renvoie à ce que j’ai écrit un peu plus haut : les Timers de l’Arduino Mega nécessitent une petite adaptation par rapport à ce que j’ai écrit pour l’UNO, mais le but de mon article est d’expliquer comment fonctionne un timer. A partir de là, et avec la datasheet d’un autre µC, on peut toujours programmer ce que l’on veut.

      Bonne continuation dans votre lecture.

      Répondre

      • commentaire 8 avril 2017 18:09, par PIVAR

        J’ai voulu m’inscrire au forum , mais ayant lu la première phrase (pas de train), j’ai reculé ; je ne veux pas polluer votre site qui est bien fait ; mais comme je n’ai pas encore la chose , une question surement stupide car je n’ai pas trouvé de réponse sur le web : comment faire pour qu’un programme se lance sur l’arduino dès la mise sous tension , sans intervention ?
        Ce message ne s’autodétruira pas après lecture , mais vous pouvez le faire

        Répondre

        • commentaire 8 avril 2017 20:52, par Christian Bézanger

          Lors de la mise sous tension ou après un RESET, la carte Arduino attend un peu pour voir si elle reçoit quelque chose via le bootloader, puis s’il n’y a rien (pas de programmation), le programme qu’elle a en mémoire se lance automatiquement. Il n’y a donc rien à faire.
          Certaines cartes clones ont besoin d’un RESET pour démarrer le programme après programmation, mais logiquement le programme en mémoire doit démarrer peu de temps après la mise sous tension.
          Si rien ne se passe à la mise sous tension, il faut examiner le programme pour voir s’il fonctionne (parfois rien ne se passe parce le programme n’est pas bon). On peut utiliser le moniteur pour voir par où passe le programme pour examiner que chaque phase se déroule bien. Il suffit de mettre des ordres println là où on veut contrôler.

          Répondre

          • commentaire 8 avril 2017 21:13, par Dominique

            Je confirme : Christian à raison : quand le programme est televersé on débranche le PC et l’Arduino fonctionne tout seul. J’en ai plusieurs comme ça sur mon réseau, reliés en réseau CAN et tout se passe bien sans PC ;)

            Répondre

            • programme au demarrage 13 avril 2017 14:29, par PIVAR

              Merci , je verrai plus clair avec le matériel , quand reçu , mais un point que j’ai du mal à saisir , quand Christian dit :"le programme qu’elle a en mémoire se lance automatiquement" ; dans quelle mémoire est donc le programme , (c’est pas de la Ram) , et qui l’y a mis ?

              Répondre

              • programme au demarrage 13 avril 2017 18:43, par Christian Bézanger

                Le programme est dans la mémoire de programme qui est de la mémoire flash.
                Celui qui l’a mis là est le programmeur quand il a televerser le programme qu’il a écrit dans son module Arduino par l’intermédiaire de l’IDE.
                Revoir les notions de base avant de s’attaquer aux Timers.

                Répondre

                • programme au demarrage 14 avril 2017 08:38, par PIVAR

                  excusez , avec le matériel , je n’aurai pas posé la question , mais pas encore reçu
                  Ok , compris ;il n’y a qu’un programme dans arduino , qui est lancé après examen du bootlander ; mais grace à vos tutos , j’ai écrit mon premier timer à interruption :fréquence déterminée par TCCR.. au démarrage , durée du front haut et du front bas variables , nombre de pas variables (ce qui suffira pour piloter un moteur pas à pas)
                   ; ça va bugger , mais je pense le principe correct

                  Répondre

  • Les Timers (I) 21 avril 2017 16:29, par Rachid

    Bonjour,

    J’utilise une carte Arduino Micro,

    Je souhaite générer deux fréquences en utisant deux timers mais je n’y arrive pas.

    J’aurais besoin d’assistance je souhaite avoir deux fréquences l’une à 30Hz et l’autre variable 7Khz - 11Khz.

    Celle à 30 Hz doit être précise et peux être interne, car elle génère une interruption. L’autre sortir une broche.

    J’ai réussi à avoir un code mais pour configurer un autre timer je n’y arrive pas. Si quelque pouvais m’aider :

    /*
    Programmer un signal PWM normal (lent), symétrique et non inversé sur la sortie OC1B/PB6 (timer 1/comparateur B) correspondant à la pin 10 ,
    les valeurs peuvent être :
    - configuration sortie : DDRB[6] = 1
    - prédiviseur : CS1[2:0] = 1 (f/1)
    - mode : WGM1[3:0] = 8 ("PWM, Phase and Frequency Correct" avec ICR1)
    - fréquence : ICR1 = 800 (fout = 16MHz/(2·prédiviseur·ICR1) = 10 kHz)
    - polarité : COM1B[1:0] = 2 (signal non inversé)
    - rapport cyclique : OCR1B (relativement à la valeur de ICR1)
    
    */
    
     int frequence ;    
     int freq1 ;        // fréquence = 8 kHz (800 pour 10KHz)
    
    unsigned int  dutycycl ; // rapport cyclique rel. icr1
    
    void setup() {
    
      Serial.begin(9600);  // initialize the serial 1 communication
      // pinMode(10, OUTPUT); 
     
      // OC1A et OC1C inutilisées
      unsigned char com1A = 0;
      unsigned char com1C = 0;
      
      // 8 kHz sur sortie 10 Micro (OC1B/PB6)
      unsigned char cs1   = 1;   // prédiviseur = f/1  (mettre à 1 pour fonctionner en kHz)
      unsigned char mode1 = 8;   // mode = 8 
      unsigned char com1B = 2;   // signal non inversé
      
    
      unsigned int  freq = 1000 ; // fréquence = (1000 pour 8 kHz et 800 pour 10KHz)
     
      unsigned int  dutycycl = freq/2 ; // rapport cyclique rel. icr1
    
    // check if data has been sent from the computer:
    
      DDRB |= 1<<6;
      TCCR1A = (com1A<<6)|(com1B<<4)|(com1C<<2)|(mode1&3);
      TCCR1B = ((mode1>>2)<<3)|cs1;
      ICR1 = freq;
      OCR1B = dutycycl;
    
    }
    
    void loop() {
      if (Serial.available()) {
        // read the most recent byte (which will be from 0 to 255)
        freq1 = Serial.parseInt();
        frequence = (16000/(2*1*freq1));
        // set the brightness of the LED:
        // analogWrite(ledPin, frequence);
      Serial.print("Saisir la valeur de la frequence en KHz:");
      Serial.println(freq1);
     
         ICR1  = frequence ;
         OCR1B = frequence/2 ;
      }
    }

    Répondre

    • Les Timers (I) 21 avril 2017 20:14, par Christian

      Bonjour Rachid,

      Ce n’est pas le meilleur endroit pour trouver de l’aide ; ici, c’est plutôt réservé pour faire des remarques sur l’article (quelque chose qui n’est pas clair ou bien une erreur, etc.).
      Je vous conseille d’ouvrir un fil sur notre forum que vous pourriez appeler "Timers du µC ATmega32U4" puisque c’est ce microcontrôleur qui équipe la carte Arduino Micro.
      Pour cette raison, le code que j’ai donné pour la carte UNO ne convient pas ; il doit être adapté au microcontrôleur ATmega32U4. Ceci nécessite d’avoir bien compris l’article puis de bien comprendre comment sont architecturés les Timers de ce µC.
      Suite à cela, vous trouverez certainement quelqu’un qui a l’habitude de ce microcontrôleur et pourra vous aider.
      Si ce n’est pas indiscret, expliquez la finalité de votre montage et pourquoi vous devez obtenir ces deux fréquences si différentes.

      Répondre

    • Les Timers (I) 28 avril 2017 00:34, par pivar

      Je commence aussi avec une Mega (et une wemos) ; le pc reconnait maintenant les ports en automatique ;j’aurai aussi besoin de plusieurs fréquences , mais un seul timer pourra suffire : en exemple , l’interruption du timer serait à 20kz , soit 50 microsecondes ; en plaçant 2 compteurs dans l’interruption , l’un qui compte 20000/30 impulsions (6666) déclenchera une void à 30Hz et l’autre qui compte 20000/(7000 à 11000) déclenchera la void à frequence variable

      Répondre

    • Les Timers (I) 14 mai 2019 09:39, par Dimi0801

      Bonjour,déjà merci pour cette proposition.
      J’aimerai effectuer un code pour mesurer deux fréquences sur deux entrées de la carte arduino ceci en utilisant deux timers et à partir de cet exemple je vois pas trop comment réaliser le mien. J’ai deux signaux dont je connecte sur la pin 5 et 6 de ma carte arduino uno et j’aimerais lire la fréquence de chaque signal. Besoin d’aide Svp. Merci

      Répondre

      • Les Timers (I) 14 mai 2019 12:43, par Christian

        Bonjour,

        Je ne sais pas pourquoi vous posez votre question à cet endroit (réponses faites à Rachid), et ce serait mieux d’ouvrir un fil sur le forum pour obtenir de l’aide.
        Pour obtenir la fréquence d’un signal, il faut mesurer sa période, donc une durée, ce qui peut tout à fait être fait avec un timer. Et pour cela, il faut surveiller les fronts montants et descendants du signal afin de faire démarrer la mesure de temps et la terminer au bon moment. Bien évidemment, il faut aussi considérer que le signal n’est peut-être pas symétrique, ce qui revient à dire qu’il faut faire la mesure toujours sur le même front (ascendant pas exemple).
        Ce n’est pas forcément un exercice simple et pour augmenter la précision, il faut faire travailler le timer le plus rapidement possible et compter le nombre de débordements pour obtenir ensuite une durée.
        Cordialement.
        Christian

        Répondre

  • Les Timers (I) 16 mai 2017 10:28, par Saïd

    Bonjour.
    Merci pour ce tutoriel. En effet j’ai remarqué une petite erreur, j’ai remarqué qu’à l’initialisation des registres de contrôle du timer, les bits CS22-CS21-CS20 doivent être à 1-0-0 et non pas 1-1-0. En tout cas c’est ce qui est mentionné sur le datasheet du microprocesseur.

    Pourtant votre programme a l’air de bien fonctionner avec ces réglages, comment est-ce possible ?

    Cordialement.

    Voir en ligne : Datasheet

    Répondre

    • Les Timers (I) 16 mai 2017 17:33, par Christian Bézanger

      Bonjour,

      Votre question ressemble à celle posée par michael le 13 novembre 2016 (voir plus haut). Je vous invite dans un premier temps à regarder ce que je lui ai répondu.
      Comme vous le dites, mon programme fonctionne (à la bonne fréquence), ce qui ne serait pas le cas si je m’étais trompé dans les registres. Je pense que vous avez lu la datasheet au mauvais tableau (au lieu de fournir la datasheet en entier, il aurait mieux valu fournir la page où vous avez lu les valeurs de CS22:0).
      Peut-être trouverez-vous par vous même la réponse à ce qui vous chagrine sinon je reste à votre disposition.

      Christian

      Répondre

      • Les Timers (I) 17 mai 2017 10:12, par Saïd

        Bonjour.
        En effet je me base sur le tableau 15-9 de la page 108 de la datasheet, ce qui, d’après la datasheeet, correspond bien au registre TCCR0B.

        Dans votre réponse à Michael, vous avez mentionné la page 162 d’une datasheet qui n’est plus disponible dans le lien que vous avez laissé. Pourriez-vous remettre cette datasheet ? Peut-être que ce n’est pas la même révision.

        Merci de votre réponse !

        Saïd

        Voir en ligne : Datasheet (page 108)

        Répondre

        • Les Timers (I) 17 mai 2017 10:24, par Saïd

          Je m’excuse, je parle de l’Arduino Méga alors que le tuto a été réalisé sur la Uno.
          En effet j’ai pu revérifier et j’ai vite compris que les bits du Clock Set ne sont pas les mêmes pour Timer0, Timer1 et Timer2.

          Répondre

          • Les Timers (I) 17 mai 2017 12:05, par Christian Bézanger

            C’est bien ce que j’expliquais : la carte MEGA n’est pas construite avec le même microcontrôleur que la carte UNO, donc le tutoriel doit être adapté à ce µC même si les principes restent les mêmes.
            Enfin, l’article utilise le Timer2, donc il faut régler TCCR2B et non TCCR0B qui concerne le timer0 (les bites CS22:0 ne sont pas les mêmes).
            Cet échange se termine bien ; l’important pour moi est que vous ayez compris ce qui vous posait un problème et que vous soyez capable d’adapter ce que j’ai dit à votre carte Mega (il faut seulement ne pas se tromper de registres donc prendre son temps pour ne rien oublier).
            Bonne programmation.

            Répondre

  • Les Timers (I) 28 janvier 2018 20:39, par Joël

    Bonjour,

    J’ai copié collé le code mais il ne fonctionne pas chez moi. J’ai bien un Arduino UNO, installé sans soucis et jamais eu de problème de téléversement récalcitrant.

    Aussi, j’ai bien pri le temps de lire cet article cependant certaines choses restent floues :

    Pour la ligne TCCR2B = 0b00000110 ; // CLock / 256 soit 16 micro-s et WGM22 = 0
    Ma question : pourquoi cela permet de mettre WGM22 à 0 alors que pour mettre WGM20 et WGM21 à 0 on avait dû utiliser un bitClear ? Je comprend pourquoi les trois derniers bits = 110 , c’est lié à CS20,21,22 donc pour diviser la fréquence avec le prescaler, mais en quoi cet octet va-t-il mettre WGM22 à 0 ?

    Deuxième question : pourquoi 0b et pas 0x ?

    Aussi, la ligne TIFR2 = 0b00000001 ; // TOV2
    Question : C’est bien pour réinitialiser le bit 0 de TIFR2, qui correspond au flag, ce qui se fait en plaçant ce bit 0 à 1 ?

    Le reste c’est ok j’ai compris.

    Répondre

    • Les Timers (I) 29 janvier 2018 12:04, par Christian

      Bonjour,
      Avez-vous utilisé le bouton "Télécharger" ou bien avez-vous fait un copier-coller du texte du programme ?
      Ecrire un octet, c’est comme écrire 8 bits en même temps, donc on gagne du temps. On peut utiliser les deux méthodes, soit mettre simplement le bit qu’on veut à 0 ou 1, soit réécrire tout l’octet. Parfois, c’est plus clair d’agir uniquement sur le bit concerné (pour celui qui relit le programme), parfois c’est plus rapide de changer tous les bits qui doivent l’être dans une seule opération.
      J’ai utilisé 0b car c’est la notation d’un octet en binaire préconisée sur le site d’Arduino.
      Dans cet article, on surveille le flag d’overflow et on le remet soi-même à 0. Vous verrez dans l’article suivant qu’on peut utiliser une routine d’interruption qui remet le flag à 0 d’elle-même. Même si vous avez encore des interrogations (ce qui est normal car ce n’est pas un sujet facile), lisez le deuxième article et peut-être que cela va s’éclaircir. Sinon on en reparlera bien évidemment.
      Christian

      Répondre

      • Les Timers (I) 29 janvier 2018 14:58, par Joël

        Bonjour,

        J’avais utilisé le bouton télécharger qui me redirigait vers une page texte dans laquelle se trouvait le code que je copiais et collais dans l’IDE d’Arduino, mais j’ai dû mal effectuer la copie car je viens de réessayer et le code tourne maintenant sur ma carte ! Aussi, merci pour vos précisions pour mes autres questions. Sinon j’ai bien lu le deuxième article qui est très clair. Je vais commencer a bidouiller maintenant.
        Merci à vous !

        Répondre

        • Les Timers (I) 29 janvier 2018 15:20, par christian

          Voilà au moins un problème résolu.
          L’article 2 reprend l’article 1 mais en utilisant une routine d’interruption (c’est bien pratique ces petites choses).
          Enfin, les articles suivant permettent de comprendre comment est générée la PWM par le microcontrôleur, et du coup de pouvoir générer sa propre PWM plutôt qu’utiliser la PWM fournie par Arduino dont la fréquence est trop faible pour commander nos moteurs.
          En conclusion, on réalise beaucoup de choses avec les timers, le plus difficile étant d’avoir une bonne connaissance des registres qui le contrôlent (le fameux qui fait quoi ?).
          Bonne fin de lecture et bon amusement.

          Christian

          Répondre

  • Les Timers (I) 30 janvier 2018 14:51, par Joël

    Bonjour,
    J’essaie d’adapter le code sur le timer0 mais ma led clignote environ toute les 3 secondes au lieu de clignoter tous les 500ms. J’ai utilisé la datasheet de l’atmel pour les valeurs du prescaler qui sont de 100 pour diviser par 256. Voici mon code :

    const byte RED = 5;
    #define LedToggleRed digitalWrite (RED, !digitalRead(RED))
    
    void setup() {
      pinMode (RED, OUTPUT);
      bitClear (TCCR0A, WGM00); // WGM00 = 0;
      bitClear (TCCR0A, WGM01); // WGM01 = 0;
      TCCR0B = 0b00000100; // Clock / 256 soit 16 micro-s et WGM02 = 0;
      TIFR0 = 0b00000001; // Réinitialisation du flag TOV0
      TCNT0 = 256 - 250; // Chargement du timer à 6
    }
    
    byte varCompteurRed = 0; // La variable compteur
    
    void loop() {
      if (bitRead (TIFR0, 0) == 1) { // Flag TOV mis à 1 ?
        TCNT0 = 256 - 250; // Rechargement du timer à 6
        bitSet(TIFR0, TOV0); // Remise à 0 du flag TOV0
        if (varCompteurRed++ > 125){ // Incrémentation et a atteint 125 ?
          varCompteurRed = 0; // On recommence un nouveau cycle
          LedToggleRed; // Inversion de la Led rouge
        }
      }
    }

    Répondre

    • Les Timers (I) 30 janvier 2018 18:00, par Christian

      Cet espace est réservé plutôt à des questions sur l’article en lui-même (signaler une erreur, un passage peu clair, etc.)
      Pour toutes questions concernant la programmation ou un projet, le mieux est de consulter le forum ou bien d’ouvrir un fil si rien n’existe.
      Merci de votre compréhension.
      (Je vais tout de même regarder le programme...)

      Répondre

  • Les Timers (I) 18 août 2018 23:47, par Liu

    Bonjour,

    Si j’écris TCCR1B = 0, le timer1 va s’arreter et le compteur TCNT1 ne changera plus, donc il n’y aura plus d’interruption associée au timer1, donc ça revient le même si j’écris TIMSK1 = 0.

    Est-ce que je me suis trompé quelque part ?

    Merci d’avance.

    Répondre

    • Les Timers (I) 15 septembre 2018 12:32, par Christian

      Bonjour Liu,

      Désolé de répondre si tard, je suis parti en vacances assez tardivement cet été.

      Mettre TCCR1B à 0 revient à mettre les bits CS10, CS11 et CS12 à 0 donc effectivement à bloquer le timer (tableau 20.7 page 173 de la doc du µC ATmega328P). Le compteur ne compte plus, donc ne peut plus déborder (ou comparer) : il n’y aura plus d’interruption.

      Le registre TIMSK1 (Timer Interrupt mask du compteur 1 décrit en page 184) sert à gérer ces interruptions si on en a le besoin ou pas. En le mettant à 0, vous interdisez toute forme d’interruption. Comme votre timer ne compte plus, cela n’a donc aucune importance.

      Néanmoins, ce n’est pas tout à fait la même chose. Le Timer est une chose, le registre de masques d’interruption une autre et il faut donc jongler avec les deux. Dans votre exemple, cela revient au même mais je me demande où vous voulez en venir. Si vous arrêtez le compteur, il ne fait plus rien alors vous n’avez plus à gérer d’interruptions. Il est parfois nécessaire dans un programme d’arrêter temporairement un Timer de même qu’il peut être indispensable de laisser tourner le Timer et d’arrêter temporairement les interruptions (pour ne pas perturber d’autres processus). C’est pour cela qu’un registre TIMSK a été créé.

      Je reste à votre disposition si ma réponse ne vous a pas satisfait.

      Cordialement.

      Christian

      Répondre

  • Pourquoi ne pas corriger le bug du ++ ? 3 septembre 2019 08:07, par fred

    varCompteur++ versus ++varCompteur ?

    Répondre

    • Pourquoi ne pas corriger le bug du ++ ? 5 septembre 2019 15:02, par Christian

      Je ne comprends pas votre question ni où se situerait le bug dans le programme donné qui tourne parfaitement.
      Voici donc un petit rappel de langage C/C++ qui peut être utile à d’autres :
      Les opérateurs ++ et — sont employés dans les cas suivants :

      incrémenter/décrémenter une variable (p.ex : dans une boucle). Dans ce cas il n’y a pas de différence entre la notation préfixe (++I —I) et la notation postfixe (I++ I—).

      incrémenter/décrémenter une variable et en même temps affecter sa valeur à une autre variable. Dans ce cas, nous devons choisir entre la notation préfixe et postfixe :

      Attention !

      X = I++

      passe d’abord la valeur de I à X et incrémente après

      X = I—
      passe d’abord la valeur de I à X et décrémente après

      X = ++I
      incrémente d’abord et passe la valeur incrémentée à X

      X = —I
      décrémente d’abord et passe la valeur décrémentée à X

      Je ne suis pas sûr d’avoir répondu à votre question mais c’est actuellement tout ce que je peux faire vu le peu d’éléments que vous donnez.
      Cordialement.

      Répondre

  • Les Timers (I) 14 septembre 2019 14:05, par Philippe T

    Merci pour votre travail.

    Dans l’exemple du timer2 avec interruption (TIMER2_OVF_vect) la LED ne clignote pas.
    En fait, il manque l’instruction pinMode (Led, OUTPUT) ;
    Par défaut, la LED est configurée en entrée ce qui explique pourquoi elle ne clignotait pas ...

    Répondre

    • Les Timers (I) 14 septembre 2019 18:22, par Christian

      Bonjour Philippe,

      Puisque vous parlez de la routine d’interruption TIMER2_OVF_vect, votre question porte sur le programme du deuxième article de la série Timer.
      Or, je viens de relire le programme et les sorties des LED sont bien déclarées dans le setup(). Vous le trouverez en lignes 12 et 13.
      Peut-être vous avez modifié ce programme involontairement ou bien alors, vous avez un mauvais contact sur votre LED.
      Dans le programme de cet article, la déclaration est faite en ligne 9.
      Cordialement.

      Christian

      Répondre

      • Les Timers (I) 14 septembre 2019 22:55, par Philippe T

        Merci Christian,
        En fait vous n’êtes pas vraiment concerné car il s’agit de l’exemple avec interruption proposé par Gérard en réponse suite à votre premier article qui contient l’erreur. La solution que vous proposé dans le second article est elle correcte.
        Cordialement,
        Philippe

        Répondre

        • Les Timers (I) 15 septembre 2019 01:06, par Christian

          Re-bonjour Philippe,
          Merci pour cette précision.
          D’où l’intérêt, quand on pose une question ou qu’on fait une remarque, d’être le plus précis possible et de donner le plus de détails possibles.
          Ce n’est pas toujours facile et notamment pour un auteur ; ce qui est évident pour lui ne l’est pas forcément pour tout le monde. C’est d’ailleurs à cela que sert cette rubrique pour s’exprimer sur un article. N’hésitez pas à dire si vous avez du mal à comprendre certains points : c’est peut-être nous qui nous exprimons mal !
          En tout cas, je suis assez content de voir que la série d’articles sur les Timers est une des plus lues bien qu’elle ne soit pas si facile à comprendre ; cela prouve que les lecteurs veulent se dépasser et c’est bien le but que nous poursuivons : tirer les gens vers le haut en leur démontrant qu’avec quelques efforts, tout est possible.
          Bonnes expériences arduinesques !!!

          Répondre

  • Les Timers (I) 17 octobre 2019 20:03, par paul reinfeld

    Bonjour
    Pourrait’on envisager de gérer par les timers la fréquence et les rapports cycliques PWM pour utiliser des servos digitaux .
    En pratique période de 3030µs avec longueur entre 900-2100µs(0 à 180°).
    Si vous pensez que c’est possible ,je me mettrai à l’étude des timers.
    Merci et félicitation pour votre explication sur les timers.

    Répondre

    • Les Timers (I) 30 octobre 2019 00:54, par Christian

      Bonjour Paul,

      Oui, cela me semble tout à fait possible mais reste à savoir si cela a un intérêt par rapport à l’utilisation de la bibliothèque Servo.
      Néanmoins, cela reste un bon challenge pour mieux connaître les timers.
      Christian

      Répondre

  • Les Timers (I) 25 octobre 2019 21:37, par Vital_ENONZAN

    Bonsoir Christian.
    Très bon article. Je ne comprends pas la ligne ci-dessous dans ton code :
    bitSet ( TIFR2 , TOV2 ) ; // Remise à zéro du flag TOV2
    Une remise à zéro ne se fait-elle pas avec un bitClear ? Merci.

    Répondre

    • Les Timers (I) 30 octobre 2019 01:06, par Christian

      Bonjour,
      C’est ce que j’explique dans l’article :
      "La dernière chose à savoir, c’est que pour réinitialiser le flag TOV2 par logiciel, il faut écrire à 1 le bit 0 du registre TIFR2 ; l’instruction est bitSet (et non bitClear comme on aurait pu le croire)."
      C’est une spécificité du microcontrôleur due à la façon dont il est construit et c’est expliqué dans la datasheet du composant. Il n’y a donc que cela à faire et un bitClear ne fonctionnerait pas.
      Christian

      Répondre

      • Les Timers (I) 31 octobre 2019 05:39, par Vital_ENONZAN

        Bonjour Christian,
        Merci pour la réponse. Avant de poser ma préoccupation, j’avais fait le test et constaté qu’avec un bitClear(), le programme ne fonctionne pas. Votre réponse me fait comprendre que lorsque le compteur TCNT2 arrive à 255, la valeur de TOV2 qui est à 1 passe automatiquement à 0 et en mode NORNAL du Timer, il faut dans le programme, dans le void loop(), la réiniser à 1 pour permettre au compteur TCNT2 de reprendre le processus de comptage.
        Mais lisez cette partie de l’article :
        "Chaque fois que le bit 0 du registre TIFR2 passe à 1, cela signifie que notre timer a compté un certain laps de temps (connu) ; il suffit alors de repositionner le flag TOV2 à 0 et d’incrémenter un compteur (une variable) pour continuer ce processus."
        Je pense que ça doit être :
        ...TIFR2 passe à 0 ...repositionner le flag TOV2 à 1.... Merci pour tout ce que vous faites. J’apprends beaucoup de ce site.
        Merci.

        Répondre

        • Les Timers (I) 31 octobre 2019 12:39, par Christian

          Voici l’ensemble du texte qu’il faut lire :
          "À partir de là, notre compteur comptera de 0 à 255 (cela lui prendra un certain temps) puis passera en débordement, c’est-à-dire qu’il repartira de 0 après avoir positionné le flag TOV2 (Timer/Counter 2 Overflow Flag) à 1. Il s’agit là du bit 0 du registre TIFR2. Chaque fois que le bit 0 du registre TIFR2 passe à 1, cela signifie que notre timer a compté un certain laps de temps (connu) ; il suffit alors de repositionner le flag TOV2 à 0 et d’incrémenter un compteur (une variable) pour continuer ce processus. Lorsque ce compteur arrive à une certaine valeur, c’est que le temps à attendre s’est écoulé."
          Quand le compteur déborde, le flag TOV2 est mis à 1. C’est ce que l’on surveille : chaque fois qu’il est mis à 1, cela signifie que le compteur a effectué un cycle de comptage. On compte le nombre de cycles de comptage, mais il faut auparavant remettre ce flag à 0 pour qu’il puisse jouer le même rôle au prochain coup et pour cela, il faut écrire 1 dedans (voir ma précédente réponse).
          Relisez l’article pour être sûr de ne pas confondre le timer avec les registres de contrôles du timer, et donc les différents flags : c’est bien cela la difficulté des timers, c’est bien comprendre qui fait quoi...
          Dans l’article suivant, on fait exactement la même chose mais au lieu de surveiller le flag TOV2, on utilise une routine (ou encore sous-programme), qui est appelée automatiquement lorsqu’il y a débordement du timer et qui réalise les opérations de remise à zéro du flag à notre place. On gagne en simplicité.
          Surtout, n’allez pas trop vite d’un article à l’autre. Pour que la série soit profitable, il faut bien avoir tout compris d’un article avant de passer au suivant.
          Et pour tout le monde (y compris pour moi), les timers sont un sujet compliqué qui demande du temps pour être digéré. Mais c’est aussi un sujet passionnant car là, on est vraiment au coeur du microcontrôleur.

          Répondre

          • Les Timers (I) 2 novembre 2019 07:26, par Vital_ENONZAN

            Bonjour Christian,
            J’ai compris. Je Vous félicite pour la qualité du travail et merci beaucoup pour votre disponibilité.
            Vital

            Répondre

            • Les Timers (I) 2 novembre 2019 10:33, par Christian

              Je pense que vous êtes prêt maintenant pour passer au deuxième article qui réalise la même chose que le premier mais de façon automatique grâce à une routine d’interruption. Une fois de plus, il est nécessaire de bien régler les différents registres de contrôle pour que cette routine puisse s’exécuter.
              C’est ce genre de traitement que vous utiliserez ensuite dans vos propres programmes utilisant les timers.

              Répondre

              • Les Timers (I) 9 novembre 2019 17:21, par Vital_ENONZAN

                Bonsoir Christian,
                Toutes mes excuses pour le retard de cette réponse.
                Je suis satisfait maintenant. Je suis sur le quatrième article de la rubrique timers.
                Suite à vos conseils, j’ai approfondi mes recherches pour mieux appréhender le fonctionnement des bascules. Le bit0(TOV2), du registre TIFR2, étant la sortie d’une bascule, lorsqu’il y a overflow, le système active automatiquement le "SET" de cette bascule pour mettre sa sortie TOV2 à 1. En mode normal et sans interruption, le programmeur doit demander au système de remettre la sortie TOV2 de la bascule à 0, pour permettre au compteur TCNT2, qui est passé à 0, de continuer par compter. Pour cela, il doit écrire dans le programme (dans void loop()) TOV2 = 1. Le système, en lisant cette instruction, sait qu’il doit activer l’entrée "RESET" de la bascule pour remettre sa sortie TOV2 à 0. Ceci est propre à une classe de microcontrôleurs dont les AVR font partie pour lesquels les entrées "SET" et "RESET" de cette bascule sont non inverseuses. Pour d’autres microntrôleurs, l’entrée "RESET" de ladite bascule est inverseuse et c’est en écrivant un 0 dans le bit correspondant que le système comprend qu’il faut mettre le fag à 0.
                Merci pour votre orientation et pour vos réponses.
                Pouvez-vous me soumettre, par courriel, à des réalisations pouvant me faire appliquer les contenus des articles sur les timers ?
                Vital.

                Répondre

  • Les Timers (I) 26 octobre 2019 11:47, par Vital_ENONZAN

    Bonjour Christian.
    Dis-moi stp.
    Est-ce qu’on peut positionner les bits CS20, CS21 et CS22 du régistre TCCR2B à 1 chacun pour diviser la fréquence d’horloge, de l’atemega328p, par 1024.pourquoi tu as donc préféré positionner ces bits à 1,1,0 pour faire une division par 250 ? je me dis qu’on pouvais aussi diviser par 1024 pour réduire la valeur que doit atteindre varCompteur pour avoir la fréquence de 2Hz recherchée.Merci

    Répondre

    • Les Timers (I) 30 octobre 2019 01:16, par Christian

      Bonjour,
      Il y a sans doute plusieurs façons d’arriver au même résultat : il suffit de reprendre ce qui est expliqué au paragraphe "Calcul théorique du comptage" en partant de la fréquence d’horloge choisie en sortie de diviseur.
      Pour ma part, je suis parti d’un calcul que je connaissais juste (un des exercices que j’ai eu à résoudre pour le cours sur les microcontrôleurs de l’Ecole Polytechnique Fédérale de Lausanne, cours que je recommande à tous puisque c’est un MOOC gratuit).
      Christian

      Répondre

      • Les Timers (I) 31 octobre 2019 05:50, par Vital_ENONZAN

        Merci Christian,
        Je veux juste savoir s’il est possible de diviser par 1024 alors que les régistres du Timer sont sur 8 bits. Merci

        Répondre

        • Les Timers (I) 31 octobre 2019 13:00, par Christian

          Il ne faut pas confondre jusqu’à combien le timer compte avec sa vitesse de comptage.
          Oui, le timer est sur 8 bits donc il ne peut compter que jusqu’à 255, après il repasse à zéro : c’est ce qu’on appelle débordement.
          Sa vitesse de comptage dépend de la fréquence de l’horloge du microcontrôleur : 16 MHz pour l’ATmega328, cela fait très rapide pour nous pauvres humains !
          Mais on peut ralentir la vitesse de comptage en divisant la fréquence de l’horloge : c’est le rôle du prescaler (prédiviseur en français) qui se règle avec les bits CS20, CS21 et CS22. Si on divise par 1024, alors la fréquence de comptage sera 16 000 000 / 1024 = 15625 Hz et un cycle durera 64 µs (soit 4 fois plus que dans l’article et c’est normal puisqu’on avait divisé par 256 au lieu de 1024, soit 4 fois moins).

          Répondre

          • Les Timers (I) 2 novembre 2019 07:33, par Vital_ENONZAN

            Bonjour Christian,
            merci pour la réponse très bien détaillée. Merci
            Vital

            Répondre

  • Les Timers (I) 1er février 2020 10:46, par Luchet

    Bonjour
    j’ai vu dans les articles sur les timers la notation suivante WGM22 : 0 = 3 je ne sais pas comment l’interpréter

    Merci de bien vouloir m’éclairer à ce sujet

    Répondre

    • Les Timers (I) 1er février 2020 11:44, par Christian

      Cette notation est expliquée dans l’article N°4 (elle n’a pas été utilisée avant dans la série) :
      On est dans ce mode si les 3 bits WGM2 de 0 à 2 sont égaux à la valeur 3 ou 7 (on écrit alors WGM22:0 = 3 ou 7, .....

      • WGM22:0 (les bits 0 à 2) est équivalent à WGM22, WGM21 et WGM20 et ces trois bits doivent donner la valeur 3 quand on note WGM22:0 = 3.
        Ce qui donne WGM0 = 1, WGM1 = 1 et WGM2 = 0, soit 011 en binaire ce qui vaut 3. Revoyez le premier des deux exemples de l’article N°4.
        Si on avait voulu la valeur 7, cela aurait donné 111.
        Il est à noter que ces trois bits appartiennent à deux registres différents TCCR2A et TCCR2B ; en fonction du bit concerné, il faut donc aller le chercher dans le bon registre. Rappelez-vous aussi que les bits sont numérotés de droite à gauche.
      • Cette notation se retrouve fréquemment dans les datasheets des microcontrôleurs ; il est donc préférable de la connaître.

      Répondre

      • Les Timers (I) 2 février 2020 10:07, par Luchet

        Bonjour
        Merci pour votre réponse je saurais maintenant déchiffrer cette notation

        Ps j’ai posté ce message dans cette partie pour que le lecteur suivant la comprenne lorsqu’il arrivera à la partie 4

        Répondre

  • Timer 1 horloge source 18 février 2020 16:06, par Jean-Pierre

    Bonjour Christian, et bravo pour vos pages, bien utiles à un débutant comme moi.
    Pour m’exercer à utiliser Timer1 et Timer2, j’écris des petits programmes dérivés de ceux que vous publiez ici.
    Mais si ce que j’obtiens avec T2 est conforme aux calculs, avec T1 il y a une erreur systématique dans le rapport 4 (le résultat est 4 fois plus lent).
    J’en viens à me demander si l’horloge de base est la même ? Est-ce que j’ai loupé quelque chose ?
    Cordialement,
    Jean-Pierre

    Répondre

    • Timer 1 horloge source 19 février 2020 10:46, par Christian

      Bonjour,

      Difficile de vous répondre avec aussi peu d’éléments. Comment avez-vous réglé les bits CS2:0 dans chacun des cas ? L’erreur peut provenir de là mais aussi d’autres registres.
      Le mieux est donc d’ouvrir un fil dans le forum car vous aurez des réponses bien plus rapides et vous pourrez déposer vos programmes, ce qui permettra de mieux comprendre ce qui se passe.
      Cordialement.

      Christian

      Répondre

  • Les Timers (I) 5 janvier 2021 19:52, par G-Quark

    Bonjour,

    Bravo pour cette page très claire !
    Un petite remarque néanmoins : dans votre introduction, vous confondez l’overflow qui concerne les opérations avec des nombres binaires signés avec le carry qui lui correspond en effet au "dépassement de capacité" du registre. Quand un registre de 8 bits est incrémenté d’une unité en partant de 255, il revient en effet à zéro mais en activant un bit de "carry" et non un bit "d’overflow".

    Voir en ligne : overflow bit

    Répondre

    • Les Timers (I) 6 janvier 2021 12:57, par Christian

      Je ne crois pas confondre le bit d’overflow avec celui de carry. Je vous invite à lire la suite (Les Timers II) et vous comprendrez que c’est bien un débordement par le haut qu’on surveille. Vous pouvez aussi lire l’article de Jean-Luc https://www.locoduino.org/spip.php?... qui explique le débordement.
      Si vous consultez la datasheet de l’ATmega328P, notamment la figure 17.2 page 117, vous verrez que c’est bien le bit d’overflow qui génère une interruption de la part du timer (Int. Req.) et absolument pas le bit de carry. D’ailleurs, le programme de l’article 2 fonctionne avec cette routine d’interruption générée par débordement du registre de timer.
      Et toujours dans la datasheet, à la page 281, vous verrez que les opérations d’incrémentation ou de décrémentation (mnémonique INC ou DEC) d’un registre de travail n’agissent absolument pas sur le bit de carry mais bien sur le bit de débordement.
      Le bit de Carry n’est d’ailleurs positionné qu’avec des opérations arithmétiques (addition, soustraction, comparaison, complément à un, complément à deux, décalage, etc.). Normal car dans ces opérations, le bit de Carry nous intéresse fortement pour que le résultat ne soit pas n’importe quoi (voir article de Jean-Luc déjà cité).
      J’espère vous avoir convaincu et cela ne remet absolument pas en cause ce qu’explique Wikipedia dans le lien que vous citez.

      Répondre

  • Les Timers (I) 8 janvier 2021 17:03, par Charles

    Bonjour,
    en tant que débutant je trouve vos articles très pertinents, clairs et bien expliqués donc un grand bravo.

    Cela donne envie de comprendre les différents points abordés même si ce n’est pas toujours évident et surtout lorsqu’il y a un loup.

    J’ai donc tenté de faire fonctionner le montage en haut de page, un vrai désastre pendant une bonne soirée mais je viens de découvrir l’arbre qui cache la forêt en me penchant sur la puce ATmega 32U4 qui équipe mon YUN.

    Dans les instructions ligne 12 en haut de page vous spécifiez de mettre

    TCCR2B = 0b00000110 ; // Clock / 256 soit 16 micro-s et WGM22 = 0

    Pour la valeur 0b00000110 la doc dit "External clock source on T0 pin. Clock on falling edge"

    En modifiant cette valeur à 00000100 ça le fait !!!!
    Cela ne pouvait pas fonctionner puisqu’il n’y avait pas d’horloge. Je pense que ça doit être pareil pour le circuit ATmega328P du UNO puisqu’ils sont déclarés de la même façon.

    Répondre

    • Les Timers (I) 8 janvier 2021 18:40, par Christian

      Logiquement, il ne doit pas y avoir de loup si vous refaites exactement la même manipulation que moi, avec le même matériel. Les programmes sont testés avant publication, souvent par plusieurs personnes du comité de lecture (ceux qui décident si un article est publiable ou s’il faut d’abord l’améliorer).
      Dans cet article, nous nous intéressons à l’ATmega328P alors que vous utilisez un ATmega32U4 ; bien évidemment, leur programmation ne se fera pas de la même façon, même si les grands principes sont les mêmes. Il faut donc bien vérifier dans la datasheet comment les différents timers du 32U4 s’utilisent, car appliquer un programme écrit pour une autre cible (ici 328P) risque de ne pas fonctionner correctement (voire pas du tout).
      Comme vous êtes débutant, je vous invite à acquérir une carte Uno car cette carte est bien décrite sur internet et dans Locoduino ; vous pourrez ainsi progresser plus vite dans la compréhension des microcontrôleurs. Ensuite, passer à un autre type de µC est facile car les principes restent les mêmes.
      Comme j’utilise très peu le 32U4, je ne peux pas vous donner d’indications ; il faudrait que je consulte la datasheet mais je préfère vous laisser faire car ce sera un excellent entraînement pour vous.

      Répondre

  • Les Timers (I) 9 janvier 2021 00:01, par Charles

    Je suis un peu surpris par votre réponse car avant de poster j’ai bien vérifié les docs et du 328p et celui du 32U4 et dans les 2 cas on trouve exactement la même chose soit :

    CS12 CS11 CS10

    • 1-----1-----0 External clock source on T1 pin. Clock on falling edge.

    Je ne vais pas insister puisque vous me semblez très sûr de vous.
    J’ai également un UNO et je vais le mettre à l’épreuve mais je ne crois pas aux miracles !!
    Je vous tiens au courant.

    Répondre

    • Les Timers (I) 9 janvier 2021 09:28, par Christian

      Inutile de le prendre comme cela ; je ne cherche qu’à vous aider.
      Oui je suis sûr de moi quand je dis que le programme fonctionne pour une carte Uno : je l’ai revérifié ce matin et n’ai eu aucun problème, la LED clignote ! Par contre, j’ai essayé de le compiler pour une carte Yun et bien évidemment, j’obtiens le message d’erreur "’TCCR2A’ was not declared in this scope". Donc, que vous obteniez des résultats en changeant la valeur de TCCR2B (qui aurait aussi déclenché une erreur de compilation) tient du miracle que je ne sais expliquer !
      J’ai donc téléchargé la notice de l’ATmega32U4 sur le site de Microchip. Puisque vous l’avez lue, il ne vous aura pas échappé que ce MCU n’a pas de timer2 ! Il a un timer 8 bit appelé timer0, deux timers 16 bits appelés timer1 et timer3, et un timer rapide appelé timer4 pouvant fonctionner de 32 à 96 MHz d’après la première page de la notice (ce que n’a pas l’ATmega328P).
      Donc, quand le programme à la ligne 12 utilise le registre d’un timer2 (TCCR2B entre autre), je ne vois pas ce qu’il se passe puisque ce registre n’existe pas pour le 32U4.
      Peut-être avez-vous utilisé le timer0 (8 bits) du 32U4 (il doit être assez identique à celui du 328P je suppose), mais dans ce cas, il faut changer tous les noms de registres de TCCR2 en TCCR0, mais vous n’indiquez pas dans votre premier message avoir fait cela.
      Je manque donc d’informations pour vous dire ce qu’il se passe chez vous, mais je doute que vous ayez pu utiliser ce programme pour une carte Yun puisque l’IDE arrive à des erreurs de compilation (normal puisque timer2 n’existe pas).
      Si vous voulez que je vous aide, j’ai besoin de savoir dans quelles conditions exactes vous avez utilisé ce programme. Bien cordialement.

      Répondre

  • Les Timers (I) 9 janvier 2021 12:22, par Charles

    Désolé, erreur de "débutant"
    J’ai testé ce matin un UNO et la diode clignote en effet.

    Pour compléter mon premier post je précise donc que en effet que c’est le premier timer0 qui avait été utilisé sur le YUN en ayant bien entendu changé toutes les ref TCCR2 —> TCCR0 etc.

    Bilan hors sujet : le YUN fonctionne mais il faut éviter dans ce cas TCCR0B = 0b00000110

    Cordialement.

    Répondre

    • Les Timers (I) 9 janvier 2021 13:43, par Christian

      "A la bonne heure !" comme disait ma marraine qui se réjouissait à la moindre occasion (une habitude qui nous ferait du bien à l’heure où les media nous sapent le moral !).
      Donc, vous avez utilisé le timer0 (8 bits) de la carte Yun en adaptant le programme. Très bon travail, surtout pour une personne qui se place dans les débutants. Et effectivement, si on regarde le tableau 13-8 de la notice du 32U4 (page 108), pour diviser la fréquence horloge par 256 (comme dans le programme de l’article), il faut bien rentrer 100 pour les bits CS02:0.
      Mais sur un ATmega328P, et pour le timer2, c’est bien 110 comme l’indique le tableau 17-9 (page 131) de la notice 328P (ce serait 100 aussi si on avait utilisé le timer0 tableau 14-9 page 87).
      Je vous invite donc à continuer votre découverte des timers, soit avec votre carte Uno, soit avec votre carte Yun mais dans ce cas, précisez bien ce que vous modifiez si vous voulez signaler un problème de fonctionnement. A votre service pour vous apporter de l’aide (dans la mesure de mes possibilités).

      Répondre

  • Les Timers (I) 28 février 2021 12:24, par sam

    bonjour :

    merci pour ces articles fort bien fait . j utilise depuis un certain temps ces cartes Arduino ( UNO et Mega ) après avoir
    utilisé des PICs programmé en ICSP .Réalisation de maquettes pédagogique pour la vulgarisation de l’astronomie
    comme quoi il faut lire et relire car je suis passer a coté d’informations maintenant que je trouve incontournable.Message d encouragement pour le temps passer par les auteurs de ces articles et qui sont d’ une aide précieuse.

    Répondre

    • Les Timers (I) 1er mars 2021 10:38, par Christian

      Merci pour ce message d’encouragement.
      Effectivement, écrire un article demande du temps afin de respecter des normes de présentation quasiment identiques pour tous nos articles. Ensuite, l’article est relu par un comité de lecture qui suggère des corrections afin d’améliorer le produit final. L’article est alors corrigé puis publié. Tout ce circuit un peu lourd garantit la qualité du site et tant qu’on opérera ainsi, nous continuerons à avoir des lecteurs. Et il y en a pour tous les niveaux, du débutant à l’expert. Et même si nous avons choisi le modélisme ferroviaire pour faire connaître Arduino, nous savons que ce site est également lu par ceux qui font de la robotique, de la domotique, de l’astronomie, du modélisme, des arts ou tout simplement ceux qui veulent comprendre les microcontrôleurs.

      Répondre

  • Les Timers (I) 31 mai 2021 22:31, par Francois

    Bonjour,

    Je découvre Arduino mais faisais un peu d’ASM par le passé.

    Comment faites vous pour déterminer le temps pris par les instructions en début d’interruption ?

    Quand vous faites :

    ISR (TIMER2_OVF_vect)

    // 256-6 —> 250X16uS = 4mS
    // Recharge le timer pour que la prochaine interruption se déclenche dans 4mS
    TCNT2 = 6 ;

    if (Compteur++ == 250)
    //250*4mS = 1S - la Led est allumée 1 S et éteinte 1 S
    Compteur=0 ;

    Vous n’incrémentez pas le compteur à 4 ms mais 4 ms + le temps de rentrer dans l’IT, de mettre 6 dans TCNT2, etc.

    En ASM on savait déterminé le temps passé à ses tâches pour compter le temps qu’on voulait, et pas plus. Y a-t-il une solution simple pour faire celà en Arduino ?

    Répondre

    • Les Timers (I) 1er juin 2021 09:35, par Christian

      En effet, le temps pour rentrer dans l’ISR va prendre quelques cycles horloge qui vont perturber le temps qu’on veut obtenir, mais il faut aussi comparer les ordres de grandeurs ; un cycle horloge dure 62,5 nano secondes à comparer avec la période à obtenir d’une seconde pour allumage ou extinction.
      Cette imprécision n’a aucune conséquence dans notre domaine du modélisme ferroviaire, mais en toute rigueur il faudrait en tenir compte. J’en ai parlé dans la série d’articles consacrée à l’assembleur ; l’IDE peut parfois rajouter des délais qu’on ne soupçonne pas (de l’ordre de quelques micro secondes) et la seule façon de calibrer une fonction temporelle est de faire appel à l’assembleur et de regarder précisément le nombre de cycles horloge qu’on utilise. Or l’utilisation de l’assembleur est plus compliquée que l’écriture en C/C++ ; la question à se poser est donc "avons nous besoin d’une telle précision ou non ?".
      Si la réponse est oui (très peu probable en modélisme ferroviaire), alors il faut développer en assembleur et comptabiliser le nombre de cycles horloge pour chaque instruction. Je ne connais pas de solution simple pour y parvenir avec Arduino qui a été conçu pour couvrir 99% des besoins des bricoleurs développeurs qui n’ont pas besoin d’une telle précision.

      Répondre

      • Les Timers (I) 1er juin 2021 11:19, par François

        Merci pour votre réponse complète, je ne suis pas du tout dans le modélisme ferroviaire mais je trouve pas mal ces arduinos pour le côté très accessible.

        Je suis d’accord avec vous concernant les ordres de grandeurs, c’est plus la dérive qui peut poser problème pour certaines applications. C’est vieux, de mémoire à l’époque je mettais toujours des nop avec plus ou moins selon le temps passé à exécuter les instructions précédentes, pour être déterministe, mais ça semble difficilement faisable en C.

        La solution idéale serait peut-être d’avoir les interruptions en assembleur et le reste en C.

        Répondre

        • Les Timers (I) 1er juin 2021 11:48, par Christian

          La solution idéale dont vous parlez est celle que je décris dans la série d’articles sur l’assembleur : développer majoritairement en C/C++ pour bénéficier de la puissance du langage et développer les fonctions critiques en timing en assembleur. Nous avons donné un exemple qui peut se faire à partir de l’IDE d’Arduino ou de Microchip Studio 7.

          Répondre

  • Les Timers (I) 21 juin 2021 16:51, par wesley

    Bonjour svp j’aimerais savoir où avoir si possible le programme permettant de générer des impulsions.
    En faits, je travaille sur la commande d’un onduleur triphasé par commande MLI et je suis bloqué sur comment es-ce que je pourrais utiliser des timer pour commander a des intervalles de temps régulier et rapide mes interrupteurs électronique

    Répondre

  • Les Timers (I) 22 juin 2021 14:20, par Dominique

    Essayez sur le site Arduino.cc

    Répondre

  • lien mort 19 mars 17:07, par Marco

    Bonjour Christian

    Merci beaucoup pour ton travail, tout à fait appréciable !
    Juste pour signaler que le lien http://www.atmel.com/images/doc8161.pdf que tu donnes pour la datasheet du uC est mort ..
    Il est valide sur le site de Sparkfun

    Voir en ligne : Datasheet doc8161.pdf rev.D

    Répondre

    • lien mort 19 mars 17:51, par Christian

      Merci pour les compliments et pour m’avoir signalé ce lien mort ; tout le problème d’internet où les choses ne sont pas éternelles. Nous avons un programme de scan de liens cassés, mais il n’a pas dû être utilisé depuis longtemùps.
      je vais faire le nécessaire.

      Répondre

    • lien mort 19 mars 18:03, par Christian

      Voilà qui est fait. En fait, c’est à cause du rachat d’Atmel par Microchip. Mais maintenant, il me reste à relire les autres articles pour voir s’il n’y en a pas d’autres à modifier.

      Répondre

Réagissez à « Les Timers (I) »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Programmation »

Les derniers articles

Les articles les plus lus