Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2399 connectés 

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Arduino nano every vs copie BUG

n°401182
heartz
Posté le 20-04-2023 à 13:41:54  profilanswer
 

Bonjour,
 
J'étais tranquillement en train de bosser sur un projet de chronomètre géant lorsque la fatigue me frappa et me fit commettre l’irréparable, j'ai inter-changé mon CD4543 avec mon ULN2003 par mégarde et depuis mon arduino nano every ne fonctionne plus. Jusque-là rien de choquant, je vais racheter un arduino nano, pas un every et pas un original une copie de chez Whadda / Velleman
 
Je retourne dans l'appli arduino je reteleverse avec succès le même programme (joint en réponse) et là le chronomètre affiche bien les 0 du départ, mais aucune réaction lorsque j'actionne le BP qui contrôle le départ/l'arret !
 
Je mets des serial print pour voir ce qu'il se passe dans le programme et je vois que l'état du BP change bien, mais que les chiffres que je veux afficher reste bien à 0, je n'y comprends plus rien !
 
Je dois terminer ce projet absolument pour une compétition samedi prochain ! Si une âme charitable pleine de connaissance peut me venir en aide, j'en serai ravi :))
 
Belle journée,
 
Clément.
Modifier le message

mood
Publicité
Posté le 20-04-2023 à 13:41:54  profilanswer
 

n°401183
heartz
Posté le 20-04-2023 à 13:42:45  profilanswer
 

Code :
  1. byte bitn[]= {2,3,4,5}; //4 pins de l'écriture des 4 bits des décodeurs (bitn[0] = 0 puis 2,4,8)
  2. byte latch[] = {6,7,8,9,10,11}; // 6 pins des latch des décodeurs (latch[0] = centieme puis 6dc,s,ds,m,dm)
  3. int chiffre[] = {0,0,0,0,0,0}; //chiffres à afficher en façade (chiffre[0] = dizaine min puis m,ds,s,dc,c)
  4. int temps[3] = {0,0,0}; //liste contenant le temps sur 3chiffre 0m 1s 2c
  5. const int bpss = 12; // bouton poussoir start/stop connecté à la masse si appuyer
  6. const int bpreset = 13; //bouton poussoir reset connecté à la masse si appuyer
  7. boolean etatss = false; // variable vrai/faux pour signaler start/stop
  8. boolean etatreset = false; // variable vrai/faux pour signaler reset on/off
  9. boolean premier_demarrage = true; // variable vrai/faux pour signaler si premier demarage ou non
  10. volatile unsigned long t0;         //variable du temps écoulé avant le start
  11. volatile unsigned long tecoul;     //variable du temps calcul pour avoir le tps ecoulé hors chorono
  12. volatile unsigned long tpause = 0; //variable du temps ecoulé avant la pause
  13. volatile unsigned long tchrono; //temps du chrono en ms utilisé pour le calcul
  14.  
  15. void setup()
  16. {
  17.     Serial.begin(9600);
  18.    // Les broches sont toutes des sorties
  19.     pinMode(bitn[0], OUTPUT);
  20.     pinMode(bitn[1], OUTPUT);
  21.     pinMode(bitn[2], OUTPUT);
  22.     pinMode(bitn[3], OUTPUT);
  23.     pinMode(latch[0], OUTPUT);
  24.     pinMode(latch[1], OUTPUT);
  25.     pinMode(latch[2], OUTPUT);
  26.     pinMode(latch[3], OUTPUT);
  27.     pinMode(latch[4], OUTPUT);
  28.     pinMode(latch[5], OUTPUT);
  29.     // sauf les deux BP
  30.     pinMode(bpss, INPUT_PULLUP);
  31.     pinMode(bpreset, INPUT_PULLUP);
  32.    
  33.     digitalWrite(bitn[0], LOW);//0
  34.     digitalWrite(bitn[1], LOW);//0
  35.     digitalWrite(bitn[2], LOW);//0
  36.     digitalWrite(bitn[3], LOW);//0
  37.     for(byte i=0; i<6; i++)// tous les decodeur s'ouvrent puis se ferme pour recevoir chacun un 0
  38.     {
  39.       digitalWrite(latch[i],1);
  40.       digitalWrite(latch[i],0);
  41.     }
  42.     // si le bouton start est enfoncé lancer la fonction startstop
  43.     attachInterrupt(digitalPinToInterrupt(bpss),evenement_start,FALLING);
  44.     // si le bouton reset est enfoncé lancer la fonction reset
  45.     attachInterrupt(digitalPinToInterrupt(bpreset),evenement_reset,FALLING);
  46. }
  47. // on change d'état start stop à chaque appui du bpss et on récupère sois le temps de départ soit le temps de pause
  48. void evenement_start()
  49. {
  50.  
  51.   etatss = !etatss ;// on change l'état de start vers stop ou inversement
  52.  
  53.   if (etatss == true)/*si start tester si 1er demarage pour init T0 sinon MAJ tecoul
  54.                        si pause actualiser le temps pause*/
  55.         {
  56.             if (premier_demarrage == true)//si premier demarage initialisation de t0
  57.             {
  58.             t0 = millis();
  59.             tecoul = t0;
  60.             premier_demarrage = false;
  61.             }
  62.          
  63.             else //sinon actualiser le temps ecoulé à soustraire à millis
  64.             {
  65.             tecoul = millis() - tpause;
  66.             }
  67.         }
  68.   else
  69.         {
  70.             tpause = millis() - tecoul ;//temps au moment de l'appuie moins le temps recup au lancement
  71.         }
  72. }
  73. void evenement_reset()
  74. {
  75.   if (etatss == false) //reset uniquement si chrono en pause
  76.   {
  77.     etatreset = true; // on demande un reset en le passant à vrai
  78.     premier_demarrage = true;// on revient à l'état premier demarrage pour reinit le chrono à 0
  79.   }
  80. }
  81. void affiche_digits()
  82. {
  83.     for(byte i=0; i<6; i++)
  84.     {
  85.         for(byte n=0; n<4; n++)
  86.             digitalWrite(bitn[n], bitRead(chiffre[i],n));
  87.         //Latch
  88.         digitalWrite(latch[i],1);
  89.         digitalWrite(latch[i],0);
  90.     }
  91. }
  92. void calcul_cpt_msc()
  93. {
  94.     //temps du chrono = temps actuel - temps écoulé hors chrono
  95.     tchrono = millis() - tecoul;
  96.     //premiere case = retient les minutes si +1min retirer 60000ms @ tchrono
  97.     temps[0] = tchrono / 60000;
  98.     tchrono %= 60000;
  99.     //deuxieme case = retient les secondes si +1s retirer 1000ms @ tchrono
  100.     temps[1] = tchrono / 1000;
  101.     tchrono %= 1000;
  102.     //troisieme case = retient les centiemes
  103.     temps[2] = tchrono / 10;
  104.     chiffre[0] = temps[2] % 10;  //chiffre5 = centiemes
  105.     chiffre[1] = temps[2] / 10;  //chiffre4 = dizaine de cent
  106.     chiffre[2] = temps[1] % 10;  //chiffre3 = secondes
  107.     chiffre[3] = temps[1] / 10;  //chiffre2 = dizaine de sec
  108.     chiffre[4] = temps[0] % 10;  //chiffre1 = minutes
  109.     chiffre[5] = temps[0] / 10;  //chiffre0 = dizaine de minutes
  110. }
  111. void reset_digits()//tous les bitn passent à 0 et sont envoyés sur chaque decodeur et l'état reset est reinitialisé
  112. {
  113.     for(byte n=0; n<4; n++)
  114.         digitalWrite(bitn[n],0);
  115.     for(byte i=0; i<6; i++)
  116.     {
  117.         digitalWrite(latch[i],1);
  118.         digitalWrite(latch[i],0);
  119.     }
  120.     etatreset = false;
  121. }
  122. void loop ()
  123. {
  124.  
  125.   if( etatss == true)//si le chrono est sur on, lancer le compteur et afficher
  126.   {
  127.     calcul_cpt_msc();
  128.     affiche_digits();
  129.   }
  130.  
  131.   if( etatreset == true)// si le reset est demandé executer reset_digits
  132.   {
  133.     reset_digits();
  134.   }
  135.          
  136.          
  137.           Serial.print("\n" );
  138.           Serial.print("\n" );
  139.           Serial.print("\n" );
  140.           Serial.print(millis());
  141.           Serial.print("\n" );
  142.           Serial.print("\n" );
  143.           Serial.print("valeur etatss :" );
  144.           Serial.print("\n" );
  145.           Serial.print(etatss);
  146.           Serial.print("\n" );
  147.           Serial.print(digitalRead(bpss));
  148.           Serial.print("\n" );
  149.           Serial.print("valeur etatreset :" );
  150.           Serial.print("\n" );
  151.           Serial.print(etatreset);
  152.           Serial.print("\n" );
  153.           Serial.print(digitalRead(bpreset));
  154.           Serial.print("\n" );
  155.           Serial.print("Chrono time :" );
  156.           Serial.print("\n" );
  157.           Serial.print("\n" );
  158.           Serial.print("\n" );
  159.           Serial.print("\n" );
  160.           for (byte i=5; i<6;i--)
  161.           {
  162.             Serial.print(chiffre[i]);
  163.             Serial.print("\n" );
  164.           }
  165.           Serial.print("\n" );
  166. }

n°401191
rat de com​bat
attention rongeur méchant!
Posté le 20-04-2023 à 16:42:47  profilanswer
 

T'as bien remis ton CD4543 je suppose? Dans le bon sens aussi? :o
 
Je vais regarder le code tout à l'heure si j'ai le temps. En attendant, si tu as un schéma du montage que tu peux poster...


---------------
Si vous ouvrez un sujet merci de ne pas le "laisser mourir" subitement et de le marquer comme "résolu" le cas échéant!
n°401200
rat de com​bat
attention rongeur méchant!
Posté le 20-04-2023 à 19:31:22  profilanswer
 

Bon, y'a quelque soucis avec ce code...
 
Déjà ceci

for (byte i=5; i<6;i--)

me paraît pas bon, mais surtout: Tes BP ont ce qu'on appelle du "bounce", autrement dit si tu appuies dessus en réalité tu as plusieurs petits appuis brefs à cause de la mécanique du bouton. Du coup si tu mets une interruption directement tu vas avoir l'interruption qui s'exécute plusieurs fois, le nombre exact étant imprévisible.
 
Il ne faut donc jamais mettre d'INT sur un BP (sauf pour réveiller un µC qui dort).
 
Je ne sais bien sûr pas si ton soucis vient de la mais c'est une possibilité. Je suppose que tu n'as pas d'oscilloscope? Alors rajoute un simple compteur dans chaque fonction INT et transmet le nombre (variable "volatile"!) dans la main par port série et regarde si ça déconne comme je décrivais plus haut.
 
Aussi les variables >8 bits faut faire du "atomic acess" en principe, sinon bonjour les bugs qui surviennent que rarement.


---------------
Si vous ouvrez un sujet merci de ne pas le "laisser mourir" subitement et de le marquer comme "résolu" le cas échéant!
n°404060
froggycorp
Posté le 30-05-2023 à 21:37:03  profilanswer
 

Je ne saurais plus dire pour arduino, j'y ai peu utilisé les interruptions.

 

Néanmoins il y a un problème de conception, dans une interruption, tu ne mets qu'un boolean et si tu veux vraiment être propre, tu désactives l'interruption dans l'interruption.
Cela permet de conserver le CPU pour le programme courant et cela évite le cas de figure décrit par rat.
Qui plus est, toutes les variables des interruptions doivent être en volatile (accès immédiat et changement possible en cours de scripts).

 

Là, mettons que tu ais des micro coupures sur les 2 boutons, t es pas dans la merde ;)

 

---------

 

Je suis fainéant et j'ai pas envie de réécrire ton code, mais en gros, dans evenement_start() et evenement_reset(), tu ne mets que un truc genre "status_evenement_start_nommage_de_variable = true;cli();" (le cli est peut etre un peu trop trash mais faut ce qu'il faut ma bonne dame)
Et dans le loop, tu test si status_evenement_start_nommage_de_variable.
Si oui, tu fais tes actions puis tu relances l'interruption.

 

Si tu as des micro contacts, tu peux rajouter un petit delay();

 

----------

 

Sinon tu fais un compteur de bouton, donc dans l'interruption, tu fais juste un status_evenement_start ++; et tu remets à 0 dans ta boucle. Tu sauras déjà si ton bouton lance plusieurs fois l'INT ou pas

 

-------------

 

Ton utilisation des for "fonctionnent" mais sont conceptuellement faux. En faite quand i = 0 et que tu fais i--, i = 255, d'où l'arrêt.

Message cité 1 fois
Message édité par froggycorp le 30-05-2023 à 21:48:12
n°404062
rat de com​bat
attention rongeur méchant!
Posté le 30-05-2023 à 21:44:18  profilanswer
 

froggycorp a écrit :

tu désactives l'interruption dans l'interruption

Attention, surtout pas pour les AVR, car c'est automatique! (Quand le µC exécute une INT il va désactiver le drapeau "I" dans le SREG et quand l'INT est terminée la dernière instruction "reti" mise par le compilateur va faire revenir le processeur là où il était ET réactiver les INT.)

 

EDIT:

Citation :

Qui plus est, toutes les variables des interruptions doivent être en volatile (accès immédiat et changement possible en cours de scripts).

et en atomic access pour les vars > 8 bits.


Message édité par rat de combat le 30-05-2023 à 21:45:22

---------------
Si vous ouvrez un sujet merci de ne pas le "laisser mourir" subitement et de le marquer comme "résolu" le cas échéant!
n°404063
froggycorp
Posté le 30-05-2023 à 21:51:31  profilanswer
 

Le but c'est de désactiver l'INT jusqu'à ce qu'il l'a traite dans le loop pour éviter qu'elle ne soit activer plusieurs fois avant traitement ;) Dans son cas de figure (ancien, encore une fois ...), cela n'a pas d'intérêt de compter le nombre de micro contact.
Je concède qu'on peut juster désactiver la dite interruption ^^


Aller à :
Ajouter une réponse
 

Sujets relatifs
Arduino Frein à main et pédalier[DIY] Chronomètre Géant CD4543/ULN2003/Arduino
arduinoPolargraph + arduino
Recycler alim pc ? 5/7/12V pour rpi3, arduino, pompe etc..Conseils pour un nano PC avec un but spécifique
shield relais arduinocontroler un bandeau led rgb arduino et soft windows
Probleme Robot Shield V2 Arduino UNOaide arduino
Plus de sujets relatifs à : Arduino nano every vs copie BUG


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR