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

Programme qui se bloque
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 » jeu. 8 avr. 2021 22:03 lien vers la Data-Sheet : Cliquez ici

Bonsoir à tous,

Je recherche un œil neuf sur mon programme de gestion de mes stores bannes !
En effet après quelques mois d'utilisation, je me rends compte que de temps en temps le programme se bloque et m'oblige à couper le couper le courant puis à le remettre pour que ça reparte.

Comme j'utilise la watchdog que je ne connais pas trop, je sais pas trop d'ou cela peut venir
Je me demande si ce n'est pas a cause de l'uart ? Peut etre que je devrais rajouter un timeout à l’intérieur de celui-ci ?

Je vous mets le code ici , si il manque quelques choses , demandez moi.
Merci a ceux qui pourront jeter un œil !

Code : Tout sélectionner

/*
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 200ms ( 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 15 secondes
*/

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

#define LED         LATC3_bit

#define Montee_D     LATC2_bit
#define Descend_D    LATC1_bit
#define Descend_G    LATC0_bit
#define Montee_G     LATA2_bit

#define AMB_RST     LATA5_bit
#define AMB_WUP     LATA4_bit

//##############################     VARIABLES     ################################################

unsigned int i=0,CPT_100ms=0, Compteur_relais=0, CPT_10ms=0;

//--------  UART
unsigned char  tmp=0, Valeur=;
char Parametre_OK=0, DATA=0, RSSI=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 : 200ms
     TMR0IF_bit   = 0;
     TMR0         = 61;
     CPT_100ms++;
     F_Sleep = 0;
     if (CPT_100ms>=2){
         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
         Montee_D = Montee_G = Descend_D = Descend_G = 0; // j'éteins les relais
      }
   }
  
  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() {

 LATA = LATC = 0x00;
 ANSELA = ANSELC = 0x00;
 WPUA = 0b00000011 ; // RA0 et RA1 pull-up
 
 TRISC3_bit 
= 0;     // LED
 TRISA4_bit = TRISA5_bit = 0;   // AMB_RST et AMB_WUP
 TRISA2_bit = TRISC0_bit = TRISC1_bit = TRISC2_bit = 0;   // Relais
 
 
//*******   OSCILLATEUR    ******
 OSCCON = 0b00111010 ;  //  PLL disable ; MF 500 Khz ; internal OSC
 
 AMB_RST 
= 1;
 AMB_WUP = 1;

 //--------------------------   INTERUPT. TIMER0 : 100ms   ---------------------------------
 OPTION_REG = 0x05;   // Prescaler 1:64;  pullup 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=1   p.107
 SWDTEN_bit = 0 ;

 //-------------------------------   INTERRUPTION   ----------------------------------------
 GIE_bit  = 1;          // Active toutes les INT  p.93
 
 CPT_100ms 
= CPT_10ms = Compteur_relais = 0;
 F_Sleep = 1;
 
 
//Conf_AMB8220();
 
/*#################################################################################################
################################      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 avanbt d'eteindre les INT
        GIE_bit  = 0;       // j'eteins les int
        
        TRISA4_bit 
= TRISA5_bit = 1;
        TRISC3_bit = 1;     // LED
        TRISA4_bit = TRISA5_bit = 1;   // AMB_RST et AMB_WUP
        WPUA = 0b00111011 ; // RA0 et RA1 pull-up
        WPUC = 0b00111000 ;
        LED = 0;
         
        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 ;
        
        LED 
= 1;
        SWDTEN_bit = 0;     // J'éteins le watchdog
        TRISC3_bit = 0;     // LED
        TRISA4_bit = TRISA5_bit = 0;   // AMB_RST et AMB_WUP
        WPUA = 0b00000011 ; // RA0 et RA1 pull-up
        WPUC = 0b00000000 ;
        
        Sleep_mode_off
();   // Je réveil le module radio
        TMR0       = 61;    // TMR0 Preload = 61
        CPT_100ms  = Valeur = 0;
        TMR0IE_bit = 1 ;
        GIE_bit  = 1;
     }

   asm CLRWDT ;
   
   
// 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 STOP_Ban       
: Montee_D = Montee_G = Descend_D = Descend_G = 0; Compteur_relais = 0 ; break;// j'éteins les moteurs
        case Monte_Ban_G    : Descend_G = 0; delay_ms(50); Montee_G = 1; Compteur_relais = 0 ; TMR1IE_bit = 1; break;
        case Descend_Ban_G  : Montee_G = 0; delay_ms(50); Descend_G = 1; Compteur_relais = 0 ; TMR1IE_bit = 1; break;
        case Monte_Ban_D    : Descend_D = 0; delay_ms(50); Montee_D = 1; Compteur_relais = 0 ; TMR1IE_bit = 1; break;
        case Descend_Ban_D  : Montee_D = 0; delay_ms(50); Descend_D = 1; Compteur_relais = 0 ; TMR1IE_bit = 1; break;
        case Monte_Ban_GD   : Descend_D = Descend_G = 0; delay_ms(50); Montee_G = Montee_D = 1; Compteur_relais = 0 ; TMR1IE_bit = 1; break;
        case Descend_Ban_GD : Montee_G = Montee_D = 0; delay_ms(50); Descend_D = Descend_G = 1; Compteur_relais = 0 ; TMR1IE_bit = 1; break;

        case Reveil         : TMR2IE_bit = 1;  break;   // je recois une ligne de vie, je raz le comtpeur
        
        default
: Montee_D = Montee_G = Descend_D = Descend_G = 0;
       }
    }
 }
}



/*#################################################################################################
################################      PROGRAMME SECONDAIRE     ####################################
#################################################################################################*/
void Sleep_mode_on(){
   // rentrer en LPM ( Low Power Mode)
   // envoie en hexa (02 28 01 01 2A)
   // Response (02 68 01 01 6A)
   do{
     UART1_Write(0x02);     // Start
     UART1_Write(0x28);     // Commande
     UART1_Write(0x01);     // Lenght
     UART1_Write(0x01);     // LPM
     UART1_Write(0x2A);     // CS
     delay_ms(50);
   }while (F_Sleep_OK == 0 );// Attente de la réponse
   F_Sleep_OK = 0;            // RAZ flag
}

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

/*#############################################################################################
Cette fonction est la pour une premiere configuration lors du premier branchement. Ensuite il faut la mettre en commentaire
Sinon il faut effectuer un RESET apres effectué des modifs non-volatiles
*/
void Conf_AMB8220(){

  // réglagle du RF_data_rate pour une meilleur sensibilité  (02 09 02 01 03 0B)
   do{
     UART1_Write(0x02);     // Start
     UART1_Write(0x09);     // Commande
     UART1_Write(0x02);     // Lenght
     UART1_Write(0x01);     // offset
     UART1_Write(0x03);     // parametre=3; = data rate=6kbps
     UART1_Write(0x0B);     // CS
     delay_ms(100);
   }while (Parametre_OK == 0 );// Attente de la réponse
   Parametre_OK = 0;            // RAZ flag

  // réglagle du Tx_Power pour diminuer la conso en émission    ( 02 09 02 04 00 0D )
   do{
     UART1_Write(0x02);     // Start
     UART1_Write(0x09);     // Commande
     UART1_Write(0x02);     // Lenght
     UART1_Write(0x04);     // offset
     UART1_Write(0x00);     // parametre
     UART1_Write(0x0D);     // CS
     delay_ms(100);
   }while (Parametre_OK == 0 );// Attente de la réponse
   Parametre_OK = 0;            // RAZ flag

  // réglagle du numero d'ID sur le réseau                     ( 02 09 02 03 02 08)
   do{
     UART1_Write(0x02);     // Start
     UART1_Write(0x09);     // Commande
     UART1_Write(0x02);     // Lenght
     UART1_Write(0x03);     // offset
     UART1_Write(ID_banette); // parametre:0x02
     UART1_Write(0x0A^ID_banette);     // CS
     delay_ms(100);
   }while (Parametre_OK == 0 );// Attente de la réponse
   Parametre_OK = 0;            // RAZ flag
}


Merci
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Programme qui se bloque
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#2 Message par satinas » ven. 9 avr. 2021 08:49 lien vers la Data-Sheet : Cliquez ici

Bonjour Jérémy

Oui, il faut gérer un time-out car les boucles while sont bloquantes

Programme qui se bloque
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. 9 avr. 2021 09:21 lien vers la Data-Sheet : Cliquez ici

Bonjour satinas,

Merci à toi d'(avoir regarder ce code, car je sais à quel point c'est pas évident .

Oui c'est bien ce à quoi je pensais .

Mais l'INT du watchdog devrait rester tout ça en tout état de cause non ?
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Programme qui se bloque
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#4 Message par satinas » ven. 9 avr. 2021 09:34 lien vers la Data-Sheet : Cliquez ici

Quels sont les mots de configuration hardware, notamment pour le watchdog.

Programme qui se bloque
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. 9 avr. 2021 09:35 lien vers la Data-Sheet : Cliquez ici

En toute logique je n'ai qu'une boucle bloquante. C'est celle qui réveille le module radio. Le problème doit donc venir d'ici.

Après analyse les INT ne reset pas le PIC. Les INT lève seulement un drapeau. Donc si le PIC est bloqué dans une boucle, il ne verra jamais le drapeau se lever et donc jamais il sera endormi par le watchdog donc rien n'est reseter.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Programme qui se bloque
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 » ven. 9 avr. 2021 10:01 lien vers la Data-Sheet : Cliquez ici

Un truc m'échappe .

Dans cette boucle qui met en veille le module radio. En fait j'envoie l'ordre de mise en veille en permanence, tant que j'ai pas reçu de réponse positive. Ce que j'ai du mal a comprendre, c'est que OK, il arrive une erreur de réception sur l'UART. Mais le coup d’après le message devrait bien passé non ?

Sauf , vous me direz si c'est possible, Quand j’envoie l'ordre de mise en veille du module radio, celui ci le reçoit, envoie la confirmation ( que je reçois mal) puis passe en veille. C'est donc quand je reçois mal une réponse de mise en veille que le bug se produit ?

Du coup dans ce cas de figure précis, la boucle ne sert à rien car la répétition de l’ordre est inefficace vu que le module est en veille et donc par définition sourd.Il serait préférable d'augmenter un peu la temporisation mais de ne pas faire de boucle ou de limiter le nombre de boucles à 3 par exemple.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Programme qui se bloque
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#7 Message par satinas » ven. 9 avr. 2021 10:07 lien vers la Data-Sheet : Cliquez ici

L'uart est hyper fiable, tu ne dois envoyer qu'une seule fois et au bon moment ta commande, et recevoir une réponse correcte. C'est pas une mitrailleuse, c'est un uart :)
Le AMB8220 n'est pas censé répondre à tous les coups ?
Le fait d'utiliser les interruptions complique le debug.

Programme qui se bloque
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. 9 avr. 2021 10:28 lien vers la Data-Sheet : Cliquez ici

L'AMB8220 est censé répondre à tout les coups. Sauf dans ce cas de figure précis, car il passe en veille ! du coup il répond une fois puis s'endort. Avec les autres commandes pas de problème, tant que lui cause il répond. C'est pour ça , qu'on peut se permettre de boucle pour éviter les erreurs, si la réponse est mauvaise on lui redemande. Mais dans ce cas la , ça fonctionne pas comme ça !

Je vais essayer avec une boucle de 3 tentatives.
Je rajoute également un RAZ de ma machine d'état UART après un réveil du PIC. Car des fois un caractère bizarre se glisse dans l'UART quand on allume un équipement.

Je ne pense pas que cela devrait être nocif pour le programme de toute façon.
Le problème c'est que c'est long a tester en vrai, étant donné que le problème survenait plutôt aléatoirement et rarement! Avec les beaux jours qui arrivent, je devrais sortir mes stores plus souvent :-D

Code : Tout sélectionner

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


Code : Tout sélectionner

        Sleep_mode_off();   // Je réveil le module radio
        TMR0       = 61;    // TMR0 Preload = 61
        CPT_100ms  = Valeur = 0;
        TMR0IE_bit = 1 ;
        Valeur = 0;     // RAZ de la machine UART
        GIE_bit  = 1;
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Programme qui se bloque
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#9 Message par Jérémy » ven. 9 avr. 2021 10:31 lien vers la Data-Sheet : Cliquez ici

Ça va être du sport d'injecter tout ça. Le boitier est en hauteur sous le toit de la terrasse .... escabeau , ordi portable, câble etc..... :sifflotte:
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Programme qui se bloque
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#10 Message par satinas » ven. 9 avr. 2021 10:35 lien vers la Data-Sheet : Cliquez ici

Toutes les erreurs doivent être prise en compte, avec un traitement adéquat, et il faut proscrire les boucles bloquantes, dans la version finale du programme. Je sais, je sais, je suis pénible de bon matin, pas réveillé :)


Retourner vers « Langage C »

Qui est en ligne

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