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

watchdog et timer
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 » mer. 8 sept. 2021 11:51 lien vers la Data-Sheet : Cliquez ici

Bonjour à tous,

Voila plusieurs jours que je cherche, modifie et tourne en rond sur un problème de timing. :sifflotte: :sifflotte:

Quelques chose doit m'échapper car j'ai bout tourner dans tous les sens je ne trouve pas de solutions mais surtout je ne vois même pas d'où ca peut venir.

Le contexte :
Il s'agit de la carte qui va gérer mon arrosage et un projecteur. cette carte sera dans mon local jardin. j'ai fais le même principe que pour mes stores bannes, à savoir, que la carte rentre en veille 2secondes ( le temps du watchdog) et se réveille pendant 300 ms pour écouter si un signal est reçu . Comme j'ai simplifier au maximum le programme pour trouver le bug je m’arrêterais la pour les explications et ne pas vous embrouiller.
Pour le moment la carte ne fait que passer en veille mais déjà la ça coince.

Afin de vérifier qu'il n'y ai pas de RESET du pic par faute d'alimentation ou autre, je fais clignoter rapidement une led verte au démarrage. aucun RESET du PIC à déclarer.
Je précise que la fréquence est de 500 Khz, j'ai pas besoin de vitesse et surtout je consomme beaucoup moins. je n'ai pas rencontrer de problème particulier avec l'UART à cette vitesse. de toute façon ici l'UART ne rentre pas en compte.
Mes timers sont testés et fonctionnent parfaitement !

Le principe est le suivant dans la boucle infinie :
- je surveille le drapeau F_Sleep qui doit m'indiquer que je dois rentrer en veille. Ce drapeau est levé par le timer0 toutes les 300ms.
- Une fois le drapeau levé je rentre dans la routine d’extinction
- j''éteins la led rouge qui est mon signal à observer à l'oscillo
- j'éteins tous les interruptions
- J'active le watchdog configurer sur 2s en début
- Je rentre en veille. le watchdog me sort de la veille au bout de 2s .

En sortie de veille
- j’éteins le watchdog
- je réveil mon module radio avec une impulsion sur sa broche wake-up.
- Je réinitialise le timer 0, je le lance
- j'allume la led rouge
- et je réactive les interruptions. Comme le timer 0 est activé je vais donc rester allumé pendant la durée du timer 0 soit 300ms

Donc pour moi la led rouge devrait s'allumer pendant 300ms à peu prêt ( + quelques lignes)

Le problème :
Dans 90% des cas elle s'allume bien pendant 300ms à l'oscillo, mais parfois il y a des ratés !!!! :mur: :mur: :mur: :mur:
je n'ai pas réussis à trouver une cohérence avec ces ratés. des fois l'impulsions ne dure que 150ms et des fois 600ms, voir 600ms plus une rapide impulsion à zéro(40ms) et re 300ms .

Ma question est qu'est ce qui pourrait générer ces erreurs dans les timings !

:!!: Tous n'est pas utilisé dan le programme cetaines focntion sont absentes !

Code : Tout sélectionner

/*
08/09/21
DS : PIC16F1825 : http://ww1.microchip.com/downloads/en/devicedoc/41440a.pdf
DS : AMB8220 : https://www.we-online.de/katalog/manual/2603011021000_Triton%202603011x2100x%20Manual_rev1.pdf

 le module se reveille toutes les 2 secondes (watchdog) et reste allumé pendant 300ms ( TMR0 )
 Dès la premiere donnée  recue par voir radio il reste allumé tant qu'il recoit une ligne de vie
 A l'allumage de l'ecran , l'ecran envoie des données toutes les 100ms pendant 3 secondes ensuite il passe une LDV / seconde
 Quand il ne recoit plus de ligne de vis il attend 3 secondes et repasse en veille
 Si un relais est activé il reste activer maximum 48 secondes
*/

//#############################################################################
//----------------------------      INCLUDES        ---------------------------
#include "Ordre_define.h"

#define LED_R        LATA0_bit
#define LED_V        LATA1_bit
#define Projo        LATA2_bit
#define BP           PORTA.B3

#define AMB_WUP      LATA4_bit
#define AMB_RST      LATA5_bit

#define Sens_GaG     LATC0_bit
#define Pulse_GaG    LATC1_bit
#define Sens_arr     LATC2_bit
#define Pulse_arr    LATC3_bit

//##############################     VARIABLES     ################################################
unsigned int i=0,CPT_100ms=0, CPT_10ms=0, Compteur_relais;
unsigned char F_LdV=0, RSSI=0;

//--------  UART
unsigned char tmp=0, Valeur=;
char Parametre_OK=0, DATA=0, F_DATA_OK=0, F_Sleep_OK=0;
char F_Sleep;

//##############################     PROTOTYPES     ###############################################
void Sleep_mode_on();
void Sleep_mode_off();
void Conf_AMB8220();


//##############################################################################
//-----------------------      INTERRUPTION        -----------------------------
void interrupt(){

  if (TMR0IF_bit){      // Determine le temps d'allumage du circuit : 300ms
     TMR0IF_bit   = 0;
     TMR0         = 61;
     CPT_100ms++;
     F_Sleep = 0;
     if (CPT_100ms>=3){
         CPT_100ms=;
         F_Sleep = 1 ;
      }
   }

  if (TMR1IF_bit){     // Determine la  durée maximum d'allumage des relais
     TMR1IF_bit = 0;
     TMR1H      = 0x0B;
     TMR1L      = 0xDC;
     Compteur_relais++;
     if (Compteur_relais >= 48 ){
         Compteur_relais = 0 ;
         TMR1IE_bit = 0;  // j'éteins le TIMER
      }
   }

  if (TMR2IF_bit){
    TMR2IF_bit = 0;
    if (TMR1IE_bit == 0) CPT_10ms++;
    F_Sleep = 0;
    if (CPT_10ms >= 300){
       CPT_10ms = 0;
       TMR0IE_bit = 1;
       F_Sleep = 1 ;
     }
  }

//-----------------------          UART        -----------------------------
  if (RCIF_bit == 1) {

    tmp = UART1_Read();      // On récupere et stock la donnée

    switch (Valeur){
        case 0:     if (tmp == 0x02){    // Start signal
                       Valeur = 1;
                     }
                     else
                       Valeur 
= 0;
                    break;

                    // Numéro de la  commande recue
        case 1:     if (tmp == 0x49)       // Parametre OK
                       Valeur = 2;
                    else if (tmp == 0x81)  // Validation d'un envoi
                       Valeur = 10;
                    else if (tmp == 0x68)  // reponse d'une demande de sleep
                       Valeur = 20;
                    else
                       Valeur 
= 0;
                    break;

       case 2:     if (tmp == 0x01)         // Nombre bytes
                       Valeur = 3;
                     else{
                        Valeur = 0;
                      }
                    break;

        case 3:     if (tmp == 0x00)        //status
                       Valeur = 4;
                     else{Valeur = 0;}
                    break;

        case 4:     if (tmp == 0x4A){       // checksum 0x02 0x49 0x01 0x00 0x4A
                       Parametre_OK = 1;    // Je léve le FLAG
                     }
                    Valeur = 0;
                    break;

        case 10:    if (tmp == 0x03)        //lenght
                       Valeur = 11;
                     else Valeur = 0;
                    break;

        case 11:    if (tmp == 0x01)        //adress source,  01=ecran
                       Valeur = 12;
                     else{Valeur = 0;}
                    break;

        case 12:    DATA = tmp ;  //  j'enregistre les données recues
                    Valeur = 13;
                    break;

        case 13:    RSSI = tmp ;        //RSSI
                    Valeur = 14;
                    break;

        case 14:    if (tmp == 0x81^DATA^RSSI){
                        F_DATA_OK = 1;       //DATA recues et valides
                     }
                    Valeur = 0;
                    break;

        case 20:    if (tmp == 0x01)        //sleep
                       Valeur = 21;
                    else {Valeur = 0;}
                    break;

        case 21:    if (tmp == 0x01)        //sleep
                       Valeur = 22;
                    else {Valeur = 0;}
                    break;

        case 22:    if (tmp == 0x6A){        //sleep
                       F_Sleep_OK = 1;
                     }
                    Valeur = 0;
                    break;
     }
  }
}
/*#################################################################################################
################################           MAIN             #######################################
#################################################################################################*/
void main() {

 ANSELA = ANSELC = 0x00; // Tout en numérique

 TRISA = 0b11001000;     // en sortie: AMB_RST, AMB_WUP, LED_R, LED_V et Projecteur
 TRISC = 0b11100000;     // En entrée: RX UART

 //*******   OSCILLATEUR    ******
 OSCCON = 0b00111010 ;  //  PLL disable ; MF 500 Khz ; internal OSC

 AMB_RST = 1;
 AMB_WUP = 1;

 //--------------------------   INTERUPT. TIMER0 : 100ms   ---------------------------------
 OPTION_REG = 0x85;   // Prescaler 1:64;  pullup dés-actived  p.189
 TMR0       = 61;     // TMR0 Preload = 61
 TMR0IE_bit = 0 ;     // p.93
 TMR0IF_bit = 0;      // p.93

 //--------------------------   INTERUPT. TIMER1 : 1s   ---------------------------------
  T1CON      = 0x11;      //Prescaler 1:2; timer1=ON ; p.197
  TMR1H      = 0x0B;      // TMR1 Preload = 3036
  TMR1L      = 0xDC;
  TMR1IF_bit = 0;
  TMR1IE_bit = 0;

 //--------------------------   INTERUPT. TIMER2 : 10ms   ---------------------------------
  T2CON      = 0x24;           // Prescaler 1:1; Postscaler 1:5;
  PR2        = 249;            // TMR2 Preload = 249;
  TMR2IF_bit = 0;
  TMR2IE_bit = 0;

 //------------------------------   INTERUPT. UART   -------------------------------------
 PEIE_bit = 1;     // Active les INT peripherique p.93
 RCIE_bit = 1;     // Active les Interruptions sur Rx UART   p.94
 RCIF_bit = 0;     // RAZ flag  p.98

 //*******   UART     ******
 UART1_Init(9600);

 //*******   WATCHDOG     ******
 WDTCON = 0b00010110 ;  // timer period=2s ; SWDTEN=0   p.107

 //-------------------------------   INTERRUPTION   ----------------------------------------
 GIE_bit  = 1;          // Active toutes les INT  p.93

 CPT_100ms = CPT_10ms = 0;
 F_Sleep = 1;
  
 delay_ms
(100);
 for (i=0;i<=;i++){
    LED_V = 1;
    delay_ms(50);
    LED_V = 0;
    delay_ms(50);
  }
 TMR2IE_bit = 1;

 LED_R = 1;

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

    // Mise en veille par le TIMER 0
    if (F_Sleep == 1){   // C'est l'heure de dormir
        F_Sleep = 0;
        
        LED_R 
= 0;
        //Sleep_mode_on();    // je met le module radio en veille avant d'eteindre les INT
        GIE_bit  = 0;       // j'eteins les int

        SWDTEN_bit = 1;     // j'active le watchdog configurer sur 2s
        asm CLRWDT ;
        asm sleep ;         // j'endors le PIC pour 2 secondes et il se reveilera grace au watchdog pour uneb durer determiner par le timer 0
        asm nop ;
        SWDTEN_bit = 0;     // Je désactive le watchdog
        delay_ms(2);


        //Sleep_mode_off();   // Je réveil le module radio
        TMR0       = 61;    // TMR0 Preload = 61
        CPT_100ms  = Valeur = 0;
        TMR0IE_bit = 1 ;
        LED_R = 1;
        GIE_bit  = 1;
     }


   // reception d'une donnée
   if (F_DATA_OK == 1){
      F_DATA_OK =0;    // raz flag

      TMR0IE_bit = 0;  // J'arrete la mise en veille
      TMR0       = 61;
      CPT_100ms  = 0 ;
      CPT_10ms = 0;

      switch (DATA){

        case Reveil         : TMR2IE_bit = 1; LED_V=~LED_V;  break;   // je recois une ligne de vie, je raz le comtpeur

        default: asm nop;
       }
    }
 }
}

/*#################################################################################################
################################      PROGRAMME SECONDAIRE     ####################################
#################################################################################################*/
void Sleep_mode_on(){
// Cette fonction fait renter le module radio en LPM. j'attends la réponse 3 fois aprés je sors pour ne pas bloquer
   // rentrer en LPM ( Low Power Mode)
   // envoie en hexa (02 28 01 01 2A)
   // Response (02 68 01 01 6A)
   char CPT_LOC=0;

   do{
     UART1_Write(0x02);     // Start
     UART1_Write(0x28);     // Commande
     UART1_Write(0x01);     // Lenght
     UART1_Write(0x01);     // LPM
     UART1_Write(0x2A);     // CS
     delay_ms(50);
     CPT_LOC++;
     if (CPT_LOC >= 3) break;
   }while (F_Sleep_OK == 0);// Attente de la réponse
   F_Sleep_OK = 0;            // RAZ flag
}

//----- Cette fonction sort le module radio de la veille
void Sleep_mode_off(){
  AMB_WUP = 0;
  delay_ms(20);
  AMB_WUP = 1;
  delay_ms(10);



Ci joint une photo du genre de problème.
IMG_20210908_090016.jpg
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 !!!

watchdog et timer
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#2 Message par satinas » mer. 8 sept. 2021 14:46 lien vers la Data-Sheet : Cliquez ici

Bonjour Jérémy, quelle est la valeur de _WDT dans la config hardware ?

watchdog et timer
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 » mer. 8 sept. 2021 15:03 lien vers la Data-Sheet : Cliquez ici

Bonjour Satinas,

Je suis pas sur d'avoir compris ta question.

Dans la configuration projet :
CONFIG1 : $8007 : 0x3FAC
CONFIG2 : $8008 : 0x1613

Le watchdog est reglé sur controlled by SWDTEN ... voir la photo ci jointe.

Dans le programme la valeur est :

Code : Tout sélectionner

 //*******   WATCHDOG     ******
 WDTCON = 0b00010110 ;  // timer period=2s ; SWDTEN=0   p.107  


Sans titre.jpg


Pense ce tempsje continue mes investigations.
Quand je supprime les focntions Sleep_mode_on(); et Sleep_mode_off(); je n'ai aucun bug de timing.

Du coup j'ai l'impression que ce la viens du module radio et/ou de 'l'UART qui interfererai avec le watchdog.
En fait quand j'endors le module radio en lui envoyant la commande (0x02 0x28 0x01 0x01 0x2A) celui-ci me répond par "02 68 01 01 6A" en hexa . dnas mon code précedent je traitais cette réponse avant de continuer. c'est pour cela que j'éteignais les interruptions apres le paasage du module en veille.

Par contre je ne traitais pas le retour de veille.
Quand je fais sortir le module radio de veille en appliquant un état bas sa sa broche Wake-up, celui m'envoie un message quand il est réveillé. Il m’envoie "02 C0 01 00 C3". Maintenant je le traite avant de continuer mon programme.

Je n'ai plus de bug à 600ms , mais par contre j'ai toujours des bugs de durée raccourci à 200ms.
J'ai l’impression que les temps sont divisés par 2 ou multipliés par deux. C'est bizarre !

Voici mon nouveau code de test avec le traitement de la sortie de veille par l'UART.

Code : Tout sélectionner

/*
09/09/21
DS : PIC16F1825 : http://ww1.microchip.com/downloads/en/devicedoc/41440a.pdf
DS : AMB8220 : https://www.we-online.de/katalog/manual/2603011021000_Triton%202603011x2100x%20Manual_rev1.pdf

 le module se reveille toutes les 2 secondes (watchdog) et reste allumé pendant 300ms ( TMR0 )
 Dès la premiere donnée  recue par voir radio il reste allumé tant qu'il recoit une ligne de vie
 A l'allumage de l'ecran , l'ecran envoie des données toutes les 100ms pendant 3 secondes ensuite il passe une LDV / seconde
 Quand il ne recoit plus de ligne de vis il attend 3 secondes et repasse en veille
 Si un relais est activé il reste activer maximum 48 secondes
*/

//#############################################################################
//----------------------------      INCLUDES        ---------------------------
#include "Ordre_define.h"

#define LED_R        LATA0_bit
#define LED_V        LATA1_bit
#define Projo        LATA2_bit
#define BP           PORTA.B3

#define AMB_WUP      LATA4_bit
#define AMB_RST      LATA5_bit

#define Sens_GaG     LATC0_bit
#define Pulse_GaG    LATC1_bit
#define Sens_arr     LATC2_bit
#define Pulse_arr    LATC3_bit

//##############################     VARIABLES     ################################################
unsigned int i=0,CPT_100ms=0CPT_10ms=0Compteur_relais;
unsigned char F_LdV=0RSSI=0;

//--------  UART
unsigned char tmp=0Valeur=;
char Parametre_OK=0DATA=0F_DATA_OK=0F_Sleep_OK=0F_Reveil_OK=0;
char F_Sleep;

//##############################     PROTOTYPES     ###############################################
void Sleep_mode_on();
void Sleep_mode_off();
void Conf_AMB8220();


//##############################################################################
//-----------------------      INTERRUPTION        -----------------------------
void interrupt(){

  if (
TMR0IF_bit){      // Determine le temps d'allumage du circuit : 300ms
     
TMR0IF_bit   0;
     
TMR0         61;
     
CPT_100ms++;
     
F_Sleep 0;
     if (
CPT_100ms>=3){
         
CPT_100ms=;
         
F_Sleep ;
      }
   }

  if (
TMR1IF_bit){     // Determine la  durée maximum d'allumage des relais
     
TMR1IF_bit 0;
     
TMR1H      0x0B;
     
TMR1L      0xDC;
     
Compteur_relais++;
     if (
Compteur_relais >= 48 ){
         
Compteur_relais ;
         
TMR1IE_bit 0;  // j'éteins le TIMER
      
}
   }

  if (
TMR2IF_bit){
    
TMR2IF_bit 0;
    if (
TMR1IE_bit == 0CPT_10ms++;
    
F_Sleep 0;
    if (
CPT_10ms >= 300){
       
CPT_10ms 0;
       
TMR0IE_bit 1;
       
F_Sleep ;
     }
  }

//-----------------------          UART        -----------------------------
  
if (RCIF_bit == 1) {

    
tmp UART1_Read();      // On récupere et stock la donnée

    
switch (Valeur){
        case 
0:     if (tmp == 0x02){    // Start signal
                       
Valeur 1;
                     }
                     else
                       
Valeur 0;
                    break;

                    
// Numéro de la  commande recue
        
case 1:     if (tmp == 0x49)       // Parametre OK
                       
Valeur 2;
                    else if (
tmp == 0x81)  // Validation d'un envoi
                       
Valeur 10;
                    else if (
tmp == 0x68)  // reponse d'une demande de sleep
                       
Valeur 20;
                    else if (
tmp == 0xC0)  // reponse d'une sortie de sleep
                       
Valeur 30;
                    else
                       
Valeur 0;
                    break;

       case 
2:     if (tmp == 0x01)         // Nombre bytes
                       
Valeur 3;
                     else{
                        
Valeur 0;
                      }
                    break;

        case 
3:     if (tmp == 0x00)        //status
                       
Valeur 4;
                     else{
Valeur 0;}
                    break;

        case 
4:     if (tmp == 0x4A){       // checksum 0x02 0x49 0x01 0x00 0x4A
                       
Parametre_OK 1;    // Je léve le FLAG
                     
}
                    
Valeur 0;
                    break;

        case 
10:    if (tmp == 0x03)        //lenght
                       
Valeur 11;
                     else 
Valeur 0;
                    break;

        case 
11:    if (tmp == 0x01)        //adress source,  01=ecran
                       
Valeur 12;
                     else{
Valeur 0;}
                    break;

        case 
12:    DATA tmp ;  //  j'enregistre les données recues
                    
Valeur 13;
                    break;

        case 
13:    RSSI tmp ;        //RSSI
                    
Valeur 14;
                    break;

        case 
14:    if (tmp == 0x81^DATA^RSSI){
                        
F_DATA_OK 1;       //DATA recues et valides
                     
}
                    
Valeur 0;
                    break;

        case 
20:    if (tmp == 0x01)        //sleep
                       
Valeur 21;
                    else {
Valeur 0;}
                    break;

        case 
21:    if (tmp == 0x01)        //sleep
                       
Valeur 22;
                    else {
Valeur 0;}
                    break;

        case 
22:    if (tmp == 0x6A){        //sleep
                       
F_Sleep_OK 1;
                     }
                    
Valeur 0;
                    break;
                    
        
// réponse aprés un reveil par la broche wake-up
        
case 30:    if (tmp == 0x01){ Valeur 31; } else { Valeur 0; } break;
        case 
31:    if (tmp == 0x00){ Valeur 32; } else { Valeur 0; } break;
        case 
32:    if (tmp == 0xC3){ F_Reveil_OK 1; } Valeur 0; break;
     }
  }
}
/*#################################################################################################
################################           MAIN             #######################################
#################################################################################################*/
void main() {

 
ANSELA ANSELC 0x00// Tout en numérique

 
TRISA 0b11001000;     // en sortie: AMB_RST, AMB_WUP, LED_R, LED_V et Projecteur
 
TRISC 0b11100000;     // En entrée: RX UART

 //*******   OSCILLATEUR    ******
 
OSCCON 0b00111010 ;  //  PLL disable ; MF 500 Khz ; internal OSC

 
AMB_RST 1;
 
AMB_WUP 1;

 
//--------------------------   INTERUPT. TIMER0 : 100ms   ---------------------------------
 
OPTION_REG 0x85;   // Prescaler 1:64;  pullup dés-actived  p.189
 
TMR0       61;     // TMR0 Preload = 61
 
TMR0IE_bit ;     // p.93
 
TMR0IF_bit 0;      // p.93

 //--------------------------   INTERUPT. TIMER1 : 1s   ---------------------------------
  
T1CON      0x11;      //Prescaler 1:2; timer1=ON ; p.197
  
TMR1H      0x0B;      // TMR1 Preload = 3036
  
TMR1L      0xDC;
  
TMR1IF_bit 0;
  
TMR1IE_bit 0;

 
//--------------------------   INTERUPT. TIMER2 : 10ms   ---------------------------------
  
T2CON      0x24;           // Prescaler 1:1; Postscaler 1:5;
  
PR2        249;            // TMR2 Preload = 249;
  
TMR2IF_bit 0;
  
TMR2IE_bit 0;

 
//------------------------------   INTERUPT. UART   -------------------------------------
 
PEIE_bit 1;     // Active les INT peripherique p.93
 
RCIE_bit 1;     // Active les Interruptions sur Rx UART   p.94
 
RCIF_bit 0;     // RAZ flag  p.98

 //*******   UART     ******
 
UART1_Init(9600);

 
//*******   WATCHDOG     ******
 
WDTCON 0b00010110 ;  // timer period=2s ; SWDTEN=0   p.107

 //-------------------------------   INTERRUPTION   ----------------------------------------
 
GIE_bit  1;          // Active toutes les INT  p.93

 
CPT_100ms CPT_10ms 0;
 
F_Sleep 1;
  
 
delay_ms(100);
 for (
i=0;i<=;i++){
    
LED_V 1;
    
delay_ms(50);
    
LED_V 0;
    
delay_ms(50);
  }
 
TMR2IE_bit 1;

 
LED_R 1;

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

    
// Mise en veille par le TIMER 0
    
if (F_Sleep == 1){   // C'est l'heure de dormir
        
F_Sleep 0;
        
        
Sleep_mode_on();    // je met le module radio en veille avant d'eteindre les INT
        
        
LED_R 0;
        
GIE_bit  0;       // j'eteins les int

        
SWDTEN_bit 1;     // j'active le watchdog configurer sur 2s
        
asm CLRWDT ;
        
asm sleep ;         // j'endors le PIC pour 2 secondes et il se reveilera grace au watchdog pour uneb durer determiner par le timer 0
        
asm nop ;
        
SWDTEN_bit 0;     // Je désactive le watchdog

        
GIE_bit  1;
        
delay_ms(1);
        
Sleep_mode_off();   // Je réveil le module radio
        
        
TMR0      61;    // TMR0 Preload = 61
        
CPT_100ms 0;
        
TMR0IE_bit ;
        
LED_R 1;

     }

    
/*
   // reception d'une donnée
   if (F_DATA_OK == 1){
      F_DATA_OK =0;    // raz flag

      TMR0IE_bit = 0;  // J'arrete la mise en veille
      TMR0       = 61;
      CPT_100ms  = 0 ;
      CPT_10ms = 0;

      switch (DATA){

        case Reveil         : TMR2IE_bit = 1; LED_V=~LED_V;  break;   // je recois une ligne de vie, je raz le comtpeur

        default: asm nop;
       }
    }
    */
 
}
}

/*#################################################################################################
################################      PROGRAMME SECONDAIRE     ####################################
#################################################################################################*/
void Sleep_mode_on(){
// Cette fonction fait renter le module radio en LPM. j'attends la réponse 3 fois aprés je sors pour ne pas bloquer
   // rentrer en LPM ( Low Power Mode)
   // envoie en hexa (02 28 01 01 2A)
   // Response (02 68 01 01 6A)
   
char CPT_LOC=0;

   do{
     
UART1_Write(0x02);     // Start
     
UART1_Write(0x28);     // Commande
     
UART1_Write(0x01);     // Lenght
     
UART1_Write(0x01);     // LPM
     
UART1_Write(0x2A);     // CS
     
delay_ms(100);
     
CPT_LOC++;
     if (
CPT_LOC >= 3) break;
   }while (
F_Sleep_OK == 0);// Attente de la réponse
   
F_Sleep_OK 0;            // RAZ flag
}

//----- Cette fonction sort le module radio de la veille
void Sleep_mode_off(){
  
AMB_WUP 0;
  
delay_ms(20);
  
AMB_WUP 1;
  while ( 
F_Reveil_OK == 0);
  
F_Reveil_OK 0;
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 !!!

watchdog et timer
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#4 Message par Jérémy » mer. 8 sept. 2021 15:26 lien vers la Data-Sheet : Cliquez ici

Voici un exemple peut etre plus clair, car je suis conscient que ce ne doit pas être évident de m'aider.

Voici une portion de code ou j'ai déplacé la mesure du temps..

Code : Tout sélectionner

    if (F_Sleep == 1){   // C'est l'heure de dormir
        
F_Sleep 0;
        
        
Sleep_mode_on();    // je met le module radio en veille avant d'eteindre les INT
        
        
LED_R 0;
        
GIE_bit  0;       // j'eteins les int

        
SWDTEN_bit 1;     // j'active le watchdog configurer sur 2s
        
asm CLRWDT ;
        
asm sleep ;         // j'endors le PIC pour 2 secondes et il se reveilera grace au watchdog pour uneb durer determiner par le timer 0
        
asm nop ;
        
SWDTEN_bit 0;     // Je désactive le watchdog
        
LED_R 1;
        
GIE_bit  1;
        
delay_ms(1);
        
Sleep_mode_off();   // Je réveil le module radio
        
        
TMR0      61;    // TMR0 Preload = 61
        
CPT_100ms 0;
        
TMR0IE_bit ;


     } 

J'ai donc placé la mesure pile poil à la sortie du watchdog ( LED_R = 1) et je ferme la mesure quand je rentre dans la fonction de mise en veille ( meme un peu apres car j'execute la fonction Sleep_mode_on(); ).

C'est la ou s’arrête ma compréhension. En tout état de cause, c'est fonction est gérée par le timer 0 qui est réglé sur 300ms. je ne peux donc pas rentrée dans cette fonction avant, c'est IMPOSSIBLE !!!!
et pour tant voici un exemple :

IMG_20210908_152256.jpg



J'ai donc une impulsion de 270ms ????? alors que c'est impossible d'être inférieur à 300ms qui le temps du timer0

Je suis perdu !!!! :mur: :mur: :mur: :mur:
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 !!!

watchdog et timer
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#5 Message par satinas » mer. 8 sept. 2021 15:31 lien vers la Data-Sheet : Cliquez ici

L'entrée et la sortie du mode sleep déclenche le reset auto du watchdog.
Commence avec un programme ultra simple avec SWDTEN_bit restant à 1, pas de flag.
Le programme boucle, sleep, 2s de watchdog, sortie et tempo par delay() de 300ms.
Ensuite tu ajoutes le module radio, si possible sans timer.
Après tu ajoutes les timers, et pourquoi ces TMR0IE_bit = 0, c'est assez compliqué comme ça, le timer on peut l'arrêter.

watchdog et timer
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#6 Message par Jérémy » mer. 8 sept. 2021 16:02 lien vers la Data-Sheet : Cliquez ici

satinas a écrit :Source du message Commence avec un programme ultra simple avec SWDTEN_bit restant à 1, pas de flag.


Code : Tout sélectionner


 while 
(1){
        LED_R = 0;
        SWDTEN_bit = 1;     // j'active le watchdog configurer sur 2s
        asm sleep ;         // j'endors le PIC pour 2 secondes et il se reveilera grace au watchdog pour uneb durer determiner par le timer 0
        asm nop ;
        SWDTEN_bit = 0;     // Je désactive le watchdog
        LED_R = 1;
        delay_ms(300);

 


IMG_20210908_155952.jpg


Après tu ajoutes les timers, et pourquoi ces TMR0IE_bit = 0, c'est assez compliqué comme ça, le timer on peut l'arrêter.

C'est vrai que j'ai pris la mauvaise habitude d’arrêter mon traitement timer en arrêtant les intéruptions lié a ce timer, ce qui en soi, n'arrete pas le timer mais seulement ces interruptions .
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 !!!

watchdog et timer
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#7 Message par satinas » mer. 8 sept. 2021 16:08 lien vers la Data-Sheet : Cliquez ici

Voilà pourquoi il faut toujours commencer simple, le SWDTEN_bit = 0; n'est pas nécessaire là, car 300ms < 2s.

watchdog et timer
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 » mer. 8 sept. 2021 16:17 lien vers la Data-Sheet : Cliquez ici

Après 5 bonne minutes a regarder mon oscillo je n'ai plus eu de bug. comme sur al photo en #6 !!!

Peut etre du à ma sonde d'oscillo ou un parasite ou un extraterrestre lol, mais je n'ai pas de bug avec cette fonction simple.

Pour infos j'avais essayé mon programme sans utilisé le SWDTEN_bit . En laissant activer le WDT en permanence et en le resetant dans le programme par des " asm CLRWDT" , le résultat était le même.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

watchdog et timer
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#9 Message par satinas » mer. 8 sept. 2021 16:25 lien vers la Data-Sheet : Cliquez ici

Je sais pas d'où vient le problème, je dis juste qu'on peut le laisser à 1 si la période d'activité ne dépasse jamais 2s, et on n'a pas à resetter le watchdog, le mode sleep s'en charge.
When the device enters Sleep, the WDT is cleared. When the device e xits Sleep, the WDT is cleared again

Si tu écartes une erreur, elle te reviendra sous une autre forme.

Code : Tout sélectionner

  char CPT_LOC=0;
  do {
    ...
    delay_ms(50);
    CPT_LOC++;
    if (CPT_LOC >= 3) break;
  } while (F_Sleep_OK == 0);  // Attente de la réponse
  F_Sleep_OK = 0;             // RAZ flag

Ou alors du mets un compteur d'erreurs, que tu affiches, j'ai cru vois passer un lcd.
Modifié en dernier par satinas le mer. 8 sept. 2021 16:48, modifié 1 fois.

watchdog et timer
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 » mer. 8 sept. 2021 16:46 lien vers la Data-Sheet : Cliquez ici

bon on peut considérer que le watchdog fonctionne comme il faut

J'avance doucement donc. Je remplace le delay de 300ms par le timer0 ( après vérification, apparemment ce timer ne peut pas s'arrêter sur ce pic)

avec cette fonction aucun bug non plus :

Code : Tout sélectionner

     if (F_Sleep == 1){   // C'est l'heure de dormir
        F_Sleep = 0;
        TMR0IE_bit = 0 ;
        
        LED_R 
= 0;
        SWDTEN_bit = 1;     // j'active le watchdog configurer sur 2s
        asm sleep ;         // j'endors le PIC pour 2 secondes et il se reveilera grace au watchdog pour uneb durer determiner par le timer 0
        asm nop ;
        SWDTEN_bit = 0;     // Je désactive le watchdog
        LED_R = 1;

        TMR0       = 61;    // TMR0 Preload = 61
        CPT_100ms  = 0 ;
        TMR0IE_bit = 1 ;
      }
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 25 invités