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
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Bonsoir a tous
Je vous expose ma problématique :
j ai besoin de calculer la période d ' un signal créneau ( de tension entre 0 et 5 volt ) en l appliquant sur l' un des pins du microcontrôleur plus précisément un pic 16f887
muni de la datasheet et d un dictionnaire anglais français je me suis lance a la recherche de méthodes pour arriver a mes fins ...
j hésite entre utiliser juste le registre du timer directement ( c' est a dire en initialisant le timer a 0 , le démarrant le compteur timer grâce a la détection d un premier front montant et en l arrêtant au second front montant ( temps entre deux fronts montant , temps d une période signal ) il restera qu' a multiplier la valeur du timer1 ( nombre de coups d horloge enregistres durant une période ) par la durée entre deux coups d horloge donc égale a 1/ F horloge ( suivant le prescaler choisi et l horloge interne ou externe ( externe dans mon cas ) la valeur du presclaer dépend de ma plage de période a mesurer pour éviter le débordement du timer je suppose ... )
ou utiliser le mode capture ?
si quel qu un pouvait m expliquer avec quelques détails de plus , ou un exemple de programme en c déjà existant et je m adapterais ... c est en se cassant la tété que l on assimile
PS : j effectue en parallèle un test des programmes sur mon circuit simule sous proteus , pratique avant la fabrication matériel .
Je travaille mon code sur MikroC
j attend vos réponse avec impatience
merci d avance de votre lecture
bonne soirée
Je vous expose ma problématique :
j ai besoin de calculer la période d ' un signal créneau ( de tension entre 0 et 5 volt ) en l appliquant sur l' un des pins du microcontrôleur plus précisément un pic 16f887
muni de la datasheet et d un dictionnaire anglais français je me suis lance a la recherche de méthodes pour arriver a mes fins ...
j hésite entre utiliser juste le registre du timer directement ( c' est a dire en initialisant le timer a 0 , le démarrant le compteur timer grâce a la détection d un premier front montant et en l arrêtant au second front montant ( temps entre deux fronts montant , temps d une période signal ) il restera qu' a multiplier la valeur du timer1 ( nombre de coups d horloge enregistres durant une période ) par la durée entre deux coups d horloge donc égale a 1/ F horloge ( suivant le prescaler choisi et l horloge interne ou externe ( externe dans mon cas ) la valeur du presclaer dépend de ma plage de période a mesurer pour éviter le débordement du timer je suppose ... )
ou utiliser le mode capture ?
si quel qu un pouvait m expliquer avec quelques détails de plus , ou un exemple de programme en c déjà existant et je m adapterais ... c est en se cassant la tété que l on assimile
PS : j effectue en parallèle un test des programmes sur mon circuit simule sous proteus , pratique avant la fabrication matériel .
Je travaille mon code sur MikroC
j attend vos réponse avec impatience
merci d avance de votre lecture
bonne soirée
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
bonjour,
Precise le domaine de frequence que tu veux mesurer ...
des exmplesICI avec choix Frequencemetre ou Periodmetre.
à adapter à ton cas ...
commence à presenter quelque chose .. et on t'aidera dans ta demarche.
Precise le domaine de frequence que tu veux mesurer ...
des exmplesICI avec choix Frequencemetre ou Periodmetre.
à adapter à ton cas ...
commence à presenter quelque chose .. et on t'aidera dans ta demarche.
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Bonjour
désolé , c est vrai que ça manque un peu de détails mon histoire
donc je m' explique :
la fréquence ( donc la période ) de mon signal d entrée ( signal issue d un capteur magnétique , sous forme d impulsions , qui grâce a un montage qui me sert d' étage de mis en forme , tout en conservant l information de fréquence , me transforme mon signal de base en signal créneau ( état haut 5v état bas 0v ) qu correspond a l information de régime moteur , c est ce signal créneau que je fournis a mon microcontrôleur .
La ou j ai besoin de plus de précision que possible c' est sur la plage régime moteur entre 500 et 14000 rpm ( en dessous de 500 tr/min le moteur tient pas le ralenti donc inutile de recevoir des informations pertinentes ) , donc entre 8 et 300 hz ( je prends beaucoup de marge )donc une mesure de période correct entre 125 ms et 3 ms ( histoire d avoir de la marge )
Sachant que l horloge que je vais utiliser pour cadencer mon pic est un quartz externe a 20 mhz , je suppose que ces infos vont servir a savoir quel prescaler je dois utiliser pour faire en sorte que le registre timer ne déborde pas même lorsque il va mesurer la plus grande période utile , dans mon cas 125 ms ? c est bien ça ?
Mais sachant que le débordement est a chaque fois indique par la mise a 1 d un drapeau , en comptabilisant ce nombre de débordements , on peut faire un programme qui compte plus précisément et surtout sur un bien plus grande plage de temps ( pour ne pas dire plus aucune limite sur ce point ..donc des fréquences en théorie très proche de 0 hz jus-qu a des fréquences très grandes ...
Si grâce a cette affaire , plus tard , je peux améliorer ma plage de fréquence de " 0" Hz a 400 Hz par exemple , ça pourra me servir pour une prochaine évolution mais nous n en sommes pas la et si je pouvais déjà avoir un truc qui marche pour une plage entre 8 Hz et 300 Hz sans gérer le drapeau de dépassement et juste en calibrant bien le prescaler a mon utilisation ce sera déjà très très bien
désolé , c est vrai que ça manque un peu de détails mon histoire
donc je m' explique :
la fréquence ( donc la période ) de mon signal d entrée ( signal issue d un capteur magnétique , sous forme d impulsions , qui grâce a un montage qui me sert d' étage de mis en forme , tout en conservant l information de fréquence , me transforme mon signal de base en signal créneau ( état haut 5v état bas 0v ) qu correspond a l information de régime moteur , c est ce signal créneau que je fournis a mon microcontrôleur .
La ou j ai besoin de plus de précision que possible c' est sur la plage régime moteur entre 500 et 14000 rpm ( en dessous de 500 tr/min le moteur tient pas le ralenti donc inutile de recevoir des informations pertinentes ) , donc entre 8 et 300 hz ( je prends beaucoup de marge )donc une mesure de période correct entre 125 ms et 3 ms ( histoire d avoir de la marge )
Sachant que l horloge que je vais utiliser pour cadencer mon pic est un quartz externe a 20 mhz , je suppose que ces infos vont servir a savoir quel prescaler je dois utiliser pour faire en sorte que le registre timer ne déborde pas même lorsque il va mesurer la plus grande période utile , dans mon cas 125 ms ? c est bien ça ?
Mais sachant que le débordement est a chaque fois indique par la mise a 1 d un drapeau , en comptabilisant ce nombre de débordements , on peut faire un programme qui compte plus précisément et surtout sur un bien plus grande plage de temps ( pour ne pas dire plus aucune limite sur ce point ..donc des fréquences en théorie très proche de 0 hz jus-qu a des fréquences très grandes ...
Si grâce a cette affaire , plus tard , je peux améliorer ma plage de fréquence de " 0" Hz a 400 Hz par exemple , ça pourra me servir pour une prochaine évolution mais nous n en sommes pas la et si je pouvais déjà avoir un truc qui marche pour une plage entre 8 Hz et 300 Hz sans gérer le drapeau de dépassement et juste en calibrant bien le prescaler a mon utilisation ce sera déjà très très bien
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
bonjour,
il faudra monter ton propre travail si tu veux de l'aide ..
une mesure de frequence ne convient pas .. ex: 8HZ +-1HZ avec une mesure par seconde ..
donc mesure de periode.
Si Q=20Mhz Fosc =Q/4 cycle = 4/Q= 4/20= 0.2µSec
400Hz => periode = 2500 µS
avec usage d'un timer1 16 bits prescaler mini=1/1
400Hz => 2500 / 0,2 => counts = 12500
8Hz => 125 000 µS 125000/0.2=625 000
avec au minimum 9 debordement de compteur.
avec une dynamique de 400/8 et si tu veux une bonne resolution ..
il faut obligatoirement comptabiliser les debordements compteur..
tu ne pourra jamais compter 0Hz !
deja pour 0,1Hz il faudra attendre 10 secondes ..
precise quel ref de PIC tu vas utiliser..
Comment tu affiches le resultat LCD,UART,Bluetooth ...
Tu as suffisament d'exemples sur le lien que je t'ai transmis pour pouvoir presenter
au moins une ebauche de programme .
Il faut quand meme potasser la datasheet du PIC choisi.(TimerX en mode CCP)
ou usage d'une entree interruptible (RB0 ?) + Timer1
il faudra monter ton propre travail si tu veux de l'aide ..
une mesure de frequence ne convient pas .. ex: 8HZ +-1HZ avec une mesure par seconde ..
donc mesure de periode.
Si Q=20Mhz Fosc =Q/4 cycle = 4/Q= 4/20= 0.2µSec
400Hz => periode = 2500 µS
avec usage d'un timer1 16 bits prescaler mini=1/1
400Hz => 2500 / 0,2 => counts = 12500
8Hz => 125 000 µS 125000/0.2=625 000
avec au minimum 9 debordement de compteur.
avec une dynamique de 400/8 et si tu veux une bonne resolution ..
il faut obligatoirement comptabiliser les debordements compteur..
tu ne pourra jamais compter 0Hz !
deja pour 0,1Hz il faudra attendre 10 secondes ..
precise quel ref de PIC tu vas utiliser..
Comment tu affiches le resultat LCD,UART,Bluetooth ...
Tu as suffisament d'exemples sur le lien que je t'ai transmis pour pouvoir presenter
au moins une ebauche de programme .
Il faut quand meme potasser la datasheet du PIC choisi.(TimerX en mode CCP)
ou usage d'une entree interruptible (RB0 ?) + Timer1
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
je vais essayer de faire un programme ce soir , on verra ce que l on peut faire après avec
Je vous tient au courant
merci encore
bonne soirée
j ai seulement besoin du résultat pour activer ou non une valve en sortie du microcontrôleur un pic 16f887
je vais gérer les débordements c est pas sorcier je pense , j ai mon idée la dessus
Je vous tient au courant
merci encore
bonne soirée
j ai seulement besoin du résultat pour activer ou non une valve en sortie du microcontrôleur un pic 16f887
je vais gérer les débordements c est pas sorcier je pense , j ai mon idée la dessus
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
voici une ebauche de mon programme :
Code : Tout sélectionner
// CHAINE DE MESURE
/*PROGRAMME qui as pour but de calculer la periode d ' un signal applique sur l entree int/rb0
d ou l utilisation du timer1 pour calculer le temps entre deux fronts montant donc de la periode du signal envoyé en entrée */
/* avec cette configuration prescaler 1 et horloge ext (20 mhz/4) pour timer0 , temps entre deux
incrementations du timer0 = 0.2 microsceondes */
unsigned int periode;
unsigned int temps;
unsigned int tempstotal;
float per_tim0 = 0.0000002; // temps entre deux incrementations du timer0 = 0.2 microsceondes
int a; // variable qui sert de condition test sortie de boucle des que l on as acqui notre periode
int dep; // variable qui stocke le nombre de depassements ayant eue lieu durant le comptage durant une periode
void main()
{
TRISC =0b00000000; // portc decalre en sortie logique pour l affichage du resulatat
TRISD =0b00000000; // portc decalre en sortie logique pour l affichage du resulatat
for(;;)
{
periode = temps = tempstotal = a = dep = 0; // initialisation des variables de stockage avant prochain calcul
TRISB.B0 =1; // pin 0 du port B est declare en entree pour l acquisition du signal
TMR1CS_bit = 1; // utilisation pour le timer0 de horloge externe a quartz
T1SYNC_bit = 0; // synchro entre l incremenattion du timer 0 et de l horloge externe
T1OSCEN_bit = 0; // oscillateur interne off / normal ( on s en sert pas )
T1CKPS1_bit = T1CKPS0_bit = 0; // prediviseur a 1 entre timer0 et horloge externe utilisé
TMR1L = TMR1H = 0; // initialisation du timer0
do
{
if(PORTA.B0 =0)
{
a=0; // le comptage de la periode commance seulement des que l' on detecte le premier front montant si non on reboucle tant que
}
if(PORTA.B0 =1) // le comptage de la periode peut commencer car on as detecte le premier front montant
{
TMR1ON_bit = 1; // mise en marche de l incrementation du timer1
do
{
if(TMR1IF_bit = 1) // boucle quidurant le comptage de la periode , comptabilise les debordement du timer0
{
dep=dep+1;
TMR1IF_bit= 0;
}
}while(PORTA.B0 =1);
TMR1ON_bit = 0; // arret de l incrementation du timer1
temps = TMR1H*256+TMR1L; // calcul de la valeur contenu si on accole les deux registres accolés sans compter le nombre de debordements
tempstotal = dep*1024+temps; // calcul nombres d incrementations en tout durant la periode , debordements multiples compris
periode = tempstotal*per_tim0; // calcul periode du signal
a=1;
}
} while(a=0);
PORTD = periode; // On envoie les 8 bits de points faibles sur le port D
PORTC = periode >> 8; // On fait un décalage des 8 bits de poids faibles pour faire apparaitre les 2 bits de poids fort restant sur le PORTC
}
}
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
bonjour,
je n'ai pas testé ton programme ,mais deja quelques anomalies à revoir
declarer TRISB.B0 =1; // pin 0 du port B est declare en entree pour l acquisition du signal
1 seule fois en dehors de la boucle principale suffit.
Ton programme ne mesure que l'etat haut du signal..
la periode c'est Etat Haut + Etat BAs
quid de la duree etat bas ?
Attention à la taille des variables..
lecture TMR1 sur 16 bits .. OK
mais cumul doit etre fait sur 32 bits : unigned long int TempsTotal
le Depassement Dep peut rester en int (16 bits)
mais au moment du cumul
1 debordement 16 bits c'est 65536 et non 1024 (confusion avec ADC ?)
il faut harmoniser les tailles
TempsTotal = (unsigned long) dep * 65536 + (unsigned long) temps;
Periode .. declaree en flottant
pour l'affichage si tu mutiplie par la duree du cycle 0,000002 tu auras un resultat en secondes !
tu veux afficher des Hz dans un premier temps ou des RPM
en Hz
periode en µS
Periode= (float) TempsTotal * 0.2; // µS
Freq declaré en unsigned int
Frequence = 1 /T
si Periode > 1.0 alors Freq = (unsigned int) (1000 000 .0 / Periode); // hz
arrondi au Hz pres
en RPM
quid de la relation Freq RPM .. 1 puls par tour ou n pulses par tour
simple mise à l'echelle
avec RPM en unisgned int (16 bits suffisent)
affichage:
toujours normaliser les tailles (meme si le compilo peut s'en debrouiller seul, c'est une bonne habitude)
PORTD =(unsigned char)' periode & 0x00FF ) ; // On envoie les 8 bits de points faibles sur le port D
PORTC = (unsigned char) periode >> 8; // On fait un décalage des 8 bits de poids fort pour les faire apparaitre sur le PORTC
je n'ai pas testé ton programme ,mais deja quelques anomalies à revoir
declarer TRISB.B0 =1; // pin 0 du port B est declare en entree pour l acquisition du signal
1 seule fois en dehors de la boucle principale suffit.
Ton programme ne mesure que l'etat haut du signal..
la periode c'est Etat Haut + Etat BAs
quid de la duree etat bas ?
Attention à la taille des variables..
lecture TMR1 sur 16 bits .. OK
mais cumul doit etre fait sur 32 bits : unigned long int TempsTotal
le Depassement Dep peut rester en int (16 bits)
mais au moment du cumul
1 debordement 16 bits c'est 65536 et non 1024 (confusion avec ADC ?)
il faut harmoniser les tailles
TempsTotal = (unsigned long) dep * 65536 + (unsigned long) temps;
Periode .. declaree en flottant
pour l'affichage si tu mutiplie par la duree du cycle 0,000002 tu auras un resultat en secondes !
tu veux afficher des Hz dans un premier temps ou des RPM
en Hz
periode en µS
Periode= (float) TempsTotal * 0.2; // µS
Freq declaré en unsigned int
Frequence = 1 /T
si Periode > 1.0 alors Freq = (unsigned int) (1000 000 .0 / Periode); // hz
arrondi au Hz pres
en RPM
quid de la relation Freq RPM .. 1 puls par tour ou n pulses par tour
simple mise à l'echelle
avec RPM en unisgned int (16 bits suffisent)
affichage:
toujours normaliser les tailles (meme si le compilo peut s'en debrouiller seul, c'est une bonne habitude)
PORTD =(unsigned char)' periode & 0x00FF ) ; // On envoie les 8 bits de points faibles sur le port D
PORTC = (unsigned char) periode >> 8; // On fait un décalage des 8 bits de poids fort pour les faire apparaitre sur le PORTC
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
j ai eue le temps de réfléchir a un autre programme a base du timer0 cette fois ci et tout en comptabilisant les dépassements en plus et affichant la fréquence sur le port c et d ( fréquence en nombre binaire 16 bit ) et en faisant en sorte que le drapeau d interruption se lève au front montant du signala plique sur int/rbo
voici :
Qu en pensez vous ?
Je regarde votre réponse précédemment poste plus tard dans la soirée car je dois m en aller précipitamment !
PS : J ai besoin d afficher une fréquence dans un premier temps , la vitesse rotation moteur je fais le calcul plus tard dans mon programme principal ..
a plus tard et merci encore
la j affiche le résultat sur les port c et d mais c est juste pour la simulation , car après j utiliserais directement la valeur numérique en return d un sous programme dans lequel il y aura le programme ci dessus pour appeler le calcul de frequance quand j aurais besoin
je met en fichier joint ma simulation sur proteus dans laquelle je lance mon fichier compilé .hex obtenu par mikroC
voici :
Code : Tout sélectionner
// CHAINE DE MESURE
/*PROGRAMME qui as pour but de calculer la periode d ' un signal applique sur l entree int/rb0
d ou l utilisation du timer1 pour calculer le temps entre deux fronts montant donc de la periode du signal envoyé en entrée */
/* avec cette configuration prescaler 1 et horloge ext (20 mhz/4) pour timer0 , temps entre deux
incrementations du timer0 = 0.2 microsceondes */
unsigned int periode;
unsigned int tempstotal;
float per_tim0 = 0.0000002; // temps entre deux incrementations du timer0 = 0.2 microsceondes
int a; // variable qui sert de condition test sortie de boucle des que l on as acqui notre periode
int dep; // variable qui stocke le nombre de depassements ayant eue lieu durant le comptage durant une periode
unsigned int frequence;
void main()
{
ANSEL = 0; // I/O en digital.
ANSELH = 0; // I/O en digital.
TRISB.B0 =1; // pin 0 du port B est declare en entree pour l acquisition du signal
TRISC =0b00000000; // portc decalre en sortie logique pour l affichage du resultat
TRISD =0b00000000; // portc decalre en sortie logique pour l affichage du resultat
OPTION_REG = 0xC0; //bit7-> RBPU=1 (off), bit6 -> INTEDG=1 (front montant)
//bit5-> T0CS=0 (fosc/4), bit4-> TOSE=0
//bit3-> PSA=0 (prescaler timer0), bit<3:0> 000 -> 1:1
// => OPTION_REG=0b11000000=0xC0
INTCON = 0x90; //bit7-> GIE=1, bit6-> PEIE=0, bit5-> T0IE=0
//bit4-> INTE=1, bit3-> RBIE=0, bit2->T0IF=0
//bit1-> INTF=0, bit0-> RBIF=0
// => INTCON=0b10010000=0x90
for(;;)
{
periode = tempstotal = frequence = a = dep = 0; // initialisation des variables de stockage avant prochain calcul
TMR0 = 0; // initialisation du timer0
T0IF_bit = 0; // initialisation du drapeau d interruption du timer0
INTE_bit = 0; // active le drapeau d interruption t0if sur l entree externe rb0/int
do
{
if(INTF_bit=0)
{
a=0; // le comptage de la periode commance seulement des que l' on detecte le premier front montant si non on reboucle tant que
}
if(INTF_bit=1) // le comptage de la periode peut commencer car on as detecte le premier front montant
{
INTF_bit = 0;
INTE_bit = 1; // mise en marche de l incrementation du timer0
do
{
if(T0IF_bit = 1) // boucle quidurant le comptage de la periode , comptabilise les debordement du timer0
{
dep=dep+1;
T0IF_bit= 0;
}
}while(INTF_bit = 0);
INTF_bit = 0;
INTE_bit = 0; // arret de l incrementation du timer0
tempstotal = dep*1024+TMR0; // calcul nombres d incrementations en tout durant la periode , debordements multiples compris
periode = tempstotal*per_tim0; // calcul periode du signal
frequence=1/periode;
a=1;
}
} while(a=0);
PORTD = frequence; // On envoie les 8 bits de points faibles sur le port D
PORTC = frequence >> 8; // On fait un décalage des 8 bits de poids faibles pour faire apparaitre les 2 bits de poids fort restant sur le PORTC
}
}
Qu en pensez vous ?
Je regarde votre réponse précédemment poste plus tard dans la soirée car je dois m en aller précipitamment !
PS : J ai besoin d afficher une fréquence dans un premier temps , la vitesse rotation moteur je fais le calcul plus tard dans mon programme principal ..
a plus tard et merci encore
la j affiche le résultat sur les port c et d mais c est juste pour la simulation , car après j utiliserais directement la valeur numérique en return d un sous programme dans lequel il y aura le programme ci dessus pour appeler le calcul de frequance quand j aurais besoin
je met en fichier joint ma simulation sur proteus dans laquelle je lance mon fichier compilé .hex obtenu par mikroC
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Bonjour a tous
je reviens cette fois ci avec un programme qui fonctionne , mais il y as quelques dysfonctionnements dans certaines conditions particulieres
le programme me calcule la duree d une periode d un signal applique sur l entree rb0/ int et m affiche la valeur de la frequence apres calcul sur un registre 16 bit ( la valeur que prend ce registre est representé par l activation ou non des sorties logiques configures sur le port c et d du pic 16f887.
voici mon code
les problèmes sont les suivants :
par exemple j applique un signal d entrée qui est normalise en amplitude ( 0-5v) de fréquence 250 hz , soit une période de 0.004 s , le programme me retourne en sortie le nombre binaire suivant : 0000000011110101 , ce qui correspond au nombre décimal 245 ;
soit la période fourni 250 hz et le montage la détectant comme 245 hs , d ou une incertitude sur la mesure qui me parait aberrante non ?
second problème , le programme refuse de me mesurer les période de signaux a très basse fréquence ( genre inférieur a 10 hz ) il me retourne une valeur complètement farfelu en sortie qui ne correspond pas a un résultat que je devrais avoir logiquement )
et cela malgré que je gère les dépassement multiples du tmr0
l incertitude est de 5 hz a 250 hz et de 1 hz a 10 hz .
qu' en pensez vous ? je ne pense pas que le montage ni le programme soit mauvais en soi , mais peut être que certains paramètres ne sont pas adaptes , ou ce timer ne convient pas a ce genre d' utilisation
je rappelle que je travaille sur pic 16f887 .
je reviens cette fois ci avec un programme qui fonctionne , mais il y as quelques dysfonctionnements dans certaines conditions particulieres
le programme me calcule la duree d une periode d un signal applique sur l entree rb0/ int et m affiche la valeur de la frequence apres calcul sur un registre 16 bit ( la valeur que prend ce registre est representé par l activation ou non des sorties logiques configures sur le port c et d du pic 16f887.
voici mon code
Code : Tout sélectionner
// CHAINE DE MESURE
/*PROGRAMME qui as pour but de calculer la periode d ' un signal applique sur l entree int/rb0
d ou l utilisation du timer0 pour calculer le temps entre deux fronts montant donc de la periode du signal envoyé en entrée */
/* avec cette configuration prescaler a 1 pour wdt( wdt pas utilisee ) donc 1:2 pour timer0 et horloge ext (20 mhz/4) pour timer0 , on aura temps entre deux
incrementations du timer0 = 0.4 microsecondes */
//
float per_tim0 = 0.0000004; // temps entre deux incrementations du timer0 = 0.8 microsceondes ( fosc/4 plus prescaler 1:8 )
int a; // variable qui sert de condition test sortie de boucle des que l on as acqui notre periode
unsigned long dep; // variable qui stocke le nombre de depassements ayant eue lieu durant le comptage durant une periode
unsigned int timer0; // variable qui stocke la valeur du registre tmr0 en sortie de la boucle de mesure de la periode
unsigned long tempstotal; // variable qui represente le nombre total de fois ou le registre tmr0 s est incrementé entre deux fronts montant sur rb0
float periode; // variable qui represente la periode du signal apres multiplication du nombvre d incrementations par le temps entre deux incrementatons d horloge
unsigned int frequence; // frequence est l inverse de la periode
void main() // boucle principal pour mesure periode signal sur rb0
{
ANSEL = 0; // I/O en digital.
ANSELH = 0; // I/O en digital.
TRISB.B0 =1; // pin rb0/int est declare en entree pour l acquisition du signal
TRISC =0b00000000; // portc decalre en sortie logique pour l affichage du resultat
TRISD =0b00000000; // portc decalre en sortie logique pour l affichage du resultat
OPTION_REG = 0xC0; //bit7-> RBPU=1 (off), bit6 -> INTEDG=1 (front montant)
//bit5-> T0CS=0 (fosc/4), bit4-> TOSE=0
//bit3-> PSA=0 (prescaler timer0), bit<3:0> 000 -> timer0 rate 1:2
// => OPTION_REG=0b11000000=0xC0
INTE_bit = 1; // on va utiliser le drapeau qui signale l interruption a chaque front montant du signal appliqué sur int/rb0
T0IE_bit = 1; // on va utiliser le drapeau qui signale l interruption a chaque debordement du timer0 ( on les comptabilise dans le programme)
PORTC = 0x00; // portc et portd parametres en sortie pour afficher nombre en binaire de la frequence trouvé en fin de programme
PORTD = 0x00; //
INTE_bit = 0; // initialisation des drapeaux
T0IE_bit = 0; //
T0IF_bit = 0; // initialisation du drapeau du depassement du regsitre TMR0
periode = tempstotal = frequence = a = dep = 0; // initialisation des variables de stockage avant le calcul
Delay_ms(5000);
do // on reste dans cette boucle tant que l on as pas acquis le temps d une periode
{
if(INTF_bit==0)
{
a=0; // le comptage de la periode commance seulement des que l' on detecte le premier front montant si non on reboucle tant que
}
if(INTF_bit==1) // le comptage de la periode peut commencer car on as detecte le premier front montant
{
TMR0 = 0;
INTF_bit = 0;
do
{
if(T0IF_bit == 1) // boucle quidurant le comptage de la periode , comptabilise les debordement du timer0
{
dep=dep+1;
T0IF_bit= 0;
}
}while(INTF_bit == 0); // on sort des que l on capte le second front montant sur rb0 ; correspond a fin de mesure de periode
timer0 = TMR0;
INTF_bit = 0;
tempstotal = dep * 256 + timer0; // calcul nombres d incrementations en tout durant la periode , debordements multiples compris
periode = tempstotal*per_tim0; // calcul periode du signal en secondes
frequence = 1 / periode; // calcul frequance signal en hz
a = 1; // condition de sortie de la boucle de mesure
}
} while(a==0); // on sort de la boucle de mesure car on est parvenu a acquerir l info de frequence du signal sur rb0
PORTD = frequence; // On envoie les 8 bits de points faibles sur le port D
PORTC = frequence >> 8; // On fait un décalage des 8 bits de poids faibles pour faire apparaitre les 2 bits de poids fort restant sur le PORTC
}
les problèmes sont les suivants :
par exemple j applique un signal d entrée qui est normalise en amplitude ( 0-5v) de fréquence 250 hz , soit une période de 0.004 s , le programme me retourne en sortie le nombre binaire suivant : 0000000011110101 , ce qui correspond au nombre décimal 245 ;
soit la période fourni 250 hz et le montage la détectant comme 245 hs , d ou une incertitude sur la mesure qui me parait aberrante non ?
second problème , le programme refuse de me mesurer les période de signaux a très basse fréquence ( genre inférieur a 10 hz ) il me retourne une valeur complètement farfelu en sortie qui ne correspond pas a un résultat que je devrais avoir logiquement )
et cela malgré que je gère les dépassement multiples du tmr0
l incertitude est de 5 hz a 250 hz et de 1 hz a 10 hz .
qu' en pensez vous ? je ne pense pas que le montage ni le programme soit mauvais en soi , mais peut être que certains paramètres ne sont pas adaptes , ou ce timer ne convient pas a ce genre d' utilisation
je rappelle que je travaille sur pic 16f887 .
Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
voir aussi mes remarques sur futura
Ta mesure est fortement dégradée en precision du fait de la duree de cet ensemble d'instruction
qui grapille du temps sur l'etat bas (avant de detecter le front haut).
Revois le melange de type de variables !
meme si le compilateur MikroC arrive à s'en debrouiller, c'est une tres mauvaise habitude de melanger des variables de taille
differentes dans les calculs ...
Tu armes les bits d'interupt Timer0 et RB0 SANS UTILISER LES INTERRUPTIONS ?
Le timer0 à une latence de 2 cycles d'instruction..
La resolution timer0 est faible (meme si on gere les debordements (qui plus est en mode pooling ).
dans cette facon de faire ,il faudrait utiliser les interruptions RB0, pour bien calibrer la periode entre 2 fronts montants
et gerer la valeur du timmer1 16 bits (+ eventuels debordements) dans l'interrupt RB0 ..
la partie calucl resultat se faisant ensuite dans le main program.
Utilise donc le mode Interruption Capture (CCP1) qui fait de lui meme la gestion lecture timer2 entre 2 fronts...
c'est étudié pour !
voir exemple via le lien du post #2
Code : Tout sélectionner
timer0 = TMR0;
INTF_bit = 0;
tempstotal = dep * 256 + timer0; // calcul nombres d incrementations en tout durant la periode , debordements multiples compris
periode = tempstotal*per_tim0; // calcul periode du signal en secondes
frequence = 1 / periode; // calcul frequance signal en hz
a = 1; // condition de sortie de la boucle de mesure
Ta mesure est fortement dégradée en precision du fait de la duree de cet ensemble d'instruction
qui grapille du temps sur l'etat bas (avant de detecter le front haut).
Revois le melange de type de variables !
meme si le compilateur MikroC arrive à s'en debrouiller, c'est une tres mauvaise habitude de melanger des variables de taille
differentes dans les calculs ...
Tu armes les bits d'interupt Timer0 et RB0 SANS UTILISER LES INTERRUPTIONS ?
Le timer0 à une latence de 2 cycles d'instruction..
La resolution timer0 est faible (meme si on gere les debordements (qui plus est en mode pooling ).
dans cette facon de faire ,il faudrait utiliser les interruptions RB0, pour bien calibrer la periode entre 2 fronts montants
et gerer la valeur du timmer1 16 bits (+ eventuels debordements) dans l'interrupt RB0 ..
la partie calucl resultat se faisant ensuite dans le main program.
Utilise donc le mode Interruption Capture (CCP1) qui fait de lui meme la gestion lecture timer2 entre 2 fronts...
c'est étudié pour !
voir exemple via le lien du post #2
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 59 invités