IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Test if ignoré


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut Test if ignoré
    Bonjour,

    Le programme ci-joint attend la saisie d'un caractère 'c' pour afficher une trame de C_maxcar octets.
    Ces octets contiennent les codes ascii consécutifs des caractères '0' à 'C'.
    Cet affichage devrait se produire C_nb_trame fois.

    Alors, le souci :
    Si les instructions Serial.print de la ligne 34 sont commentées, le test de n_trame est ignoré.
    Si ces instructions sont actives, le test est respecté !?!?!?
    Phénomène constaté avec le moniteur série et un programme de mon cru sur un PC.

    Je n'arrive pas à localiser mon erreur.

    So help me please.

    Cordialement,
    bidouilleelec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    /*
     *Le programme attend la saisie d'un caractère 'c' pour afficher une trame de C_maxcar octets.
     *Ces octets contiennent les codes ascii consécutifs des caractères '0' à 'C'.
     *Cet affichage devrait se produire C_nb_trame fois.
     
     *Alors, le souci :
     *Si les instructions Serial.print de la ligne 34 sont commentées, le test de n_trame est ignoré.
     *Si ces instructions sont actives, le test est respecté !?!?!? 
     */
     
    const int C_maxcar = 20; //256  
    const unsigned long C_nb_trame = 3 ;    // nb envoi de C_nb_trames de C_maxcar byte
    const byte C_valeur_octetdedepart =  0x30;  // 0x00 ;  //0xFB;  //0x30 = code de zéro
    byte octet[(C_maxcar)] ;
    int n_trame = 1;
    bool recu = false;
    char incomingByte = 'a';
     
    // ***************************************************
    void setup() { 
     
    Serial.begin(115200);      //1024000 230400  768000
    delay(500);
    // *** initialise un tableau de byte
        for (int k = 0; k<= C_maxcar - 1; k++){
            octet[k]  = k + C_valeur_octetdedepart ;       // code ascii de 0123456789:;<=>?@ABC      
        } // fin for            
    } // fin setup
     
    // ***************************************************
    void loop() {  
      recu = false;              
          if ( n_trame <= C_nb_trame ){
              //Serial.println("after test n_trame ");Serial.print("C_nb_trame = "); Serial.print(C_nb_trame);
              // *** attend un caractère 'c'
              while ( !recu ){
                    if (Serial.available() > 0) {
                        incomingByte = Serial.read();            
                        if (incomingByte == 'c' ) {                         
                            incomingByte = 'z';           
                            recu = true;                        
                        } // fin in == 'c'
                    } // fin Serial.available   
              } // fin while
     
              Serial.write(octet , C_maxcar);
              Serial.flush();                    
               n_trame++;
               //Serial.println("after test n_trame ");Serial.print("C_nb_trame = "); Serial.print(C_nb_trame);
          } // fin if n_trame
          else                
          {
            while (true) ;
          } // fin while        
    } // fin loop

  2. #2
    Membre expérimenté Avatar de Denis la Malice
    Homme Profil pro
    FabManager
    Inscrit en
    Février 2013
    Messages
    133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : FabManager
    Secteur : Services de proximité

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Par défaut Quelques détails ...
    Bonjour,
    quelques petites remarques sur ton code.
    C_nb_trame est de type const unsigned long
    n_trame est de type int (donc signé).

    En ligne 33, tu compare ces 2 valeurs dont l'une est signée et l'autre pas. Et ça, il faut éviter.

    En ligne 34, tu affiches la valeur de C_nb_trames à chaque tour de boucle. Mais c'est une constante. Tu espères qu'elle varie ?

    En ligne 34 et 49 tu affiches un message "... after test ...". N'est-ce pas plus différenciant de mettre des messages différents ? Par exemple "... before test ..." pour un des messages ?

    Le while (true) ; ne sert à rien. Supprime les lignes 51 à 54. Laisse la loop () faire son travail au lieu de saturer la CPU sans permettre d'interruption.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    /*
     *Le programme attend la saisie d'un caractère 'c' pour afficher une trame de C_maxcar octets.
     *Ces octets contiennent les codes ascii consécutifs des caractères '0' à 'C'.
     *Cet affichage devrait se produire C_nb_trame fois.
     
     *Alors, le souci :
     *Si les instructions Serial.print de la ligne 34 sont commentées, le test de n_trame est ignoré.
     *Si ces instructions sont actives, le test est respecté !?!?!? 
     */
     
    const int C_maxcar = 20; //256  
    const int C_nb_trame = 3 ;    // nb envoi de C_nb_trames de C_maxcar byte
    const byte C_valeur_octetdedepart =  0x30;  // 0x00 ;  //0xFB;  //0x30 = code de zéro
    byte octet[(C_maxcar)] ;
    int n_trame = 1 ;
    bool recu = false;
    char incomingByte = 'a';
     
    // ***************************************************
    void setup() { 
     
    Serial.begin(115200);      //1024000 230400  768000
    delay(500);
    // *** initialise un tableau de byte
        for (int k = 0; k < C_maxcar ; k++)
        {
            octet[k]  = k + C_valeur_octetdedepart ;       // code ascii de 0123456789:;<=>?@ABC      
        } // fin for            
    } // fin setup
     
    // ***************************************************
    void loop() {  
      recu = false;              
          if ( n_trame <= C_nb_trame )
          {
              //Serial.println() ; Serial.print("before test n_trame ");Serial.print("n_trame = "); Serial.println(n_trame);
              // *** attend un caractère 'c'
              while ( !recu )
              {
                    if (Serial.available() > 0) 
                    {
                        incomingByte = Serial.read();            
                        if (incomingByte == 'c' ) 
                        {                         
                            incomingByte = 'z';           
                            recu = true;                        
                        } // fin in == 'c'
                    } // fin Serial.available   
              } // fin while
     
              Serial.write(octet , C_maxcar);
              Serial.flush();                    
               n_trame++;
              //Serial.println() ; Serial.print("after test n_trame ");Serial.print("n_trame = "); Serial.println(n_trame);
          } // fin if n_trame
    } // fin loop

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut Bonjour Denis La Malice
    Bonjour Denis la Malice

    Grand merci pour votre réponse.
    Cependant :

    A/ "En ligne 33, tu compare ces 2 valeurs dont l'une est signée et l'autre pas. Et ça, il faut éviter."

    La constante n'est pas signée , ce qui aurait tendance à renforcer le test.
    Mais à l'origine les deux étaient des int.
    Mais j'ai essayé avec 2 unsigned long et 2 int: même souci.

    B/ "En ligne 34, tu affiches la valeur de C_nb_trames à chaque tour de boucle. Mais c'est une constante. Tu espères qu'elle varie ?"

    J'ai rajouté ce Serial.print de la constante quand j'ai constaté que le test n'était pas respecté. Je pense à un écrasement de données.
    Dans les faits je cherche à échanger des trames binaires aléatoires de 256 octets entre Arduino et PC.
    Ce Serial.print est uniquement pour test et serait nuisible dans l'utilisation "opérationnelle" .

    C/ "En ligne 34 et 49 tu affiches un message "... after test ...". N'est-ce pas plus différenciant de mettre des messages différents ? Par exemple "... before test ..." pour un des messages ?"

    Ah Yes!. En fait la ligne 49 peut être effacée : commentée ou pas , cela ne change rien au comportement du programme.

    D/"Le while (true) ; ne sert à rien. Supprime les lignes 51 à 54. Laisse la loop () faire son travail au lieu de saturer la CPU sans permettre d'interruption."

    Ah! C'est tout à fait volontaire. Ce programme ne sert (dans une version plus complète ) qu'à tester un programme de mon (petit) cru d'échange avec le PC (une sorte de moniteur série). J'ai joint une version simplifiée mais qui pose le même souci.

    E/ J'ai déassemblé le code. Il y a des trucs bizarres.
    Comme il se fait tard, je posterais demain le code déassemblé et mes remarques.
    Je reste stupéfait qu'un programme aussi simple puisse poser un souci.

    Encore merci de votre réponse.

    Cordialement
    bidouilleelec

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut Re Bonjour Bonjour Denis La Malice
    Re bonjour

    Alors, alors :
    en relisant vos conseils, j'ai supprimé les lignes 51 à 54.
    ET LA : magie.
    Le test est respecté.
    Il me reste à comprendre pourquoi.

    Merci pour la piste.

    Très cordialement,
    bidouileelec

  5. #5
    Membre expérimenté Avatar de Denis la Malice
    Homme Profil pro
    FabManager
    Inscrit en
    Février 2013
    Messages
    133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : FabManager
    Secteur : Services de proximité

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Par défaut
    Citation Envoyé par ducelier Voir le message
    ... Laisse la loop () faire son travail au lieu de saturer la CPU sans permettre d'interruption."...
    C'est en supprimant le while (true) ; que j'ai réussi à faire tourner ton programme sans exploser la pile.

    Essaie : while (true) delay (1) ; et ça fonctionnera mieux.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut Pile explosée ?
    Re bonjour Denis la Malice

    "C'est supprimant le while (true) ; que j'ai réussi à faire tourner ton programme sans exploser la pile."

    Pile explosée : le while (true); exploserait la pile?
    hé bé.Je ne savais pas.
    Cela expliquerait tout.
    Je vais regarder cela de près.
    C'est intéressant.

    Grace à vous je dormirais mieux cette nuit.

    Cordialement,
    bidouillellec

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut solution?
    Re-re Bonjour M. Denis

    Effectif , Bien vu, nouvelle version :
    Content d'avoir appris.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    /*
     *Le programme attend la saisie d'un caractère 'c' pour afficher une trame de C_maxcar octets.
     *Ces octets contiennent les codes ascii consécutifs des caractères '0' à 'C'.
     *Cet affichage devrait se produire C_nb_trame fois.
     
     *Alors, le souci :
     *Si les instructions Serial.print de la ligne 34 sont commentées, le test de n_trame est ignoré.
     *Si ces instructions sont actives, le test est respecté !?!?!? 
     *Problème résolu:
     *29/06/2018  <> 00h30  retrait du else while(true) !!!!!!!
     *29/06/2018 écrasement de pile ??????
     *Merci M. Denis La Malice
     *https://www.developpez.net/forums/d1868328/general-developpement/programmation-systeme/embarque/arduino/test-if-ignore/#post10334866
     */
    const int C_maxcar = 20; //256  
    int C_nb_trame = 3 ;    // nb envoi de C_nb_trame de C_maxcar byte
    const byte C_valeur_octetdedepart =  0x30;  //0x30 = code ascii de zéro
    byte octet[(C_maxcar)] ;
    int n_trame = 1;
    bool recu = false;
    char incomingByte = 'a';
    // ********************* setup ******************************
    void setup() {  
    Serial.begin(115200);      //1024000 230400  768000  fonctionne à 768000
    delay(500);
    // *** initialise un tableau de byte
        for (int k = 0; k <= C_maxcar - 1; k++)
        {
            octet[k]  = k + C_valeur_octetdedepart ;       // code ascii de 0123456789:;<=>?@ABC      
        } // fin for k           
    } // fin setup
    // ********************* loop ********************************
    void loop() {  
      recu = false;              
          if ( n_trame <= C_nb_trame ){
              //Serial.println("after test n_trame ");Serial.print("C_nb_trame = "); Serial.print(C_nb_trame);  //pour test
              // *** attend un caractère 'c'
              while ( !recu ){
                    if (Serial.available() > 0) {
                        incomingByte = Serial.read();            
                        if (incomingByte == 'c' ) {                         
                            incomingByte = 'z';       //inutile         
                            recu = true;                        
                        } // fin in == 'c'
                    } // fin Serial.available   
              } // fin while !recu      
              Serial.write(octet , C_maxcar);
              Serial.flush();                    
              n_trame++;          
          } // fin if n_trame     
    } // fin loop
    Best Regards,
    biduoilleelec

  8. #8
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Salut,
    Citation Envoyé par ducelier Voir le message
    Pile explosée : le while (true); exploserait la pile?
    [...]
    Je vais regarder cela de près.
    C'est intéressant.
    C'est surtout très bizarre !

    Un while(true); sans rien de particulier dans la boucle ne peut pas faire déborder la pile. Pour que celle-ci déborde il faut au moins un appel de fonction, d'interruption ou non, qui va générer un empilement (ou une variable qui fait un overflow mais rien ne dit qu'il va toucher la pile).

    Ça sent le bug caché. C'est peut être lié aux options d'optimisation du compilateur qui, lorsqu'il a vu ton while(true); et tout ton programme, a optimisé tout ça d'une certaine façon qui pourrait le faire réagir très différemment.


    A ta place j'essayerai de trouver ce qu'il se passe pour éviter que ce problème resurgisse pendant que tu avances dans ton programme. Malheureusement, le gros problème avec les Arduino UNO/MEGA c'est que tu ne peux pas faire du débug hardware, (c'est à dire voir en direct les registres, la mémoire et faire dérouler le programme en pas à pas) contrairement à des cartes Nucléo ou LaunchPad et c'est précisément dans un problème comme tu rencontres ici que ça te servirait.

  9. #9
    Membre expérimenté Avatar de Denis la Malice
    Homme Profil pro
    FabManager
    Inscrit en
    Février 2013
    Messages
    133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : FabManager
    Secteur : Services de proximité

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Par défaut Une piste de solution moins empirique ...
    J'ai trouvé ça sur un forum :
    The ESP8266 is a little different than the standard Arduino boards in that it has the watchdog(WDT) turned on by default. If the watchdog timer isn't periodically reset then it will automatically reset your ESP8266. The watchdog is reset every time loop() runs or you call delay() or yield() but if you have blocking code like the above then the watchdog may time out, resulting in your reset.
    Il y a un chien de garde qui doit régulièrement être réinitialisé. Visiblement, il est là pour surveiller qu'il n'y a pas de blocage du code. Il attend donc régulièrement un tour de loop() ou un appel à la fonction delay () ou yield ().

    Du coup les 2 solutions proposées : enlever les lignes du else pour redonner la main à loop () ou ajouter un delay (1) dans la boucle while sont de bonnes solutions. Seule l'explication était fantaisiste.

    Ça veut-il dire que le code fautif tournait sur un ESP8266 et pas sur un Arduino ?

  10. #10
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Aaaahhh
    Cette explication là me convient mieux !
    Là on a la vraie raison.... et jusqu'au bout de l'explication

    Denis la Malice



    En effet, le watchdog semble être la cause d'un RESET de la carte et pour en être vraiment sur et certain, il faudrait lire en boucle le bit numéro 3 du registre MCUSR dans le micro. Si celui-ci passe a 1 alors le micro s'apprête à faire un "RESET Watchdog". Page 79 de la datasheet : http://ww1.microchip.com/downloads/e..._Datasheet.pdf

    La fonction delay est implémenté comme suit d'après une source du forum Arduino :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void delay(unsigned long ms)
    {
    	uint16_t start = (uint16_t)micros();
     
    	while (ms > 0) {
    		yield();
    		if (((uint16_t)micros() - start) >= 1000) {
    			ms--;
    			start += 1000;
    		}
    	}
    }
    Et la fonction yield() rafraîchit le watchdog pour lui dire que le programme n'est pas planté et qu'il attend volontairement. Accessoirement on voit que delay() n'est qu'une vulgaire boucle et n'apporte pas plus d'oxygène à une boucle while(true); monopolisant 100% du CPU dans le micro.

  11. #11
    Membre expérimenté Avatar de Denis la Malice
    Homme Profil pro
    FabManager
    Inscrit en
    Février 2013
    Messages
    133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : FabManager
    Secteur : Services de proximité

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Par défaut yield () = O2
    Citation Envoyé par Vincent PETIT Voir le message
    Aaaahhh ... Accessoirement on voit que delay() n'est qu'une vulgaire boucle et n'apporte pas plus d'oxygène à une boucle while(true); monopolisant 100% du CPU dans le micro.
    Ben non. L'oxygène, c'est le yield () présent dans le delay () et pas dans le while (true) ;

  12. #12
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Alors ça dépend de ce que tu entends par un temps de respiration ou bouffée d'oxygène. Peut être que je n'ai pas compris ce que tu voulais dire. Initialement je pensais que tu parlais de laisser respirer 1ms le CPU car juste au dessus, tu disais à juste titre qu'il était monopolisé à 100%.

    Je vais regardé comment est implémenté yield la semaine prochaine pour en dire plus.

    Mais si c'est ce que je pense, cette fonction yield n'apporte pas non plus d'oxygène au CPU qui tournerait en rond dans une boucle, elle dit au watchdog (qui n'est autre qu'un Timer agissant sur le reset du microcontroleur) de relancer son timer avant le Reset.

    A la page 81 de la datasheet, que j'ai posté plus haut, on voit que suivant le réglage du timer du watchdog, il reset le micro au bout de 16ms si jamais on ne lui a pas envoyé un signal du genre : "reset pas, je suis pas planté, tout va bien". Pour moi le yield sert juste à ça mais il ne libère pas le CPU de sa boucle infinie.

    Je n'ai pas de Arduino sous la main là tout de suite mais en mettant un yield dans un while(TRUE) ça ne devrait plus planter. Tout comme ça ne devrait pas planter si on éteint le watchdog et qu'on se passe du yield (par contre je ne sais pas si Arduino laisserait faire si il voit éteint le watchdog ?)

  13. #13
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 127
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 127
    Par défaut
    Yep !

    J'interviens dans votre monde que je ne connais pas, mais j'en connais d'autres !
    Citation Envoyé par Vincent PETIT Voir le message
    Je vais regarder comment est implémenté yield la semaine prochaine pour en dire plus.
    Pas la peine, l'explication (limpide) est là : https://www.arduino.cc/en/Reference/SchedulerYield et c'est un peu comme le Application.ProcessMessages de Pascal (Delphi, Lazarus, etc.) ou le DoEvents de VB6 : dans une boucle d'instructions, il faut laisser du temps au processeur pour qu'il puisse s'occuper des autres processus.

    Sinon, on a l'impression qu'il est planté, ce qui est un abus de langage et n'est pas du tout le cas : il est au contraire tout à son travail dans la boucle.

  14. #14
    Membre expérimenté Avatar de Denis la Malice
    Homme Profil pro
    FabManager
    Inscrit en
    Février 2013
    Messages
    133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 66
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : FabManager
    Secteur : Services de proximité

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Par défaut Les chiens de garde
    Bonjour,
    l'oxygène, ce n'est pas tant pour la CPU que pour les chiens. Il y a le chien quincaillerie (hardware) et le chien logiciel (software). On peut arrêter le soft mais pas le hard (on gagne quelques secondes). J'ai essayé le yield () dans la boucle, il n'y a plus de reset.

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut Explication?
    Bonjour Denis ,Vincent, Jipété

    Précisions : le code en cause est destiné à tourner sur un Arduino Uno, pas sur un ESP8266.
    Le watchdog n'est pas activé.

    Alors , après déassemblage :
    dans la version avec le while(true), si les instructions Serial.print de la ligne 34 sont commentées, le test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( n_trame <= C_nb_trame )
    n'est pas généré (absent du code assembleur) , du diable pouquoi.
    Mais si on rajoute un delay dans le while(true) , le test est généré.

    Denis :
    Le while (true) ; ne sert à rien. Supprime les lignes 51 à 54. Laisse la loop () faire son travail au lieu de saturer la CPU sans permettre d'interruption.
    Je ne pense pas que le while (true) empêche les interruptions.

    Cordialement,
    bidouilleelec

  16. #16
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Salut,
    Tu n'as pas lu nos échanges ?
    Citation Envoyé par ducelier Voir le message
    Le watchdog n'est pas activé
    Arduino active le WDT dans ton dos (et de toute manière au démarrage il est activé par défaut), de la même manière qu'il configure le TIMER0 pour la fonction delay etc... Arduino fait plein de trucs sans le dire.

    Dans ton programme le WDT est activé et c'est lui qui reset le micro au bout d'un certain temps.

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Par défaut WDT sur Arduino Uno
    Bonjour Vincent PETIT


    Citation Envoyé par Vincent PETIT Voir le message
    Salut,

    Arduino active le WDT dans ton dos (et de toute manière au démarrage il est activé par défaut), de la même manière qu'il configure le TIMER0 pour la fonction delay etc... Arduino fait plein de trucs sans le dire.

    Dans ton programme le WDT est activé et c'est lui qui reset le micro au bout d'un certain temps.
    J'ai bien lu toutes les réponses et signalé qu'il N'y avait PAS de déclenchement du watchdog.
    Sur Arduino Uno , le WDT N'est PAS activé par défaut.
    Dans les cas de dysfonctionnement cités, le WDT N'est PAS en cause.

    Il est clairement établi que l'optimiseur, dans divers cas de figures , supprime la génération correcte du test de n_trame et de la boucle infinie.

    Cordialement,
    bidouilleelec

  18. #18
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Hummm ça n'est pas vraiment ce que je vois en dé-assemblant ton programme.

    J'ai fait un avr-objdump -h -d -l -S ton_programme.elf dans les deux versions, c'est à dire la version qui fonctionne sans le commentaire de la ligne 34 et avec le commentaire sur la ligne 34.

    Que l'optimisation supprime du code, c'est possible car je me suis déjà fait avoir et c'est pour cette raison que je l'ai dit dans le message #8 https://www.developpez.net/forums/d1.../#post10335282 mais là, après désassemblage on voit bien la présence de l'intégralité de ton programme, à la ligne 34 prés, que l'on soit dans la version qui marche ou celle qui ne marche pas.


    Pour apporter des éléments de lecture :
    Dans les fichiers désassemblés, par exemple la ligne /usr/share/arduino/sketch_jul10a.ino:31 correspond exactement à la ligne 31 de ton programme. Par exemple, le code désassemblé de la version avec commentaire, ne fait pas référence à la ligne 34. Mais si tu regardes de prés tu verras quand les deux versions le compilateur n'a pas supprimer du code.

    Ta condition if ( n_trame <= C_nb_trame ) se trouve à la ligne 33 dans ton programme ce qui correspond, dans les deux fichiers désassemblés, aux lignes /usr/share/arduino/sketch_jul10a.ino:33


    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    /*
     *Le programme attend la saisie d'un caractère 'c' pour afficher une trame de C_maxcar octets.
     *Ces octets contiennent les codes ascii consécutifs des caractères '0' à 'C'.
     *Cet affichage devrait se produire C_nb_trame fois.
     
     *Alors, le souci :
     *Si les instructions Serial.print de la ligne 34 sont commentées, le test de n_trame est ignoré.
     *Si ces instructions sont actives, le test est respecté !?!?!? 
     */
     
    const int C_maxcar = 20; //256  
    const unsigned long C_nb_trame = 3 ;    // nb envoi de C_nb_trames de C_maxcar byte
    const byte C_valeur_octetdedepart =  0x30;  // 0x00 ;  //0xFB;  //0x30 = code de zéro
    byte octet[(C_maxcar)] ;
    int n_trame = 1;
    bool recu = false;
    char incomingByte = 'a';
     
    // ***************************************************
    void setup() { 
     
    Serial.begin(115200);      //1024000 230400  768000
    delay(500);
    // *** initialise un tableau de byte
        for (int k = 0; k<= C_maxcar - 1; k++){
            octet[k]  = k + C_valeur_octetdedepart ;       // code ascii de 0123456789:;<=>?@ABC      
        } // fin for            
    } // fin setup
     
    // ***************************************************
    void loop() {  
      recu = false;              
          if ( n_trame <= C_nb_trame ){
              //Serial.println("after test n_trame ");Serial.print("C_nb_trame = "); Serial.print(C_nb_trame);
              // *** attend un caractère 'c'
              while ( !recu ){
                    if (Serial.available() > 0) {
                        incomingByte = Serial.read();            
                        if (incomingByte == 'c' ) {                         
                            incomingByte = 'z';           
                            recu = true;                        
                        } // fin in == 'c'
                    } // fin Serial.available   
              } // fin while
     
              Serial.write(octet , C_maxcar);
              Serial.flush();                    
               n_trame++;
               //Serial.println("after test n_trame ");Serial.print("C_nb_trame = "); Serial.print(C_nb_trame);
          } // fin if n_trame
          else                
          {
            while (true) ;
          } // fin while        
    } // fin loop

    Voici le code désassemblé de ton programme avec le commentaire de la ligne 34 (je ne mets que la fonction loop())
    Code A : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    000000ea <loop>:
    loop():
    /usr/share/arduino/sketch_jul10a.ino:31
      ea:	cf 93       	push	r28
      ec:	df 93       	push	r29
    /usr/share/arduino/sketch_jul10a.ino:32
      ee:	10 92 14 01 	sts	0x0114, r1
    /usr/share/arduino/sketch_jul10a.ino:33
      f2:	80 91 01 01 	lds	r24, 0x0101
      f6:	90 91 02 01 	lds	r25, 0x0102
      fa:	04 97       	sbiw	r24, 0x04	; 4
      fc:	08 f0       	brcs	.+2      	; 0x100 <loop+0x16>
      fe:	32 c0       	rjmp	.+100    	; 0x164 <loop+0x7a>
    /usr/share/arduino/sketch_jul10a.ino:40
     100:	ca e7       	ldi	r28, 0x7A	; 122
    /usr/share/arduino/sketch_jul10a.ino:41
     102:	d1 e0       	ldi	r29, 0x01	; 1
    /usr/share/arduino/sketch_jul10a.ino:36
     104:	80 91 14 01 	lds	r24, 0x0114
     108:	81 11       	cpse	r24, r1
     10a:	14 c0       	rjmp	.+40     	; 0x134 <loop+0x4a>
    /usr/share/arduino/sketch_jul10a.ino:37
     10c:	82 e3       	ldi	r24, 0x32	; 50
     10e:	91 e0       	ldi	r25, 0x01	; 1
     110:	0e 94 ab 01 	call	0x356	; 0x356 <_ZN14HardwareSerial9availableEv>
     114:	18 16       	cp	r1, r24
     116:	19 06       	cpc	r1, r25
     118:	ac f7       	brge	.-22     	; 0x104 <loop+0x1a>
    /usr/share/arduino/sketch_jul10a.ino:38
     11a:	82 e3       	ldi	r24, 0x32	; 50
     11c:	91 e0       	ldi	r25, 0x01	; 1
     11e:	0e 94 d7 01 	call	0x3ae	; 0x3ae <_ZN14HardwareSerial4readEv>
     122:	80 93 00 01 	sts	0x0100, r24
    /usr/share/arduino/sketch_jul10a.ino:39
     126:	83 36       	cpi	r24, 0x63	; 99
     128:	69 f7       	brne	.-38     	; 0x104 <loop+0x1a>
    /usr/share/arduino/sketch_jul10a.ino:40
     12a:	c0 93 00 01 	sts	0x0100, r28
    /usr/share/arduino/sketch_jul10a.ino:41
     12e:	d0 93 14 01 	sts	0x0114, r29
     132:	e8 cf       	rjmp	.-48     	; 0x104 <loop+0x1a>
    /usr/share/arduino/sketch_jul10a.ino:46
     134:	44 e1       	ldi	r20, 0x14	; 20
     136:	50 e0       	ldi	r21, 0x00	; 0
     138:	65 e1       	ldi	r22, 0x15	; 21
     13a:	71 e0       	ldi	r23, 0x01	; 1
     13c:	82 e3       	ldi	r24, 0x32	; 50
     13e:	91 e0       	ldi	r25, 0x01	; 1
     140:	0e 94 83 01 	call	0x306	; 0x306 <_ZN5Print5writeEPKhj>
    /usr/share/arduino/sketch_jul10a.ino:47
     144:	82 e3       	ldi	r24, 0x32	; 50
     146:	91 e0       	ldi	r25, 0x01	; 1
     148:	0e 94 f7 01 	call	0x3ee	; 0x3ee <_ZN14HardwareSerial5flushEv>
    /usr/share/arduino/sketch_jul10a.ino:48
     14c:	80 91 01 01 	lds	r24, 0x0101
     150:	90 91 02 01 	lds	r25, 0x0102
     154:	01 96       	adiw	r24, 0x01	; 1
     156:	90 93 02 01 	sts	0x0102, r25
     15a:	80 93 01 01 	sts	0x0101, r24
    /usr/share/arduino/sketch_jul10a.ino:55
     15e:	df 91       	pop	r29
     160:	cf 91       	pop	r28
     162:	08 95       	ret
    /usr/share/arduino/sketch_jul10a.ino:33
     164:	ff cf       	rjmp	.-2      	; 0x164 <loop+0x7a>

    Et ici, toujours le loop() de ton programme mais en retirant le commentaire de la ligne 34.
    Code A : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    000000ea <loop>:
    loop():
    /usr/share/arduino/sketch_jul10a.ino:31
      ea:	cf 93       	push	r28
      ec:	df 93       	push	r29
    /usr/share/arduino/sketch_jul10a.ino:32
      ee:	10 92 36 01 	sts	0x0136, r1
    /usr/share/arduino/sketch_jul10a.ino:33
      f2:	80 91 01 01 	lds	r24, 0x0101
      f6:	90 91 02 01 	lds	r25, 0x0102
      fa:	04 97       	sbiw	r24, 0x04	; 4
      fc:	08 f0       	brcs	.+2      	; 0x100 <loop+0x16>
      fe:	48 c0       	rjmp	.+144    	; 0x190 <loop+0xa6>
    /usr/share/arduino/sketch_jul10a.ino:34
     100:	63 e0       	ldi	r22, 0x03	; 3
     102:	71 e0       	ldi	r23, 0x01	; 1
     104:	84 e5       	ldi	r24, 0x54	; 84
     106:	91 e0       	ldi	r25, 0x01	; 1
     108:	0e 94 f3 01 	call	0x3e6	; 0x3e6 <_ZN5Print7printlnEPKc>
     10c:	67 e1       	ldi	r22, 0x17	; 23
     10e:	71 e0       	ldi	r23, 0x01	; 1
     110:	84 e5       	ldi	r24, 0x54	; 84
     112:	91 e0       	ldi	r25, 0x01	; 1
     114:	0e 94 d6 01 	call	0x3ac	; 0x3ac <_ZN5Print5printEPKc>
     118:	2a e0       	ldi	r18, 0x0A	; 10
     11a:	30 e0       	ldi	r19, 0x00	; 0
     11c:	43 e0       	ldi	r20, 0x03	; 3
     11e:	50 e0       	ldi	r21, 0x00	; 0
     120:	60 e0       	ldi	r22, 0x00	; 0
     122:	70 e0       	ldi	r23, 0x00	; 0
     124:	84 e5       	ldi	r24, 0x54	; 84
     126:	91 e0       	ldi	r25, 0x01	; 1
     128:	0e 94 5b 02 	call	0x4b6	; 0x4b6 <_ZN5Print5printEmi>
    /usr/share/arduino/sketch_jul10a.ino:40
     12c:	ca e7       	ldi	r28, 0x7A	; 122
    /usr/share/arduino/sketch_jul10a.ino:41
     12e:	d1 e0       	ldi	r29, 0x01	; 1
    /usr/share/arduino/sketch_jul10a.ino:36
     130:	80 91 36 01 	lds	r24, 0x0136
     134:	81 11       	cpse	r24, r1
     136:	14 c0       	rjmp	.+40     	; 0x160 <loop+0x76>
    /usr/share/arduino/sketch_jul10a.ino:37
     138:	84 e5       	ldi	r24, 0x54	; 84
     13a:	91 e0       	ldi	r25, 0x01	; 1
     13c:	0e 94 68 02 	call	0x4d0	; 0x4d0 <_ZN14HardwareSerial9availableEv>
     140:	18 16       	cp	r1, r24
     142:	19 06       	cpc	r1, r25
     144:	ac f7       	brge	.-22     	; 0x130 <loop+0x46>
    /usr/share/arduino/sketch_jul10a.ino:38
     146:	84 e5       	ldi	r24, 0x54	; 84
     148:	91 e0       	ldi	r25, 0x01	; 1
     14a:	0e 94 94 02 	call	0x528	; 0x528 <_ZN14HardwareSerial4readEv>
     14e:	80 93 00 01 	sts	0x0100, r24
    /usr/share/arduino/sketch_jul10a.ino:39
     152:	83 36       	cpi	r24, 0x63	; 99
     154:	69 f7       	brne	.-38     	; 0x130 <loop+0x46>
    /usr/share/arduino/sketch_jul10a.ino:40
     156:	c0 93 00 01 	sts	0x0100, r28
    /usr/share/arduino/sketch_jul10a.ino:41
     15a:	d0 93 36 01 	sts	0x0136, r29
     15e:	e8 cf       	rjmp	.-48     	; 0x130 <loop+0x46>
    /usr/share/arduino/sketch_jul10a.ino:46
     160:	44 e1       	ldi	r20, 0x14	; 20
     162:	50 e0       	ldi	r21, 0x00	; 0
     164:	67 e3       	ldi	r22, 0x37	; 55
     166:	71 e0       	ldi	r23, 0x01	; 1
     168:	84 e5       	ldi	r24, 0x54	; 84
     16a:	91 e0       	ldi	r25, 0x01	; 1
     16c:	0e 94 99 01 	call	0x332	; 0x332 <_ZN5Print5writeEPKhj>
    /usr/share/arduino/sketch_jul10a.ino:47
     170:	84 e5       	ldi	r24, 0x54	; 84
     172:	91 e0       	ldi	r25, 0x01	; 1
     174:	0e 94 b4 02 	call	0x568	; 0x568 <_ZN14HardwareSerial5flushEv>
    /usr/share/arduino/sketch_jul10a.ino:48
     178:	80 91 01 01 	lds	r24, 0x0101
     17c:	90 91 02 01 	lds	r25, 0x0102
     180:	01 96       	adiw	r24, 0x01	; 1
     182:	90 93 02 01 	sts	0x0102, r25
     186:	80 93 01 01 	sts	0x0101, r24
    /usr/share/arduino/sketch_jul10a.ino:55
     18a:	df 91       	pop	r29
     18c:	cf 91       	pop	r28
     18e:	08 95       	ret
    /usr/share/arduino/sketch_jul10a.ino:33
     190:	ff cf       	rjmp	.-2      	; 0x190 <loop+0xa6>

  19. #19
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Mais ce n'est pas un bug, c'est normal.

    Le WDT (WatchDog timer) reset le micro au bout d'un certain temps car c'est son rôle lorsqu'on l'active. Un WDT ça sert à faire ça, il permet d'empêcher le micro de planter dans une boucle sans fin et involontaire en le résétant.

    Il suffit de rafraîchir le WDT par la fonction yield() dans la boucle d'attente, et de manière régulière. C'est ce que fait la fonction delay () par exemple.

    Ce n'est pas un bug.

Discussions similaires

  1. Ignorer une méthode pendant les tests
    Par oxilia dans le forum Spring
    Réponses: 2
    Dernier message: 22/01/2015, 16h54
  2. [NUnit] - Ignorer classe Test
    Par marcel_kobain dans le forum C#
    Réponses: 2
    Dernier message: 15/05/2009, 14h32
  3. [XSL] Test sur un xsl-if qui semble ignoré
    Par Shadow aok dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 18/04/2006, 18h23
  4. [XMLRAD] test de nullité
    Par Pm dans le forum XMLRAD
    Réponses: 5
    Dernier message: 29/11/2002, 10h57
  5. test collisions
    Par tatakinawa dans le forum OpenGL
    Réponses: 5
    Dernier message: 08/06/2002, 06h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo