LOCODUINO

Les Timers (I)

Les bases

. Par : Christian

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 (…)

Retourner à l'article

Vous répondez à :

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

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.)

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

Rubrique Programmation

Les derniers articles

Les articles les plus lus