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

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » ven. 13 janv. 2023 10:59 lien vers la Data-Sheet : Cliquez ici

Bonjour à tous,

je vous soumet quelque chose que je n'explique pas encore !

Je souhaite synchroniser un signal avec un timer pour pouvoir à termes modifier le rapport cyclique.

La synchronisation s'effectue sur le secteur soit un signal 230V/50Hz .
Après une mise en forme HARD du signal secteur, j'obtiens donc des impulsions toutes les 10ms (100hz).
Ces impulsions sont tirées au 3V3 pour une pull-up de 10k.
Elles viennent attaquées la broche RA3 de mon PIC .( DS en haut du post)

Cette broche RA3 ne peut être qu'une entrée. Elle est également la PIN MCLR du PIC, j'ai donc désactivé cette fonction bien entendu, sinon le PIC redémarrerait sans cesse ! :sifflotte:

J'ai donc configurée celle-ci pour recevoir une Interrupt-On-Change(IOC) sur un front montant.

Mon idée est la suivante:

A chaque front montant détecté par interruption, j'active une sortie (RA2) pour un temps donné .
Pour mes tests ce temps n'est pas variable.
Je l'ai fixé à 30 boucles de 100µS soit 3ms

Au bout de ces 3ms j’éteins ma sortie.

Voici ce que j'obtiens en sortie à l'oscilloscope
largeuer impulsion.png


j'ai, aléatoirement, des pulses qui dure plus longtemps. que les 3ms attendu. Les pulses sont soient de 3.2ms ( grossomodo) soit de 4.5ms( grossomodo).
Comment expliquer les pulses de 4.5ms ?


Je vous mets partiellement le code pour vous simplifier la chose. y'a pas grand chose de plus si ce n'est la partie Radio UART.

Code : Tout sélectionner

//##############################     VARIABLES     ################################################
unsigned int i=0, Temps_ON;
bit Etat_Lampe;
bit direction_variation;
bit long_press;

//--------  Dans les intteruptions
volatile bit F_appui_bref;
volatile bit F_appui_long;
volatile char F_Attente_300ms;
unsigned int Compteur_100us = 0, Compteur_100ms = 0;
unsigned char Valeur;

//--------  UART
unsigned char  tmp, Time_out, RSSI ;

//#################################################################################################
//-----------------------      INTERRUPTION        -----------------------------
void interrupt(){
   //------------------          IOC         ------------------------
   if (IOCIF_bit)
   {
      IOCAF = 0;              // RAZ des interruptions

      TMR0           = 56;    // je RAZ le timer a chaque activation
      Compteur_100us = 0;     //car on ne sait pas exactemetn quand il s'est arreté
      TMR0IF_bit     = 0 ;
      
      Pulse 
= 1;              // J'active la sortie
      TMR0IE_bit = 1;         // J'active la tempo pour le temps_ON
   }

  //------------------          TIMER 0 : 100µs         ------------------------
  if (TMR0IF_bit){
    TMR0IF_bit = 0;
    TMR0       = 56;

    Compteur_100us++;

    if (Compteur_100us >= Temps_ON-1)
    {
        Compteur_100us = 0;
        Pulse = 0;
        TMR0IE_bit = 0;
    }
  }

}
/*#################################################################################################
################################           MAIN             #######################################
#################################################################################################*/
void main(){

 ANSELA = 0b00000000;  // Lecture analogique tout en OFF
 TRISA.B1 = 1; // RA1 en entrée(BP)
 TRISA.B0 = 0; // LED_orange en sortie
 TRISA.B2 = 0; // Pulse en sortie
 
 OPTION_REG
.B7 = 0;      // Active les pull up individuelles
 WPUA = 0b00000010;      // Active les pull up sur RA1 pour BP

 RXDTSEL_bit = 1;        // RX_UArt sur RA5
 TXCKSEL_bit = 1;        // TX_Uart sur RA4
 
 
// ----- OSCILLATEUR
 OSCCON = 0b01110010;    // réglage de l'Oscillateur à 8Mhz (P.53)

 //------------  Initialisation UART ----------
 UART1_Init(115200);
 delay_ms(10);
 TRISA.B0 = 0; // LED_orange en sortie
 
 
//------------  IOC  ----------
 IOCAP = 0b00001000; // front montant sur RA3
 IOCIE_bit = 0 ;     // Interrupt-on-Change Enable bit
 
 
//------------ TIMER 1 : 100uS ---------------
 T1CON             = 0x21;
 TMR1IF_bit  = 0;
 TMR1H             = 0x3C;
 TMR1L             = 0xB0;
 TMR1IE_bit         = 0;

 //------------ TIMER 0 : 10mS ---------------
 OPTION_REG  = 0x08;
 TMR0        = 56;
 TMR0IE_bit  = 0;

 //------------     Interruption    ----------
 PEIE_bit = 1;
 RCIE_bit = 1;
 RCIF_bit = 0;
 GIE_bit  = 1;

  
  Etat_Lampe 
= Off;
  Pulse = 0 ;
  Temps_ON = 30;
  F_appui_bref = 0;
  F_appui_long = 0;

  

/*#################################################################################################
################################      BOUCLE PRINCIPALE     #######################################
#################################################################################################*/
 while (1){

   if ( F_appui_bref == 1)
   {
      F_appui_bref = 0;
      
      Etat_Lampe 
= ~Etat_Lampe;
      
      if 
(Etat_Lampe == On)
      {
         IOCIE_bit = 1;
      }
      else 
      
{
         IOCIE_bit = 0;
      }

     }


    if ( BP_PIC == 0) asm reset;
 }
}



Merci à tous
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#2 Message par Jérémy » ven. 13 janv. 2023 11:43 lien vers la Data-Sheet : Cliquez ici

Bon....

La bonne nouvelle , j'ai trouvé par chance pourquoi il y a un décalage.
La mauvaise nouvelle c'est que je ne sais pas comment le résoudre.

Au lieu de faire des boucles de 100µs que je compte 30 fois , donc je multiplie l'imprécision par 30. Je voulais faire uen temporisation directement de 3ms avec le timer 0. sauf que je me suis trompe dans le prescaler et mon timer est de 100µs.

Voila ce que j'obtiens à l'oscillo.
Erreur largeur.jpg


On voit clairement que j'ai un déclenchement sur un front descendant de temps en temps!
cela me ramène bien à mes 1.2ms de trop sur certaines impulsions.

La question comment est ce possible que je détecte une IOC sur un front descendant alors que celle-ci est configurée sur un front montant ? des rebonds ?

Bon je me dis OK je vais traiter l'info sur un front descendant, et ben bingo le même phénomène.

Ai-je loupé ma config IOC , probléme de timing ? dois je redressser la courbe de detection ? dois je la filtrée ?
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#3 Message par Jérémy » ven. 13 janv. 2023 12:21 lien vers la Data-Sheet : Cliquez ici

Je continue mes investigations......

j'ai augmenter la résistance de tirage au 3V3 de 10K à 33K pour augmenter la pente de détection et raccourcir sa largeur afin d'eviter les rebonds.
Je suis passer à 1ms de largeur d'impulsions au lieu de 1.5ms.

cela n'as pas changer grand chose j'ai toujours des erreurs.

Chose plus perturbantes qui m'oriente du coup vers le HARD.
J'ai modifié le code ainsi.
Quand je détecte un front montant, j’éteins les interruptions sur IOC ( donc je suis censé ne pas en recevoir). J'active ma sortie et lance ma temporisation.

A la fin de ma tempo, je mets à zéro ma sortie, j'éteins mon timer et je réactive mes interruptions SUR IOC.

Code : Tout sélectionner


void interrupt
(){
   
//------------------          IOC         ------------------------
   
if (IOCIF_bit)
   {
      if (
IOCAF3_bit)
      {
        
IOCAF 0;              // RAZ des interruptions
        
IOCIE_bit 0;

        
TMR0           68;    // je RAZ le timer a chaque activation
        
TMR0IF_bit     ;

        
Pulse 1;              // J'active la sortie
        
TMR0IE_bit 1;         // J'active la tempo pour le temps_ON
      
}
   }

  
//------------------          TIMER 0         ------------------------
  
if (TMR0IF_bit){
    
TMR0IF_bit 0;
    
TMR0       68;

     
Pulse 0;
     
TMR0IE_bit 0;
     
IOCIE_bit 1;

  } 


Et be surprise, je reçois quand même des interruptions sur IOC alors que l'INT est éteinte !
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Timer et Interruption-On-Change
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#4 Message par satinas » ven. 13 janv. 2023 12:39 lien vers la Data-Sheet : Cliquez ici

Bonjour Jérémy,
Les F_appui_xxx n'ont pas à être volatile car elles n'apparaissent que dans le main.
Par contre Compteur_100us je la mettrais en volatile, comme toute variable globale figurant dans l'ISR.
Pour le dernier message, l'int IOC n'est pas éteinte car tu fais IOCIE_bit = 1 à la fin de la tempo.
Après pour les problèmes de déclenchement, teste ton programme avec un autre signal, tu as un générateur de fonction ?

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#5 Message par Jérémy » ven. 13 janv. 2023 12:54 lien vers la Data-Sheet : Cliquez ici

Merci satinas pour ta réponse.

Les F_appui_xxx sont dans l'interrptuion UART que je n'ai pas dans le code pour le simplifier. Cette partie réception UART fonctionne parfaitement.
Je n'ai pas mis Compteur_100us en volatile car cette variable n'est utilisé que dans l'ISR et n'est pas modifié ailleurs. Mais t uas raison ca ne mange pas de pain de la mettre aussi en volatile !
satinas a écrit :Source du message Pour le dernier message, l'int IOC n'est pas éteinte car tu fais IOCIE_bit = 1 à la fin de la tempo.

Oui je rallume à la fin de la tempo, mais je l'éteins quand je reçois une IOC .

en gros quand je détecte une IOC, je peux plus en détecter jusqu’à la fin de la tempo qui la rallume.

Oui mon oscilloscope peut générer un signal ! a quoi penses tu ?

Je précise que les déclencher son bien précis, c'est pourquoi j'ai un doute sur le parasitage. Si c'était des parasites, les erreurs se produiraient n'importe quand ? Hors la c'est vraiment a chaque détection de zéro en front montant a 1.17V et en descendant à 1.0V , c'est vraiment précis
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Timer et Interruption-On-Change
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#6 Message par satinas » ven. 13 janv. 2023 13:08 lien vers la Data-Sheet : Cliquez ici

Si il déclenche sur le front descendant de façon systématique, et si IOCAN est bien à 0, cela pose question.
Un générateur de fonctions peut créer des signaux de toutes formes, si ton oscillo en possède un c'est bien, cela permettrait de tester de façon plus complète. En fait c'est plutôt un générateur d'impulsions qu'il faut :)

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#7 Message par Jérémy » ven. 13 janv. 2023 13:20 lien vers la Data-Sheet : Cliquez ici

Ok.

Pour le moment les IOC se déclenche toujours sur un front montant , et c'est nickel. par contre de temps en temps il y a un déclenchement sur un front descendant, ce n'est pas systématique ....... C'est ce qui met le flou. Par contre je pense que c'est bien sur un front descendant car c'est très précis a chaque fois qu'il y en a un.

Oui mon oscillo peut faire des faire d'impulsions maximum de 2V d'amplitude j'espere que cela sera suffisant .
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#8 Message par Jérémy » ven. 13 janv. 2023 13:53 lien vers la Data-Sheet : Cliquez ici

Fin du test.

Alors on avance un peu mais c'est pas folichon.

Quand je substitue mon signal de détection "zéro-cross" par une impulsion parfaite de 2V . J'entends par impulsion parfaite des fronts bien droits comme sur l'image ci dessus
simulation impulsion.png


Aucun problème et aucune erreur. le signal est conforme

par contre quand je modifie l'impulsion générée par une autre plus ressemblante c'est à dire avec des pentes moins droites.
j'ai un nombre d'erreur conséquent !
simulation impulsion2.png


C'est quand même incroyable qu'il me déclenche une IOC alors que la courbe est en phase descendante !

En modifiant l'impulsion comme cela , c'est à dire une éloignant la phase montante de la phase descendante j'ai quasiment aucune erreur , mais quelques unes tout de même.
simulation impulsion3.png
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Timer et Interruption-On-Change
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#9 Message par satinas » ven. 13 janv. 2023 14:15 lien vers la Data-Sheet : Cliquez ici

Ces 2 instructions vont ensemble, ne pas les éloigner.
IOCAF = 0;
IOCIE_bit = 1;
Cela devrait marcher quand même.
Nombre max de déclenchements pour une impulsion d'entrée ?

Timer et Interruption-On-Change
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#10 Message par Jérémy » ven. 13 janv. 2023 14:32 lien vers la Data-Sheet : Cliquez ici

satinas a écrit :Source du message Nombre max de déclenchements pour une impulsion d'entrée ?

Je ne suis pas sûr d'avoir compris ta question.

Une impulsion d'entrée = un déclenchement pour une durée déterminée
C'est en faisant des erreurs, que l'on apprend le mieux !!!


Retourner vers « Langage C »

Qui est en ligne

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