Pages: 1 [2] 3   Go Down
Author Topic: Plus d'info sur l'utilisation des Timer par l'environnement Arduino  (Read 6522 times)
0 Members and 1 Guest are viewing this topic.
France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5347
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ces "pause" concernent quel types interruptions ?
Toute les interruptions quels quelle soit, de type ISR (ou anciennement SIGNAL).

Les compteurs continuent de s'incrémenter normalement ?
Les compteurs TCNxx sont directement relié à l'horloge du microcontrôleur.
Ils s'incrémentent tant que leurs prescaler les reliant à l'horloge du µc est différent de 0 (0 = déconnecté de l'horloge).

(l'incrémentation des compteurs c'est bien fait par une interruption ?)
Non c'est matériel, il n'y as pas d'interruptions.
Si il devait y avoir une interruption à chaque tick de l'horloge cpu on ne pourrais rien faire smiley-wink

Et les interruption de type counter overflow, elle peuvent intervenir ?
Non, l'interruptions sera généré mais le morceaux de code lié ne sera pas appelé par le cpu.
SEI et CLI permettent d'autorisé ou d'interdire toute les interruptions au niveau du cpu.

Toutes les interruptions qui auraient du arrivent pendant cette période sont-elle jetées à la poubelle ou certaines sont-elles mises en file d'attente ?
Elles sont ignoré comme si elles n'avait jamais existé, les compteurs continue de s'incrémenter sans rien faire d'autre, etc ...
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Paris
Offline Offline
Sr. Member
****
Karma: 2
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci à tous, la brume se dissipe.

Finalement, au niveau des timer/counter, le "core arduino" ne consomme pas de ressource, il ne fait que paramétrer le timer0 pour ses besoins.

Je peux donc disposer à ma guise des 3 timers à partir du moment ou je n'utilise pas les fonctions suivantes :
micros(), millis(), delay(), analogWrite() qui utilise le timer0
La librairie Servo qui utilise le timer1

Sev
Logged

EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

IDF/SO
Offline Offline
Edison Member
*
Karma: 41
Posts: 2266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
analogWrite() qui utilise le timer0

Je n'avais pas compris comme cela , (mais c'est pas pour autant que j'ai raison) :
Merci d'avoir lancé ce sujet il est très intéressant.
Quote
• INT1/OC2B/PCINT19 – Port D, Bit 3
INT1, External Interrupt source 1: The PD3 pin can serve as an external interrupt source.
OC2B, Output Compare Match output: The PD3 pin can serve as an external output for the
Timer/Counter0 Compare Match B. The PD3 pin has to be configured as an output (DDD3 set
(one)) to serve this function. The OC2B pin is also the output pin for the PWM mode timer
function.
PCINT19: Pin Change Interrupt source 19. The PD3 pin can serve as an external interrupt
source.
Quote
• MOSI/OC2/PCINT3 – Port B, Bit 3
MOSI: SPI Master Data output, Slave Data input for SPI channel. When the SPI is enabled as a
Slave, this pin is configured as an input regardless of the setting of DDB3. When the SPI is
enabled as a Master, the data direction of this pin is controlled by DDB3. When the pin is forced
by the SPI to be an input, the pull-up can still be controlled by the PORTB3 bit.
OC2, Output Compare Match Output: The PB3 pin can serve as an external output for the
Timer/Counter2 Compare Match. The PB3 pin has to be configured as an output (DDB3 set
(one)) to serve this function. The OC2 pin is also the output pin for the PWM mode timer
function.

A ce que je comprend de la datasheet j'ai l'impression que  la pmw obtenue à partir du port B utilise le timer 2  et que celle obtenue à partir du port C utilise le timer 0.
En fait il faudrait un timer différent par port.
Les deux sont des timers 8 bits, seul le timer 1 (16bits) semble totalement libre.

Aurais-je raison ou me mettais-je le doigt dans l'oeil jusqu'au coude ?
Logged

Bretagne
Offline Offline
Edison Member
*
Karma: 16
Posts: 1395
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Toutes les interruptions qui auraient du arrivent pendant cette période sont-elle jetées à la poubelle ou certaines sont-elles mises en file d'attente ?
Elles sont ignoré comme si elles n'avait jamais existé, les compteurs continue de s'incrémenter sans rien faire d'autre, etc ...
Sauf si je me trompe, mais il me semble que le flag "interrupt" de chaque interruption est mis à 1 lorsque se produit l'évènement correspondant, ce flag n'est mis à 0 que si on écrit un 1 dedans ou dès le traitement de l'INT, ce qui fait que quand on fait un SEI() (ou en sortie d'ISR), toutes les interruptions intervenues pendant le CLI() sont traitées les unes après les autres, dans l'ordre d'importance (et non d'arrivée).

Pour ton projet, ça fait un paquet de choses à compter, je te conseillerais la mega, car les PCINT ne sont utiles que si on les traite tout de suite (il se peut que le signal ait disparu entre l'interruption et la lecture du port, dans ce cas, tu n'auras pas moyen de savoir qui a déclenché la PCINT).

Je maintiens que les timers sont indépendants, la seule chose qui les relie est le prescaler. lorsqu'on reset le prescaler, tous les timers auront un temps de retard ou d'avance sur le départ de comptage suivant (le prescaler est un bête compteur 10 bits avec l'horloge CPU en entrée (16MHz)...). Tu peux même configurer un timer pour compter les impulsions sur une pin (Tn ou n est le numéro du timer), ça se fait matériellement, et ça permet de déclencher des int (COMPA, CMPB, OVF...)au bout d'un certain nombre d'impulsions... ou encore de relever la valeur du comptage au bout d'un temps précis pour connaître la fréquence de tes impulsions. pour le comptage d'impulsion, c'est super intéressant! mais seul la broche T5 du mega est routée, les autres entrées des timers sont pas accessibles, c'est vraiment dommage, voir nul.
Logged

Paris
Offline Offline
Sr. Member
****
Karma: 2
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
analogWrite() qui utilise le timer0

Je n'avais pas compris comme cela , (mais c'est pas pour autant que j'ai raison) :
Merci d'avoir lancé ce sujet il est très intéressant.
Quote
...Datasheet Atmega328P...

Aurais-je raison ou me mettais-je le doigt dans l'oeil jusqu'au coude ?

Je pense que nous ne parlons juste pas de la même chose, je parlais de l'utilisation faite des timer par le "core arduino", tu ne trouveras rien à ce sujet dans la Datasheet de l'Atmega, parce que Atmega ne sait pas ce que Arduino fait avec son controlleur smiley-wink

Sauf si je me trompe, mais il me semble que le flag "interrupt" de chaque interruption est mis à 1 lorsque se produit l'évènement correspondant, ce flag n'est mis à 0 que si on écrit un 1 dedans ou dès le traitement de l'INT, ce qui fait que quand on fait un SEI() (ou en sortie d'ISR), toutes les interruptions intervenues pendant le CLI() sont traitées les unes après les autres, dans l'ordre d'importance (et non d'arrivée).

Ok il faudra que je sois vigilant sur ce point.

Pour ton projet, ça fait un paquet de choses à compter, je te conseillerais la mega, car les PCINT ne sont utiles que si on les traite tout de suite (il se peut que le signal ait disparu entre l'interruption et la lecture du port, dans ce cas, tu n'auras pas moyen de savoir qui a déclenché la PCINT).

Je ne compte interrompre les interruptions ( smiley-roll) que une fois par trame (après la réception du dernier front), et ce uniquement dans le but de relever les valeurs, je pense sincèrement que cette "coupure" peut être légère, courte et bien positionnée.... mais ça reste bien sûr à verifier.

Je crains beaucoup plus pour la partie de recopie des canaux avec 5ms d'ecart, parce que la seule solution que j'ai trouvé pour le moment c'est qu'une interruption "ordonance" une autre interruption... tout ça avec une précision de 1 µs.  smiley-sweat

Sev
« Last Edit: June 20, 2012, 11:22:46 am by UniseV » Logged

EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

IDF/SO
Offline Offline
Edison Member
*
Karma: 41
Posts: 2266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Atmega ne sait pas ce que Arduino fait avec son controlleur

Ma remarque fait suite a tes propos qui laissaient à penser que la pwm ne dépend que du core arduino qui aurait choisi d'utiliser uniquement le timer 0.

A titre personnel j'avais compris différemment : le core arduino utiliserait les fonctions hardware cablées en dur à l'intérieur du micro-controleur.
Et par conséquence  le choix des timers pour la pwm ne serait  pas modifiable.

La réponse que j'espère est : qu'elle est la bonne réponse ?

J'en profite pour demander comment peut-on identifier avec certitude dans la datasheet du micro-controleur si une sortie de port peut ou non faire de la pwm.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Je rejoins ce que dit 68jts,

les pin OCxn de Atmel correspondent aux pins PWM de l'arduino, on peut donc penser que pour faire de la PWM ils utilisent les fonctions cablés prévues dans le microcontrôleur: c'est plus simple (et plus logique)

Mais les 6 pins PWM arduino correspondent aux sorties PWM pour les TROIS timers (OC0A,OC0B,OC1A,OC1B,OC2A,OC2B). donc en plus de gérer la PWM, ces timers servent pour les fonctions millis() et dérivées?

Comment s'assurer que ces timers sont dispo pour créer des ISR d'overflow ou autres?

(ces remarques sont pour les arduino basés sur un ATmega328)
Logged

J'apprends tous les jours!

Bretagne
Offline Offline
Edison Member
*
Karma: 16
Posts: 1395
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Comment s'assurer que ces timers sont dispo pour créer des ISR d'overflow ou autres?
il suffit de savoir sur quelles pins on fait un analogWrite(), si on utilise la pin OC1B par exemple, alors le timer1 n'est plus dispo, à moins de générer la PWM soit-même et il reste possible alors d'utiliser OCR1A pour des int internes, mais faut super bien réfléchir à la chose!

Je trouve qu'arduino est trop éloigné de l'atmega, car utiliser le datasheet atmel et la carte arduino en même temps demande une réflexion double (penser arduino et atmega en même temps, chaque fonction de l'un est différente chez l'autre), c'est une gymnastique pas facile. Mais quand on y arrive, alors on obtient une certaine fierté perso (du vécu)...
Logged

IDF/SO
Offline Offline
Edison Member
*
Karma: 41
Posts: 2266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
les pin OCxn de Atmel correspondent aux pins PWM
C'est ce que j'avais compris en lisant la datasheet, merci de ta confirmation.

Pour info hier soir j'ai trouvé un site donnant des explications très claires :
http://aquaticus.info/pwm
« Last Edit: June 21, 2012, 01:42:50 am by 68tjs » Logged

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5347
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

J'en profite pour demander comment peut-on identifier avec certitude dans la datasheet du micro-controleur si une sortie de port peut ou non faire de la pwm.
Il suffit de regarder le "pinout" du composant et chercher l'emplacement des broches annoté OCxn.
Puis de faire un tour dans les différentes rubriques timer/pwm et regarder le schéma de principe de celles ci.

les pin OCxn de Atmel correspondent aux pins PWM de l'arduino, on peut donc penser que pour faire de la PWM ils utilisent les fonctions cablés prévues dans le microcontrôleur: c'est plus simple (et plus logique)
La PWM "arduino" est généré en utilisant les générateurs de signaux PWM matériel, seul la librairie Servo utilise les timers "en timer" seul pour faire de la PWM logiciel.

Mais les 6 pins PWM arduino correspondent aux sorties PWM pour les TROIS timers (OC0A,OC0B,OC1A,OC1B,OC2A,OC2B). donc en plus de gérer la PWM, ces timers servent pour les fonctions millis() et dérivées?
Oui, cependant il ya une GROSSE astuce pour cela smiley-wink

Un signal PWM à toujours une fréquence fixe, en général dans les alentours de 500Hz ou 1KHz pour bien faire.
Le timer 0 est configuré pour générer les "tick" (interruption "on compare match") nécéssaire au bon fonctionnement de millis(), ...

En parallèle le générateur de signal PWM est indépendant, il est juste basé sur la fréquence/registre OCRxn du timer.
La team arduino n'as donc pas chercher bien loin, ils génèrent tout simplement le signal PWM sur OC0A et OC0B sans se soucié dans la fréquence du signal.
Ce qui laisse la partie interruption fonctionner normalement, et de faire de la pwm "pas trop mal" en même temps.

Comment s'assurer que ces timers sont dispo pour créer des ISR d'overflow ou autres?
Il n'existe pas de fonction hardware ou software pour cela.
Il faudrait lire la doc du core arduino en profondeur ... si elle existait ...
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

0
Offline Offline
Full Member
***
Karma: 0
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Je n'ai pas compris les dernières explications: le timer0 est utilisé pour appeler des ISR pour la fonction millis... et la PWM? elle est fabriquée dans l'ISR du coup? car on ne peut pas utiliser le fonctionnement interruption et pwm en même temps, il y une configuration bien précise des registres pour chaque utilisation...

Donc si je n'ai pas tout faux jusque là (c'est à dire si la PWM est fabriqué dans la routine d'interruption) pourquoi est elle associée aux pins correspondants OC0A et 0COB alors qu'ils auraient pu les laisser parfaitement libre...

(D'ailleurs je trouve qu'il est dommage de pas pouvoir générer plus de PWM / de signaux de servos, si on utilise les 3 timers on doit bien pouvoir dépasser les 12 signaux... et atteindre les 19:le nombre d'I/O!)

Bon en relisant ta réponse je viens de voir que je n'avais pas compris  smiley-sweat Donc si tu peux réexpliquer l'astuce, ça m'intéresse  smiley-lol
Logged

J'apprends tous les jours!

IDF/SO
Offline Offline
Edison Member
*
Karma: 41
Posts: 2266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Un signal PWM à toujours une fréquence fixe, en général dans les alentours de 500Hz ou 1KHz pour bien faire.
Attention de ne pas généraliser, ce que tu dis n'est valable que si on reste dans l' "univers de programmation arduino".
Comme il est écrit sur le site http://aquaticus.info/pwm-frequency le micro-controleur permet différentes fréquences en fonction du choix du préscaller (dans l'exemple du site la fréquence peut varier de 30 kHz à 30Hz).

En résumé il ressort de ces échanges très constructifs que mixer les univers arduino/avr-libc est super casse cou.

- il faut bien identifier les ressources matérielles utilisées par le micro lui même, ce n'est pas simple
  --> outil : lire et relire la datasheet
- il faut bien identifier les timers utilisés par les bibliothèques arduino, c'est malheureusement encore moins simple
  --> outil : le site arduino mais il est atrocement déficient.

Si on est obligé d'utiliser un timer déjà utilisé par les bibliothèques arduino il faut marcher sur des oeufs avant de modifier sa configuration.

Je vois là une idée d'un beau travail collectif pour créer un document qui préciserait l'état et la configuration de tout les timers pour l'ATMega328p et l'ATMega2560.


Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok après relecture de la datasheet et un peu de réflexion, je pense avoir compris commen les dev ont fait pour gérer les millis() en même temps que la pwm...

mode FAST pour la PWM, ce qui donne 2 sorties; et peut importe le mode de PWM choisie, ils ont configuré une routine d'interruption qui se déclenche au TOP (=MAX) du timer pour incrémenter des variables qui stocke le temps écoulé depuis la mise sous tension du bouzin. Et pour avoir une résolution à 4 µs près, ils regardent en plus où en est rendu le timer (entre 0 et 255)

Et comme le dis 68tjs, si on touche à la fréquence de découpage, on touche (au moins?) aux fonctions millis, micros et delay; et je trouve dommage que le site Arduino ne donne pas plus de détails, je n'ai absolument pas le niveau pour relire le code source de analogWrite() et millis().

Pour la coupe de robotique l'année prochaine je compte mélanger code Arduino et AVR, j'essaierai de penser à faire un retour d'expérience.
Logged

J'apprends tous les jours!

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5347
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Attention de ne pas généraliser, ce que tu dis n'est valable que si on reste dans l' "univers de programmation arduino".
Oui je reste dans le cadre "arduino", pour de la "vrai" PWM (fiable et bien conçu) on préférera des fréquences de plusieurs KHz pour quelle ne soit pas audible.
(Du reste en bricolant un peu dans le sens inverse il est possible de transformer n'importe quel moteur en instrument de musique smiley-wink)

En résumé il ressort de ces échanges très constructifs que mixer les univers arduino/avr-libc est super casse cou.
En résumé rien ne vaut eclipse, la toolchain avr-gcc et la doc de la avr-libc smiley-wink
Arduino c'est bien, mais dés que l'on veut faire quelques chose de plus poussé avr-c c'est bien mieux (et plus simple parfois).

Ok après relecture de la datasheet et un peu de réflexion, je pense avoir compris comment les dev ont fait pour gérer les millis() en même temps que la pwm...
Regarde dans wiring.c -> tu auras le fonctionnement de millis() et micros()
Regarde dans wiring_analog.c -> tu auras le fonctionnement de analogWrite()
Le principe est simple, le générateur de PWM est toujours en marche avec une interruption de type timer_overflow (disponible en mode FastPWM).

L'interruption incrémente le compteur de millis() et un compteur de "fraction de temps", millis() ne fait que lire son compteur, micros() lui se base sur le compteur de fraction de temps et l'état courant (à l'appel de micros()) du compteur du timer pour déduire un nombre de cycles, précis à 4µs prés.

AnalogWrite() ne fait qu'une seule chose, elle connecte la sortie du générateur de PWM à la broche OCxn en plaçant le "1" dans la case du registre qui va bien.
Et elle modifie le registre du générateur de PWM OCR0x en conséquence.

L'interruption de type 'overflow est donc toujours au même moment (à l'overflow du timer) quelque soit la valeur du générateur de PWM.
Une pierre, deux coups.

Et comme le dis 68tjs, si on touche à la fréquence de découpage, on touche (au moins?) aux fonctions millis, micros et delay; et je trouve dommage que le site Arduino ne donne pas plus de détails, je n'ai absolument pas le niveau pour relire le code source de analogWrite() et millis().
Le site arduino a un gros défaut, la documentation n'est que superficielle.
Pour un débutant c'est parfait, pour un utilisateurs expérimenté c'est insupportable.

En plus le code source en lui même contient des choses incohérente, des commentaires à faire pâlir un dév (du genre "this should works"), et mériterai une refonte complète sur certains points ...

Pour la coupe de robotique l'année prochaine je compte mélanger code Arduino et AVR, j'essaierai de penser à faire un retour d'expérience.
Mauvaise idée smiley-wink
Si le code doit être publié, soit tu écrit tout en arduino, soit tout en avr-c/c++ ne t'amuse pas à mélangé les genres ça ferait pas bonne figure.
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

0
Offline Offline
Full Member
***
Karma: 0
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Mauvaise idée smiley-wink
Si le code doit être publié, soit tu écrit tout en arduino, soit tout en avr-c/c++ ne t'amuse pas à mélangé les genres ça ferait pas bonne figure.

Mouais, mais certaines fonctions arduino comme le Serial sont bien pratiques pour débugger... et de toutes manières quand on achète les Arduino MEGA le Bootloader est installé, je voulais savoir si de base les timers étaient pré configurés.

Et puis si j'annonce du 100% avr-c/c++ je vais faire fuir tous les membres du club  smiley-yell
Logged

J'apprends tous les jours!

Pages: 1 [2] 3   Go Up
Jump to: