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

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Points : 20
    Points
    20
    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 actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    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
    De la réflexion, naît l'action ...

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Points : 20
    Points
    20
    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 à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Points : 20
    Points
    20
    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 actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    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.
    De la réflexion, naît l'action ...

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Points : 20
    Points
    20
    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 à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Points : 20
    Points
    20
    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 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    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.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  9. #9
    Membre actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    Par défaut
    Citation Envoyé par Vincent PETIT Voir le message
    ... C'est surtout très bizarre ! ...
    J'avoue que l'explication de la pile explosée est peut-être un peu aléatoire, mais en tout cas ça crashe la carte (j'ai testé le code sur une Wemos, c'est ce que j'avais sous la main). Je trouve une mauvaise idée de coder une instruction qui prenne toute la CPU à 100% sans laisser de miettes à tout le reste (interruptions par exemple). Donc soit on supprime les lignes pour refaire un tour de loop (), soit on accorde une milliseconde de respiration while (true) delay(1) ;
    Et si on teste une partie du programme et que l'on veut simuler le futur code, on peut écrire quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while (true)
    {
        Serial.print (".") ;
        delay (1000) ;
    }
    De la réflexion, naît l'action ...

  10. #10
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    Par défaut
    Citation Envoyé par Denis la Malice Voir le message
    J'avoue que l'explication de la pile explosée est peut-être un peu aléatoire.
    Je ne remettais pas en cause ton explication, c'est peut être bien la pile qui déborde mais en tout cas ça me paraît très étrange et ça mérite d'y regarder de prés pour voir ce qu'il se passe.

    Citation Envoyé par Denis la Malice Voir le message
    Je trouve une mauvaise idée de coder une instruction qui prenne toute la CPU à 100%
    Moi aussi. En général j'endors mon micro en le mettant en veille (plus ou moins profonde, parfois même CPU off, Auxiliaire Clock off et il n'y a plus que la RAM et les Spécials Functions Registers qui sont maintenus sous tension). Le réveil prend une petite 10aine de µs, en fonction des micro, et se fait par une interruption extérieure.

    Citation Envoyé par Denis la Malice Voir le message
    sans laisser de miettes à tout le reste (interruptions par exemple).
    Donc soit on supprime les lignes pour refaire un tour de loop (), soit on accorde une milliseconde de respiration [B]while (true) delay(1) ;
    Je t'invite à essayer pour voir si ça fait vraiment ce que tu penses.

    Une interruption n'est absolument pas gênée par un while (true); dans le programme principal. Tu peux t'en convaincre en faisant un programme principal bloqué dans une boucle qui ne fait rien et un programme d'interruption qui fait clignoter une LED. Tu verras que malgré la présence d'une boucle qui monopolise 100% du CPU, celle-ci est interrompue par le programme d'interruption qui fera clignoter la LED. Dès lors, la présence d'un delay(1) dans la boucle n'est pas nécessaire sans compter que cette fonction est aussi une simple boucle qui monopolise tout autant le CPU
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  11. #11
    Membre actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    Par défaut
    Citation Envoyé par Vincent PETIT Voir le message
    ... Je t'invite à essayer pour voir si ça fait vraiment ce que tu penses. ...
    Mince, la science ne m'a rien appris. En revanche l'expérience m'a montré que le while (true) delay (1) ; ne crash pas alors que le while (true) ; lui crashe.

    Il faudrait désassembler le code généré et le faire tourner sur un simulateur. Si quelqu'un a le temps de le faire, le résultat m'intéresse

    Sur la console, lors du plantage :
    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
    Soft WDT reset
     
    ctx: cont 
    sp: 3ffef760 end: 3ffef950 offset: 01b0
     
    >>>stack>>>
    3ffef910:  3ffee6f8 3ffe84e0 3ffee904 402020e8  
    3ffef920:  00000000 00000000 00000001 3ffee928  
    3ffef930:  3fffdad0 00000000 3ffee920 40202424  
    3ffef940:  feefeffe feefeffe 3ffee930 40100108  
    <<<stack<<<
     
     ets Jan  8 2013,rst cause:2, boot mode:(1,7)
     
     
     ets Jan  8 2013,rst cause:4, boot mode:(1,7)
     
    wdt reset
    De la réflexion, naît l'action ...

  12. #12
    Membre actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    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 ?
    De la réflexion, naît l'action ...

  13. #13
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    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.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  14. #14
    Membre actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    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) ;
    De la réflexion, naît l'action ...

  15. #15
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    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 ?)
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  16. #16
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 729
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 729
    Points : 15 133
    Points
    15 133
    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.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  17. #17
    Membre actif 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 : 65
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Février 2013
    Messages : 133
    Points : 287
    Points
    287
    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.
    De la réflexion, naît l'action ...

  18. #18
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 49
    Points : 20
    Points
    20
    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

  19. #19
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    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.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  20. #20
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 190
    Points : 11 573
    Points
    11 573
    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.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

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