Bienvenue aux nouveaux arrivants sur FantasPic !
- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.
--- L’équipe FantasPic ---
- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.
--- L’équipe FantasPic ---
Modérateur : Jérémy
Mesure de temps avec un Timer
Bonjour !
Je souhaite mesurer la durée d'un état haut avec un PIC16f886 et son Timer. Je rencontre quelques soucis d'imprécision et je voulais donc avoir vos avis et expériences.
J'utilise un Quarz 20Mhz.
Tout simplement, ma boucle principale est composé de :
Et pour calculer la durée :
Pour des petits délais je n'ai pas de soucis, j'arrive à avoir une précision qui se rapproche de la microseconde mais dès que je passe au seconde... c'est pas la même.
Exemple pour ce code :
A l'aide d'un analyseur logique avec un taux d’échantillonnage de 4MHz : voir Mesure1.png
Le programme lui me retourne ms = 6252 et us = 478
Maintenant, j'augmente la durée de mon état haut avec
A l'aide d'un analyseur logique avec un taux d’échantillonnage de 4MHz : voir Mesure2.png
Le programme lui me retourne ms = 8227 et us = 97
Plus le delai est grand et plus l’imprécision est grande mais trop grande je trouve (je m'attendais à quelques centaine de us voir une milliseconde).
Est ce que mon calcul est efficace ? Un soucis avec l'oscillateur ou normal ?
Je souhaite mesurer la durée d'un état haut avec un PIC16f886 et son Timer. Je rencontre quelques soucis d'imprécision et je voulais donc avoir vos avis et expériences.
J'utilise un Quarz 20Mhz.
Tout simplement, ma boucle principale est composé de :
Code : Tout sélectionner
while (1)
{
ms = 0;
TMR1H = 0x00;
TMR1L = 0x00;
PORTAbits.RA1 = 1;
T1CON = 0x01; // Start timer
for (i=0 ; i<30000 ; i++)
{
for (j=0 ; j<60 ; j++)
{
if (TMR1IF)
{
TMR1IF = 0;
ms++;
}
}
}
PORTAbits.RA1 = 0;
T1CON = 0x00; // Stop timer
SYS_CalculRetard (ms);
}
Et pour calculer la durée :
Code : Tout sélectionner
void SYS_CalculRetard (unsigned int millisecond)
{
unsigned int timer = 0;
unsigned int us = 0;
unsigned int ms = 0;
us = millisecond * (535/5);
ms = (millisecond * (65/5)) + (us / 1000);
us = us % 1000;
timer = ((TMR1H << 8) + TMR1L);
timer /= 5;
us = us + (timer % 1000);
ms = ms + (timer / 1000) + (us / 1000);
us %= 1000;
millisecond = 0;
}
Pour des petits délais je n'ai pas de soucis, j'arrive à avoir une précision qui se rapproche de la microseconde mais dès que je passe au seconde... c'est pas la même.
Exemple pour ce code :
A l'aide d'un analyseur logique avec un taux d’échantillonnage de 4MHz : voir Mesure1.png
Le programme lui me retourne ms = 6252 et us = 478
Maintenant, j'augmente la durée de mon état haut avec
Code : Tout sélectionner
for (j=0 ; j<80 ; j++)
A l'aide d'un analyseur logique avec un taux d’échantillonnage de 4MHz : voir Mesure2.png
Le programme lui me retourne ms = 8227 et us = 97
Plus le delai est grand et plus l’imprécision est grande mais trop grande je trouve (je m'attendais à quelques centaine de us voir une milliseconde).
Est ce que mon calcul est efficace ? Un soucis avec l'oscillateur ou normal ?
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Modifié en dernier par Simlock le mer. 8 mars 2017 09:43, modifié 1 fois.
Mesure de temps avec un Timer
-
Jérémy
Administrateur du site- Messages : 2722
- Âge : 44
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
SAlut Simlock,
JE te propose de mettre un lien de la Data-sheet de ton PIC ! (procédure) .
Je pense que c'est ton programme qui ne va pas : Il te faut travailler avec des Interruptions si tu veux de la précision, sinon c'est mort !
La tout de suite j'ai pas trop le temps ! peut être ce soir .
A+
JE te propose de mettre un lien de la Data-sheet de ton PIC ! (procédure) .
Je pense que c'est ton programme qui ne va pas : Il te faut travailler avec des Interruptions si tu veux de la précision, sinon c'est mort !
La tout de suite j'ai pas trop le temps ! peut être ce soir .
A+
Mesure de temps avec un Timer
-
Jérémy
Administrateur du site- Messages : 2722
- Âge : 44
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
re, sur le trajet du retour à la maison j'ai pensé à ton histoire !
Il faut absolument que tu passes par une Interruption pour compter . Comme on ne sait pas la précision que tu souhaite partons sur 1ms .
Ensuite tu nous montre le réglage de ton OSCillateur pour obtenir une Interruption toutes les millisecondes .
A chaque interruption tu incrémente ton compteur de ms .
En l'état ton programme est très imprécis, voir bug carrément ! ( sauf si il n'est pas entier).
Tu as un super outils plutôt pratique pour régler ton OSC . : Timer calculator , mais c'est plus enrichissant de tout calculer avant , et de vérifier après avec !
Il faut absolument que tu passes par une Interruption pour compter . Comme on ne sait pas la précision que tu souhaite partons sur 1ms .
Ensuite tu nous montre le réglage de ton OSCillateur pour obtenir une Interruption toutes les millisecondes .
A chaque interruption tu incrémente ton compteur de ms .
En l'état ton programme est très imprécis, voir bug carrément ! ( sauf si il n'est pas entier).
Tu as un super outils plutôt pratique pour régler ton OSC . : Timer calculator , mais c'est plus enrichissant de tout calculer avant , et de vérifier après avec !
Mesure de temps avec un Timer
Bonjour Simlock, Jérémy, et bonjour à tous,
Quel Timer utilises tu, je dirais que c'est le Timer1, peux tu le confimer ?
Timer0
Timer1
Timer2
C'est normal d'avoir une imprécision, sur un temps de quelque seconde, car il faut tenir compte du débordement de ton Timer
soustraire la différence, qui est multiplier par le nombre de débordement.
Quelle est le temps que tu veux mesurer, mini, et maxi .
Il y a peut être une autre solution, y a tu réfléchis ?
A+
Quel Timer utilises tu, je dirais que c'est le Timer1, peux tu le confimer ?
Timer0
Timer1
Timer2
C'est normal d'avoir une imprécision, sur un temps de quelque seconde, car il faut tenir compte du débordement de ton Timer
soustraire la différence, qui est multiplier par le nombre de débordement.
Quelle est le temps que tu veux mesurer, mini, et maxi .
Il y a peut être une autre solution, y a tu réfléchis ?
A+
Mesure de temps avec un Timer
Bonjour Jérémy et Temps-x,
Merci pour votre aide.
Je souhaite maximum une précision de 5ms, je ne m'inquiète pas beaucoup c'est relativement lent pour un PIC. Mais je voulais m'amuser un peu et voir si je pouvais atteindre une précision de l'ordre de la microseconde
Pourquoi mon programme buggerait ? Je n'ai pas mis tout mon programme, je pensais que ces petits bouts suffiraient. La grosse boucle qu'il y a dans mon programme est juste là pour maintenir une broche à l'état haut et comparer ensuite la mesure du programme avec ce que je vois avec l'analyseur logique.
Configuration de l'horloge :
Je pensais pouvoir me passer des interruptions puisque lorsque le timer 1 atteint le maximum de son registre, il reset en levant le flag TMR1IF donc il me suffit juste d'incrémenter une variable pour dire lors de mon calcul final "attention ! il y a eu déjà x 65535 tick". Mais le registre, lui, continue de tourner et s'incrémenter. Le seul débordement que j'aurai serait le temps que j'arrête le timer ?
Par contre, si je joue avec l'interruption, cela veut dire que lorsqu'il y en a une, je dois :
J'espère que j'ai été clair et que je ne dis pas n'importe quoi
Merci pour votre aide.
Je souhaite maximum une précision de 5ms, je ne m'inquiète pas beaucoup c'est relativement lent pour un PIC. Mais je voulais m'amuser un peu et voir si je pouvais atteindre une précision de l'ordre de la microseconde
Pourquoi mon programme buggerait ? Je n'ai pas mis tout mon programme, je pensais que ces petits bouts suffiraient. La grosse boucle qu'il y a dans mon programme est juste là pour maintenir une broche à l'état haut et comparer ensuite la mesure du programme avec ce que je vois avec l'analyseur logique.
Configuration de l'horloge :
Code : Tout sélectionner
#pragma config FOSC = HS
OSCCON = 0x70; // Sert à rien vu que j'utilise l'oscillateur externe à 20MHz
OSCTUNE = 0x00;
Je pensais pouvoir me passer des interruptions puisque lorsque le timer 1 atteint le maximum de son registre, il reset en levant le flag TMR1IF donc il me suffit juste d'incrémenter une variable pour dire lors de mon calcul final "attention ! il y a eu déjà x 65535 tick". Mais le registre, lui, continue de tourner et s'incrémenter. Le seul débordement que j'aurai serait le temps que j'arrête le timer ?
Par contre, si je joue avec l'interruption, cela veut dire que lorsqu'il y en a une, je dois :
- - Aller dans la fonction à exécuter en cas d'interruption (géré par le compilateur soit)
- Reset le flag
- Reconfigurer le registre TMR1H et TMR1L de sorte que l'interruption s'effectue en 1us (par exemple)
- Incrementer mes variables de mesure.
J'espère que j'ai été clair et que je ne dis pas n'importe quoi
Mesure de temps avec un Timer
-
Jérémy
Administrateur du site- Messages : 2722
- Âge : 44
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Hello,
J'avoue ne pas comprendre ta méthode !
Tu es donc obligé d'imposer un temps de comptage, je suppose que ce sont tes boucle qui font cela ! Achauqe fois que tu incremente ton ms, en fait il s'est écoulé 13.107ms .
Moi j'aurais fait comme ceci, mais je suis pas très calé
Tu tourne à 20Mhz ! on divise par 4 car il faut 4 coup d'horloge pour exécuter une instruction . ce qui fait 5 000 000 d'instructions par secondes. soit 0.2µs par instructions.
Tu compte le nombre d'instructions effectues et tu multiplie par 0.2µs . Un truc du genre
Tu lance ton Timer préalablement remis à zéro . Il te suffit donc de compter le nombre d'instruction obtenu durant le laps de temps .
A chaque débordement du timer tu as eu donc 65535 instructions de passées.
J'avoue ne pas comprendre ta méthode !
Tu es donc obligé d'imposer un temps de comptage, je suppose que ce sont tes boucle qui font cela ! Achauqe fois que tu incremente ton ms, en fait il s'est écoulé 13.107ms .
Moi j'aurais fait comme ceci, mais je suis pas très calé
Tu tourne à 20Mhz ! on divise par 4 car il faut 4 coup d'horloge pour exécuter une instruction . ce qui fait 5 000 000 d'instructions par secondes. soit 0.2µs par instructions.
Tu compte le nombre d'instructions effectues et tu multiplie par 0.2µs . Un truc du genre
Tu lance ton Timer préalablement remis à zéro . Il te suffit donc de compter le nombre d'instruction obtenu durant le laps de temps .
A chaque débordement du timer tu as eu donc 65535 instructions de passées.
Mesure de temps avec un Timer
Bonjour Simlock, et Jérémy, et bonjour à tous,
C'est une précision que tu veux, ou un temps, car 5ms(5000µs) c'est largement faisable, sans passer par les diviseurs.
Avec le Timer1 (65535 /5)/1000 =13,107 ms
Comme je fais de l'assembleur, qui est mon langage de programmation, voici comment je fais :
Après on récupère la valeur de TMR1H, et TMR1L, normalement, il faudrait contrôler si le Timer1 à débordé
A+
Je souhaite maximum une précision de 5ms
C'est une précision que tu veux, ou un temps, car 5ms(5000µs) c'est largement faisable, sans passer par les diviseurs.
Avec le Timer1 (65535 /5)/1000 =13,107 ms
Comme je fais de l'assembleur, qui est mon langage de programmation, voici comment je fais :
Code : Tout sélectionner
remonte
btfss PORTA,1 ; est ce que RA1 est à l'état haut
goto remonte ; non RA1 n'est pas à l'état haut
; oui, RA1 est à l'état haut
clrf TMR1L ; remis à zéro de TMR1L
clrf TMR1H ; remis à zéro de TMR1H
bsf T1CON,TMR1ON ; lancer le timer1
boucle
btfsc PORTA,1 ; est ce que RA1 est à l'état bas
goto boucle ; non, RA1 n'est pas à l'état bas
; oui, RA1 est à l'état bas
bcf T1CON,TMR1ON ; arrêt du timer1
Après on récupère la valeur de TMR1H, et TMR1L, normalement, il faudrait contrôler si le Timer1 à débordé
A+
Mesure de temps avec un Timer
Bonjour,
Ok... regarde mon programme et tu vas voir que je le fait déjà. Multiplier par 0.2 revient à diviser par 5.
Désolé si j'ai pas très bien expliqué mon problème mais je crois que vous n'avez pas compris. Je ne demande pas un programme pour mesurer une durée, ça je l'ai déjà et il fonctionne, j'ai même mis des images. Je demande pourquoi j'ai une aussi grosse imprécision.
Je reviens à mon premier post.
Pour la première mesure, l'analyseur logique trouve 6 253 110us et mon programme mesure 6 252 478us soit un écart de 632us.
Pour la seconde mesure, l'analyseur logique trouve 8 293 471us et mon programme mesure 8 227 097us soit un écart de 66 374us.
Je précise que pour une dizaine de milliseconde, j'ai une précision à la microseconde !
J'ai donc résolu mon problème pour la seconde mesure, je reposte mon code avec une correction mineure sur le nom des variables pour éviter toute confusion (millisecond remplacé par overflow car plus logique) :
Le PIC ici peux maximum contenir une variable de 16bits soit 65 535. Or si ma variable overflow dépasse 612, je sors donc des capacités du PIC et ma variable revient à 0 et je rate donc 65 535us d'ou mon écart brusque plus haut. (613 * (535/5) = 613 * 107 = 65591)
Donc pour revenir au sujet de base, j'ai donc maintenant :
Pour la première mesure, l'analyseur logique trouve 6 253 110us et mon programme mesure 6 252 478us soit un écart de 632us.
Pour la nouvelle mesure, l'analyseur logique trouve 9 313 553us et mon programme mesure 9 312 710us soit un écart de 842us.
Pourquoi j'ai ce décalage et comment puis-je faire pour améliorer ça ?
Merci pour votre aide et votre patience ^^
Jérémy a écrit :Tu tourne à 20Mhz ! on divise par 4 car il faut 4 coup d'horloge pour exécuter une instruction . ce qui fait 5 000 000 d'instructions par secondes. soit 0.2µs par instructions.
Tu compte le nombre d'instructions effectues et tu multiplie par 0.2µs . Un truc du genre
Ok... regarde mon programme et tu vas voir que je le fait déjà. Multiplier par 0.2 revient à diviser par 5.
Désolé si j'ai pas très bien expliqué mon problème mais je crois que vous n'avez pas compris. Je ne demande pas un programme pour mesurer une durée, ça je l'ai déjà et il fonctionne, j'ai même mis des images. Je demande pourquoi j'ai une aussi grosse imprécision.
Je reviens à mon premier post.
Pour la première mesure, l'analyseur logique trouve 6 253 110us et mon programme mesure 6 252 478us soit un écart de 632us.
Pour la seconde mesure, l'analyseur logique trouve 8 293 471us et mon programme mesure 8 227 097us soit un écart de 66 374us.
Je précise que pour une dizaine de milliseconde, j'ai une précision à la microseconde !
J'ai donc résolu mon problème pour la seconde mesure, je reposte mon code avec une correction mineure sur le nom des variables pour éviter toute confusion (millisecond remplacé par overflow car plus logique) :
Code : Tout sélectionner
void SYS_CalculRetard (unsigned int overflow)
{
unsigned int timer = 0;
unsigned int us = 0;
unsigned int ms = 0;
us = overflow * (535/5);
ms = (overflow * (65/5)) + (us / 1000);
us = us % 1000;
timer = ((TMR1H << 8) + TMR1L);
timer /= 5;
us = us + (timer % 1000);
ms = ms + (timer / 1000) + (us / 1000);
us %= 1000;
}
Le PIC ici peux maximum contenir une variable de 16bits soit 65 535. Or si ma variable overflow dépasse 612, je sors donc des capacités du PIC et ma variable revient à 0 et je rate donc 65 535us d'ou mon écart brusque plus haut. (613 * (535/5) = 613 * 107 = 65591)
Donc pour revenir au sujet de base, j'ai donc maintenant :
Pour la première mesure, l'analyseur logique trouve 6 253 110us et mon programme mesure 6 252 478us soit un écart de 632us.
Pour la nouvelle mesure, l'analyseur logique trouve 9 313 553us et mon programme mesure 9 312 710us soit un écart de 842us.
Pourquoi j'ai ce décalage et comment puis-je faire pour améliorer ça ?
Merci pour votre aide et votre patience ^^
Mesure de temps avec un Timer
- paulfjujo
Expert- Messages : 2589
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
bonjour Simlock,
Les division par 5 sur des entiers .... ça laisse toujours des restes .. donc des inexactitudes
si tu testes dans un premier temps le comptage en cycles ...
et utilises ta calculette pour diviser par 5 ..
ou la valeur de f1 !
ou prend un quartz de 16MHz ..plus de probleme d'arrondi !
Code : Tout sélectionner
unsigned lond TuS=0;
unsigned int timer=0;
float f1;
......
while (1)
{
TuS=0;
overflow = 0;
TMR1H = 0x00;
TMR1L = 0x00;
PORTAbits.RA1 = 1;
T1CON = 0x01; // Start timer
for (i=0 ; i<30000 ; i++)
{
for (j=0 ; j<60 ; j++)
{
if (TMR1IF)
{
TMR1IF = 0;
overflow++;
}
}
}
T1CON = 0x00; // Stop timer
PORTAbits.RA1 = 0;
Tus=(unsigned long)overflow <<16;
timer = ((TMR1H << 8) + TMR1L);
TuS=Tus + timer; // <- en cycles
f1= (float)Tus * 0.2; // en µSec
}
Les division par 5 sur des entiers .... ça laisse toujours des restes .. donc des inexactitudes
si tu testes dans un premier temps le comptage en cycles ...
et utilises ta calculette pour diviser par 5 ..
ou la valeur de f1 !
ou prend un quartz de 16MHz ..plus de probleme d'arrondi !
Mesure de temps avec un Timer
Merci paulfjujo, déjà tu me simplifies beaucoup le calcul car je ne savais pas que "unsigned long" permettait de stocker un nombre sur 32bits. Je pensais que ce n'était pas possible sur in PIC16F.
J'ai donc essayé avec un Quartz 16MHz et donc sur une attente de 11 641 733us j'obtient dans le programme 11 641 067us. Soit 666us de différence.
Je pense que c'est l'imprécision de l'oscillateur et que je ne peux faire autrement. A moins d'acheter THE quartz super précis et qui ne dévie jamais...
En tout cas c'est bien plus précis que ce que je dois faire à la base
Merci pour l'aide apportée, j'ai appris quelques subtilités sur le chemin mais si vous avez d'autres suggestion sur l'imprécision je suis preneur.
J'ai donc essayé avec un Quartz 16MHz et donc sur une attente de 11 641 733us j'obtient dans le programme 11 641 067us. Soit 666us de différence.
Je pense que c'est l'imprécision de l'oscillateur et que je ne peux faire autrement. A moins d'acheter THE quartz super précis et qui ne dévie jamais...
En tout cas c'est bien plus précis que ce que je dois faire à la base
Merci pour l'aide apportée, j'ai appris quelques subtilités sur le chemin mais si vous avez d'autres suggestion sur l'imprécision je suis preneur.
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 41 invités