Les Timers (I)
Les bases
. Par : Christian
Vous répondez à :
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…
41 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;
- }
- }
-
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.
-
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
-
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
-
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
-
-
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) ?
-
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.-
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 !
-
-
-
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 ?
-
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 !
-
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.
-
-
-
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 -
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
-
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…
-
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
-
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 ?-
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
-
-
-
-
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)-
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.
-
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-
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.-
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 ;)
-
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 ?
-
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.-
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
-
-
-
-
-
-
-
-
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() {
- // 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() {
- // read the most recent byte (which will be from 0 to 255)
- frequence = (16000/(2*1*freq1));
- // set the brightness of the LED:
- // analogWrite(ledPin, frequence);
- ICR1 = frequence ;
- OCR1B = frequence/2 ;
- }
- }
-
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. -
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
-
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
-
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
-
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)
-
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.-
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.
-
-
-
-
-
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.
-
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-
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 !-
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
-
-
-
-
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() {
- 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() {
- TCNT0 = 256 - 250; // Rechargement du timer à 6
- if (varCompteurRed++ > 125){ // Incrémentation et a atteint 125 ?
- varCompteurRed = 0; // On recommence un nouveau cycle
- LedToggleRed; // Inversion de la Led rouge
- }
- }
- }
-
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…)
-
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.
-
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
-