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 ---
Forum général sur le langage C !

Modérateur : Jérémy

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#21 Message par Jérémy » dim. 25 oct. 2015 21:31

adrienc45 a écrit :Source du message la première méthode citée me permettra d avoir un rafraîchissement sur la valeur de période mesure au plus faible de 1 seconde ( largeur de la " fenêtre de mesure ") , cela ne me convient pas car trop long pour l utilité que je vais en avoir , mais rien ne m empêche de mettre en œuvre l exercice effectivement .


Non tu peux prendre une base de temps plus faible . Mais la précision sera moins grande, car échantillonnage plus court . Tu pourras mesurer le nombre de front sur 100ms si tu voulais .

A titre d inforamtion si je pouvais avoir une reponse a cela quand meme ;)

Ton code est farfelu est difficile pour mon niveau de voir trop ou tu veut en venir . Mais si les valeurs sont proches et que les corrige avec un coefficient ( qui n'est vraiment pas la bonne méthode), c'est que les valeurs traités sont erronés ; certainement du a un traitement trop long de l'information qui fausse la base de temps pendant le calcul. je ne vois que ca !

Par exemple effacer le registre TMR0 prends deux cycles d'instructions il me semble si on veut être précis il faut les prendre en compte .

je sais sa parait surement idiot pour vous mais moi je suis heureux

Pas du tout, ça me fais le même effet quand quelques fonctionne ! :D

Il est préférable pour toi de poster ton schéma proteus et mettre ton programme dans une balise <code > . Les personnes n'auront pas toutes envie de se fader le téléchargement de la PJ , plus la décompression, plus l'ouverture avec le logiciel etc ...... Si tu mets des images direct , tu attireras plus de monde.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
adrienc45
Débutant
Débutant
Messages : 27
Enregistré en : octobre 2015

#22 Message par adrienc45 » dim. 25 oct. 2015 23:34

Tu n as pas tort effectivement .

voici mon schema :

Image

accompagne du code mis en place :

Code : Tout sélectionner

//-------------------------------Fonction principale------------------------------
// clignotement  de la sortie , evenement qui se repete a une periode egale a celle du signal qui arrive sur rb0 ( cadence )
void main()
{
      GIE_bit=1;
       PEIE_bit=1;
       INTE_bit=1;
       INTF_bit=0;
       TRISD.B0=0;
       TRISB.B0=1; // rbo en entree su microcontrolleur
       
        ANSEL 
= 0;
        ANSELH = 0;

       
       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

       PORTD.B0 =0;

       for(;;)
       {
       nop();
       }

}

#pragma origin 0x4
//---------------------------------ROUTINE D INTERRUPTION--------------------------------
void interrupt(void)   // a chaque interruption sur rbo/int la led changera d etat ( allume ou eteinte)
{

                  if(INTF_bit=1)
                  {
                                PORTD.B0 = ~PORTD.B0;
                                INTF_bit=0;
                  }




Il me reste plus qu a appliquer le calcul de mesure de periode a l aide des interruptions .

si j ai bien sais cette fois ci , une fois que cela sera fait , je pourrais me servir n importe quand dans mon programme principal (main ) de ma valeur de frequence calculé pendant la routine d' interruption :mrgreen:

Je potasse la dessus ce soir, il faut que j' y arrive +1 , je vous tient au courant demain

corrigez moi si je me trompes , j avance de mes erreurs :roll:

Bonne soiree !
Modifié en dernier par adrienc45 le lun. 26 oct. 2015 08:01, modifié 1 fois.

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#23 Message par Jérémy » lun. 26 oct. 2015 07:22

Oui c'est pas mal .

if(INTF_bit=1) à remplacer par if(INTF_bit == 1) ;Attention à cette erreur très fréquente, que je fais moi aussi encore :lol: .

Par contre tu ecrit dans ton commentaire que la LED s’allumera toute les 50ms ??? Ca c'est pas pas bon . Ta LED s'allumera tout les deux front montants sur RB0.

Un front montant va l'allumer ,un deuxième va l’éteindre, un troisième la rallumer un quatrième l’éteindre etc ....

Ta led clignotera à la fréquence des INT.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
adrienc45
Débutant
Débutant
Messages : 27
Enregistré en : octobre 2015

#24 Message par adrienc45 » lun. 26 oct. 2015 08:04

Oui c'est pas mal .

if(INTF_bit=1) à remplacer par if(INTF_bit == 1) ;Attention à cette erreur très fréquente, que je fais moi aussi encore :lol: .


c est vrai , j ai oublie que dans les conditions ca s ecrivait pas pareil , je corrige
il faut que je m en rapelle surtout si sa peut etre une source d erreur pour des programmes plus complexes a venir

Par contre tu ecrit dans ton commentaire que la LED s’allumera toute les 50ms ??? Ca c'est pas pas bon . Ta LED s'allumera tout les deux front montants sur RB0.

Un front montant va l'allumer ,un deuxième va l’éteindre, un troisième la rallumer un quatrième l’éteindre etc ....

Ta led clignotera à la fréquence des INT.


c est une phrase que j ai laissé par megarde , desolé ,

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#25 Message par Jérémy » lun. 26 oct. 2015 08:40

Donc c'est bien partis .

Maintenant au lieu d'allumer une led . Incremente un compteur. Il va donc compter le nombre de front montant ? Tiens ca nous interresse ca !.

Et si maintenant on autorise cette INT, à compter pendant une seconde ? Nous obtiendrons le nombre de fronts montant pendant une seconde ? Ca aussi ca nous intéresse. Car on pourra déterminer une période ? et donc une fréquence.

Allez a toi de jouer . creer une tempo de 1 seconde , et autoriser le comptage que pendant cette seconde.
PS: ne pas oublier de remettre le compteur à zéro avant un nouveau comptage
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
adrienc45
Débutant
Débutant
Messages : 27
Enregistré en : octobre 2015

#26 Message par adrienc45 » lun. 26 oct. 2015 08:52

La deuxième consiste a compter réellement le nombre d'instruction entre deux fronts montants.
Pour ce faire , je te propose ceci .

L’arrivée d'un front montant , remets à zéro le TMR0. Je rappelle que le timer0 compte en permanence le nombre d'instructions.

L'arrivée d'un deuxième front montant . enregistre la valeur du TMR0. Le nombre d’instructions sera égale à
(Valeur TMR0 à l'arrivée) - (Valeur TMR0 au départ) = Nombre d'instructions

Comme on avait remis à 0 le TMR0. la valeur du TMR0 sera = aux nombres d'instruction.

Suivant la fréquence de ton programme, tu connais le temps d'une instruction que tu multiplie par le nombre d'insrcutionet tu obtiens le temps entre deux fronts montants et Donc ta période


Bonjour
comme promis , je me suis mis en tete de faire un code correct qui fasse en sorte de calculer la frequence du signal qui arrive sur l entree int de mon pic 16f887 dans la routine d interruption , valeur que je pourrais utiliser a tout moment dans mon programme principal car celle ci sera rafraichi " en temps reel " si on peut dire , j' applique donc la methode de paulfjujo que je cite ci dessus , tiré d un precedent message de cette conversation

Code : Tout sélectionner

//initialisation et declaration des variables utilisés
int test=1;// variable pour savoir si premier ou second front montant pour mesure de la periode
int dep=0;
int temps=0;
float periode=0;
int frequence=0;
int fr=0;

//-------------------------------Fonction principale------------------------------
// affichage de la frequence mesuré , sur port c et portd
void main()
{
     
       GIE_bit
=1;
       PEIE_bit=1;
       INTE_bit=1;
       INTF_bit=0;
       T0IE_bit=1;
       T0IF_bit=0;
       
       TRISD
=0;
       TRISC=0;
       TRISB.B0=1; // rbo en entree su microcontrolleur

        ANSEL = 0;
        ANSELH = 0;


       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
                         // temps entre deux cycles avec ces parametres =0.4 microsecondes


       for(;;)
       {
              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
       }

}

//---------------------------------ROUTINE D INTERRUPTION--------------------------------
#pragma origin 0x4
void interrupt(void)   // a chaque interruption sur rbo/int calcul debut et fin de periode
{
                  GIE_bit=0;
                  

                  
                  if
(INTF_bit==1)
                  {
                                if(test==1)
                                {
                                          TMR0=0;
                                          test=2;
                                          INTF_bit=0;
                                }
                                if(test==2)
                                {
                                          temps=TMR0+256*dep;
                                          periode=temps*0.0000004;
                                          frequence=1/periode;
                                          temps=0;
                                          periode=0;
                                          dep=0;
                                          test=1;
                                          INTF_bit=0;
                                          

                                
}
                  }
                  if(T0IF_bit==1)
                  {             
                                dep
=dep+1;
                                T0IF_bit=0;
                  }
                  
                  
                  GIE_bit
=1;
}


voici le schema proteus dans lequel je lance la simulation de mon code :

Image

mais je crois que sa marche mal , sa me donne des résultats bizarre en sortie , je me demande si ça ne vient pas de la taille ou du type de mes variables utilisés , ou alors des incohérences dans la routine d' interruption

merci de votre attention , de votre patience , et de votre aide , mais en persévérant je vais y arriver j espère ;)

En attente de vos réponses , bonne journée a tous humour!!

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#27 Message par Jérémy » lun. 26 oct. 2015 09:03

Ce n'est pas bon !

Regarde ici :

Code : Tout sélectionner

 if(test==1)
                                {
                                          
TMR0=0;
                                          
test=2;
                                          
INTF_bit=0;
                                }
                                if(
test==2)
                                { 

sI TEST = 1 alors tu mets test à 2 . Et la condition c'est de vérifier si test est à 2 ?? Donc forcement il le sera toujours vu que tu le mets à 2 juste avant . les deux conditions seront exécutés.

Je pense que tu va trop vite. Tu veux directement faire un programme parfait . Il faut avancer doucement pour bien comprendre, et améliorer petit à petit . perso c'est ce que je fais .

fais une temporisation de 1 seconde et autorise l'INT sur les fronts montants pendant cette seconde . Montre un code et je le corrigerais si je peux !
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#28 Message par paulfjujo » lun. 26 oct. 2015 10:16

bonjour,

un petit detail, mais qui pourrait faire foirer d'entree un programme..

et aussi une bonne habitude à prendre :
ARMER les interruptions qu' APRES avoir tout initialiser.

Code : Tout sélectionner


void main
()
{
     
         
       TRISD
=0;
       TRISC=0;
       TRISB.B0=1; // rbo en entree su microcontrolleur

        ANSEL = 0;
        ANSELH = 0;


       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
                         // temps entre deux cycles avec ces parametres =0.4 microsecondes
                         
 
// armement des interruptions avec un contexte initial connu .                
        PEIE_bit=1;
       INTE_bit=1;
       INTF_bit=0;
       T0IE_bit=1;
       T0IF_bit=0;
       GIE_bit=1;   //  autorisation generale en dernier   




remarque:

Mesure de frequences basses < 250Hz
il est illusoire de vouloir les mesurer avec une fenetre de comptage inferieure à la seconde
Déja avec 1 seconde de mesure la resolution sera toujours, au mieux , de +-1 Hz
C'est pourquoi il faut passer par la methode Capture CCP.. PERIODEMETRE
quitte ensuite à calculer F= 1/T

par contre pour une large gamme de frequnce , up to 30MHz ,c'est beaucoup mieux adapté FREQUENCEMETRE


18F26K22_principe_periodmeter.jpg
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
adrienc45
Débutant
Débutant
Messages : 27
Enregistré en : octobre 2015

#29 Message par adrienc45 » lun. 26 oct. 2015 10:58

oui mais la methode que tu m as dit d utiliser , consistant a mesurer le nombre d incrementations de TMR0 et ses depassements , la valeur de la periode min est limite par le pas d incrementation du TMR0 et la valeur max de periode limité par la taille des variables que j utilise non ?

je suis pourtant a la lettre ce que vous m avez dit plus haut :D

ou est le problème donc ?

Je rapelle qu ' une precision sur la mesure de frequence au hertz pres m est largement satisfaisant .

Merci

Calcul période signal créneau (amplitude 0-5v) avec pic 16f887
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#30 Message par paulfjujo » lun. 26 oct. 2015 14:11

adrienc45 a écrit :.... methode consistant a mesurer le nombre d incrementations de TMR0 et ses depassements ,
la valeur de la periode min est limite par le pas d incrementation du TMR0 et la valeur max de periode
limité par la taille des variables que j utilise non ?


OUI !


Je rapelle qu ' une precision sur la mesure de frequence au hertz pres m est largement satisfaisant .


OK , mais tu veux mesurer en dessous de 10Hz ...


nota: on ne touche pas au GIE_bit dans les interruptions..
c'est automatique
une amelioration (combinée à une bonne habitude ) constituerait à tester aussi le bit
Enable interrupt vu que tu en as deja 2 .
et dans un programme ( plus important) les interrupts ne sont pas forcement validees en meme temps.

toujours à propose de la taille des variables et le melange dans les calculs

Code : Tout sélectionner

//initialisation et declaration des variables utilisés
int test=1;// variable pour savoir si premier ou second front montant pour mesure de la periode
int dep=0;
//int temps=0;
long temps=0;
float periode=0;
float f1;
unsigend int  frequence;
int fr=0;

//-------------------------------Fonction principale------------------------------
// affichage de la frequence mesuré , sur port c et portd
void main()
{
     
    
       TRISD
=0;
       TRISC=0;
       TRISB.B0=1; // rbo en entree su microcontrolleur

        ANSEL = 0;
        ANSELH = 0;


       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
                         // temps entre deux cycles avec ces parametres =0.4 microsecondes

 
       PEIE_bit
=1;
       INTE_bit=1;
       INTF_bit=0;
       T0IE_bit=1;
       T0IF_bit=0;
        GIE_bit=1;
       
       for
(;;)
       {
              PORTD = frequence & 0x00FF;         // 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 8 bits de poids fort restant sur le PORTC
       }

}

//---------------------------------ROUTINE D INTERRUPTION--------------------------------
#pragma origin 0x4  // <- ??
void interrupt(void)   // a chaque interruption sur rbo/int calcul debut et fin de periode
{
                   if((INTF_bit==1) && (INTE_bit==1))
                  {
                                if(test==1)
                                {
                                          TMR0=0;
                                          test=2;
                                          INTF_bit=0;
                                }
                                if(test==2)
                                {
                                         
// si temps est un int .. limite à +32767  -32768  ..risque de  debordement si dep>126
//avec  un unsigned int .. 0 à 65535 .. déja mieux
// ou avec un entier long .. tranquille pour ensuite descendre en frequence  !
                                              temps=(long) TMR0+ (long)dep * 256;
                                          periode=(float) temps  *4.0 ;
                                          f1=10000000.0/periode;  // pour eventuel affichage  decimal ex: 49,53Hz
                                          frequence=(unsigned int)f1; // pour affichage sur leds  en Hz  ex: 49
                                           test=1;
                                           dep=0;
                                          INTF_bit=0;
                                          

                                
}
                  }
                  if(( T0IF_bit==1) && (T0IE_bit==1))
                  {             
                                dep
=dep+1;
                                T0IF_bit=0;
                  }

}
 
Aide toi, le ciel ou FantasPic t'aidera


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 47 invités