Bonjour,
J'ai un programme que je récupère et je que je souhaiterai faire marcher uniquement ISR(TIMER1_COMPA_vect) mais cela ne fonctionne pas. Le programme fonctionne uniquement avec ISR(TIMER1_COMPB_vect). Savez vous pour quelle raison. Merci d'avance de votre réponse.
Bonjour Kamil,
Oui cela fonctionne sans problème mais je voudrai comprendre un peu le code par curiosité. Le Timer 1 est sur 16 bits et il fonctionne en comparateur (si je ne me trompe pas), on charge la valeur OCR1A = (((F_CPU / 1000 / 1024)) * periodeA); soit 15625 soit 64µs. Du coup toutes les 64µs on a une interruption ? Est ce bien cela ?
Merci Kamill,
Dans un premier temps, je voudrai isoler le fonctionnement de OCR1A pour bien comprendre son fonctionnement (peut-être que je me trompe ? ou bien OCR1A est lié avec OCR1B ?)
TCCR1B = _BV(WGM12) | _BV(CS12) | _BV(CS10); Diviser par 1024 = CS12=1; CS11=0; CS10=1.
Fonctionnement en CTC : WGM12 = 1; WGM13 = 0
Est ce bien cela ou je me trompe ?
C'est OCRB qui est lié à OCRA. Les deux its ont la même période définie par OCRA (et le prédiviseur) et OCRB est le retard de l'it B par rapport à l'it A.
Dans ce cas je peux très bien raisonner uniquement sur OCRA et j'obtiens :
16:35:36.228 -> A
16:35:37.181 -> A
16:35:37.181 -> B
16:35:38.130 -> A
16:35:39.115 -> A
La période de A n'est pas tout à fait 1seconde. Je suis un peu lent et je ne comprends pas très bien ton expression :
OCR1A = (((F_CPU / 1000 / 1024)) * periodeA); F_CPU = 16 Mhz et priodeA=1000 dont tu charges bien la valeur 15625 dans le OCR1A non ?
du coup le Timer 1 comptes avec la nouvelle période 64µs (16Mhz/1024). Dont pour aller jusqu'à 15625 avec la nouvelle période de l'horloge à 64µs il faut 1seconde ? Je ne me trompe pas dans le raisonnement ?
Parce que tu fais une division avec des entiers (long). La division par 1024 laisse un reste non négligeable. Faire la division par 1024 en dernier.
Pour minimiser l'erreur il faudrait faire OCR1A = F_CPU / 1000 * periodeA / 1024;
C'est pour cette raison que je voulais enlever le OCR1B pour ne voir uniquement le fonctionnement de l'interruption OCR1A ci dessous le fonctionnement de ISR(TIMER1_COMPA_vect) :
18:38:11.731 -> A
18:38:12.708 -> A
18:38:13.666 -> A
18:38:14.616 -> A
18:38:15.569 -> A
18:38:16.527 -> A
18:38:17.513 -> A
18:38:18.466 -> A
18:38:19.421 -> A
18:38:20.376 -> A
18:38:21.328 -> A
18:38:22.314 -> A
18:38:23.269 -> A
18:38:24.226 -> A
18:38:25.178 -> A
18:38:26.127 -> A
C'est un peu plus juste, je pense que le faîte d'envoyer une valeur via le PORT série USB fait perdre un peu de temps.
En revanche je n'ai pas compris l'astuce de terminer par une division au lieu d'une multiplication nous fait minimiser l'erreur ? OCR1A = F_CPU / 1000 * periodeA / 1024;
Pourras-tu détailler ta réponse ? Merci Kamill.
Effectivement cela ne donne pas le même résultat :
09:14:09.151 -> 15000
09:14:09.151 -> 15625
Serial.println(((F_CPU / 1000 / 1024)) * periodeA); donne 15000 et
Serial.println(F_CPU / 1000 * periodeA / 1024); donne 15625
Je ne sais pas pour quelle raison ? Il a probablement arrondi le résultat en divisant ? Ou je me trompe ?
Oui il y a une troncature quand tu fais F_CPU / 1000 / 1024
Il y a aussi une troncature lorsqu'on fait F_CPU / 1000 * periodeA / 1024 mais le dividende est 1000 fois plus grand donc la troncature est plus faible.
09:49:13.418 -> A
09:49:14.431 -> A
09:49:15.421 -> A
09:49:16.402 -> A
09:49:17.411 -> A
09:49:18.405 -> A
09:49:19.426 -> A
09:49:20.424 -> A
09:49:21.429 -> A
09:49:22.403 -> A
09:49:23.405 -> A
09:49:24.407 -> A
09:49:25.409 -> A
09:49:26.413 -> A
09:49:27.411 -> A
Effectivement avec cette modification, on est au 1/100 de précision et je pense que dans la routine interruption :
ISR(TIMER1_COMPA_vect)
{ Serial.println("A");}
Il faut aller très vite si je me trompe du coup le faite d'envoyer sur le port série et afficher les valeurs nous fait perdre pas mal de temps.
Je ne sais pas si on peut mettre une sonde directement dans l'environnement de développement Arduino (IDE Arduino) pour regarder l'incrémentation d'une variable ? Je ne connais pas très bien l'environnement de développement Arduino mais j'avais travaillé (il y a très longtemps) sur IAR Embedded Workbench pour les microprocesseurs Motorola et on peut pratiquement faire du Debug en temps réel ce qui aide beaucoup dans la phase de développement.
Effectivement le traitement d'interruption doit être le plus court possible et en principe on ne met pas de Serial.print() dans l'interruption, sauf besoin de debug.
Cependant l'envoi sur la liaison série est bufferisé et tant que le buffer n'est pas plein Serial.print() est rapide puisque il se résume à formater le message et à le ranger dans le buffer. C'est le cas ici, comme l'interruption a lieu toutes les secondes le buffer a le temps de se vider.
A ma connaissance, il n'y a pas moyen d'utiliser un debugger sous l'IDE.
Merci pour les renseignements. Je me demande s'il existe des compilateurs autre que sur ce site qui nous permet d'avoir la possibilité de visualiser les registres, les variables, les interruptions etc..