Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Arduino] 74HC595 + Afficheur à segments

Problème de "fantôme"

Sujet résolu
    16 juin 2014 à 22:10:35

    Bonjour à vous ! 

    J'ai un soucis de ghosting lors de l'affichage de nombres sur l'afficheur et je n'arrive pas à trouver de solution pour le résoudre.

    En fait c'est un afficheur à 4 chiffres donc je passe par un 74HC595 pour commander les segments et 4 transistors NPN pour les 4 anodes communes.

    Sur les segments j'ai mis des résistances de 460 Ohms et aux bases de NPN des 1K ohms. 

    L'éclairage est satisfaisant et l'alternance d'allumage des différents chiffres est de 5ms. 

    Pour le moment je n'ai codé que l'affichage de deux chiffres pour faire des essais.

    Mais il se trouve que si j'affiche par exemple 21, les segment correspondant aux 2 et 1 sont affichés en inversé de façon faible (12) au lieu de rester éteints complètement. 

    Je sais pas si je me fais bien comprendre, je vous poste une photo qui rend compte du phénomène : 

    Le code en question, ça viens peut-être de là et ça peut aider pour trouver la cause : 

    #include <math.h>
    #define PIN_NTC 0
    const int chiffre1 = 2;
    const int chiffre2 = 3;
    const int chiffre3 = 4;
    const int chiffre4 = 5;
    
    //Broche connectée au ST_CP du 74HC595
    const int verrou = 11;
    //Broche connectée au SH_CP du 74HC595
    const int horloge = 12;
    //Broche connectée au DS du 74HC595
    const int data = 10;
    
    byte chiffres[10];
           
    
    double Rref = 1000.0; //Résistance de référence à 25°C
    double V_IN = 5.0; //Alimentation
    
    //information de la thermistance, coefs
    
    double A_1 = 3.354016E-3;
    double B_1 = 2.569850E-4;
    double C_1 = 2.620131E-6;
    double D_1 = 6.383091E-8;
    
    double SteinhartHart(double R)
    {
      
      double equationB1 = B_1 * log(R/Rref);
      double equationC1 = C_1 * pow(log(R/Rref), 2);
      double equationD1 = D_1 * pow(log(R/Rref), 3);
      double equation = A_1 + equationB1 + equationC1 + equationD1;
      return pow(equation, -1);
      
    }
    
    void setup()
    {
      Serial.begin(115200);
    
      pinMode(verrou, OUTPUT);
      pinMode(horloge, OUTPUT);
      pinMode(data, OUTPUT);
      
      pinMode(chiffre1, OUTPUT);
      pinMode(chiffre2, OUTPUT);
      pinMode(chiffre3, OUTPUT);
      pinMode(chiffre4, OUTPUT);
    
      
      
    chiffres[0] = 0b11111100;
    chiffres[1] = 0b01100000;
    chiffres[2] = 0b11011010;
    chiffres[3] = 0b11110010;
    chiffres[4] = 0b01100110;
    chiffres[5] = 0b10110110;
    chiffres[6] = 0b10111110;
    chiffres[7] = 0b11100000;
    chiffres[8] = 0b11111110;
    chiffres[9] = 0b11110110;
    
    }
    
    void loop()
    {
      
      
      double valeurAnalog = analogRead(PIN_NTC);
      double V = valeurAnalog / 1024 * V_IN;
      
      double Rth = (Rref * V) / (V_IN - V);
      Serial.print("Rth = ");
      Serial.print(Rth);
      
      double kelvin = SteinhartHart(Rth);
      double celsius = kelvin - 273.15;
      Serial.print("Ohm - T = ");
      Serial.print(celsius);
      Serial.print("C\n");
      
      affichage(celsius);
      
      
    
      
    }
    
    void affichage(double celsius)
    {
      int dizaine = 0;
      int unite = 0;
      
      dizaine = celsius/10;
      unite = celsius - (dizaine * 10);
      
      
        digitalWrite(chiffre1, HIGH);
        digitalWrite(verrou, LOW);
        shiftOut(data, horloge, LSBFIRST, ~chiffres[2]);
        digitalWrite(verrou, HIGH);
        delay(5);
        digitalWrite(chiffre1, LOW);
        
    
        
        digitalWrite(chiffre2, HIGH);
        digitalWrite(verrou, LOW);
        shiftOut(data, horloge, LSBFIRST, ~chiffres[1]);
        digitalWrite(verrou, HIGH);
        delay(5);
        digitalWrite(chiffre2, LOW);
    
    }
    

    Je vous remercie pour l'attention que vous m'accorderez ! :)

    • Partager sur Facebook
    • Partager sur Twitter
      17 juin 2014 à 12:08:22

      Je pense que ton problème vient du programme.

          digitalWrite(chiffre1, HIGH);
          digitalWrite(verrou, LOW);
          shiftOut(data, horloge, LSBFIRST, ~chiffres[2]);
          digitalWrite(verrou, HIGH);
          delay(5);
          digitalWrite(chiffre1, LOW);

      En passant chiffre1 à HIGH avant d'avoir positionné ton 74HC595, ton digit va donc afficher l'ancienne valeur (donc le mauvais chiffre) pendant une fraction de seconde.

      Je te propose donc de mettre chiffre1 à HIGH après avoir fait ton opération 74HC595 et non avant.

          // digitalWrite(chiffre1, HIGH); PAS ICI
          digitalWrite(verrou, LOW);
          shiftOut(data, horloge, LSBFIRST, ~chiffres[2]);
          digitalWrite(verrou, HIGH);
          digitalWrite(chiffre1, HIGH); // PLUTOT ICI
          delay(5);
          digitalWrite(chiffre1, LOW);

      Et bien sur, faire de même pour le(s) autre(s) digit(s)


      • Partager sur Facebook
      • Partager sur Twitter
        17 juin 2014 à 12:14:10

        Magnifique merci c'était exactement ça ! :)
        • Partager sur Facebook
        • Partager sur Twitter
          17 juin 2014 à 13:16:45

          Cependant j'ai un nouveau soucis, j'ai donc raccordé la thermistance pour afficher la température mais les chiffres "sautillent" lors des changements, ce n'est pas franc.

          Je vous ai pris une vidéo du phénomène : https://www.youtube.com/watch?v=9j3TwcwXx1s

          J'ai essayé différentes combinaisons de timing mais rien n'y fait, et je n'arrive pas à déterminer la cause alors j'en fais appel à vos compétences ! :)

          Merci !

          • Partager sur Facebook
          • Partager sur Twitter
            17 juin 2014 à 13:54:08

            Là, c'est tout simplement parce que tu ne filtre pas et que ton système d'alimentation n'est pas parfait.

            Supposons que la température soit exactement de 29.87°C

            Avec tes division, tu vas afficher 29.8°C.

            Vu que ton programme tourne en boucle, une fraction de seconde plus tard, il va à nouveau refaire une mesure et l'afficher.

            Sauf que cette fois, une micro perturbation sur l'alimentation ou un micro courant d'air provoque une augmentation de 0.04°C.

            Serte, 0.04°C, c'est ridicule ... sauf que additionné à 29.87, ça donne 29.91 donc ton système va afficher 29.9°C

            Voila donc comment tu te retrouve avec un chiffre qui oscille très rapidement entre 29.8 et 29.9.

            Si tu veux éviter cela, il te faut faire un filtrage.

            Par exemple, tu peux te contenter de faire une sorte de moyenne histoire que les micro variations soient gommer.

            void loop()
            {
            
              static double kelvinFiltre = 0.0;
               
              double valeurAnalog = analogRead(PIN_NTC);
              double V = valeurAnalog / 1024 * V_IN;
               
              double Rth = (Rref * V) / (V_IN - V);
              Serial.print("Rth = ");
              Serial.print(Rth);
            
              kelvinFiltre = ( ( ( kelvinFiltre * 19.0 ) + SteinhartHart(Rth) ) / 20.0 );
               
              double kelvin = kelvinFiltre ;
              double celsius = kelvin - 273.15;
              Serial.print("Ohm - T = ");
              Serial.print(celsius);
              Serial.print("C\n");
               
              affichage(celsius);
               
            }



            -
            Edité par lorrio 17 juin 2014 à 13:56:25

            • Partager sur Facebook
            • Partager sur Twitter
              17 juin 2014 à 14:02:01

              Je ne comprends pas vraiment cette ligne :

              kelvinFiltre = ( ( ( kelvinFiltre * 19.0 ) + SteinhartHart(Rth) ) / 20.0 );

              Ou plutôt les valeurs 19.0 et 20.0 ?

              Pourrais tu m'expliquer plus précisément pourquoi avoir choisie celles-ci? Merci !

              Et aussi, les coefs que j'ai pris là viennent d'une autre thermistance, ce ne sont pas exactement ceux de celle que j'utilise, comme j'imagine que les différences sont minimes j'ai pris ça pour le moment car je n'arrive pas à trouver les informations correspondantes sur la datasheet.

              http://www.gotronic.fr/pj-697.pdf

              Je vois bien page 4 des correspondances mais ce sont loin des 10^-6 et -8 des coefs que j'ai, donc j'en déduit que c'en est pas je me trompe?

              -
              Edité par CactusTribe 17 juin 2014 à 14:22:11

              • Partager sur Facebook
              • Partager sur Twitter
                17 juin 2014 à 16:24:26

                Plutôt que de me lancer dans de grand discours, je vais te donner un exemple.

                =====

                Supposons que tu mesures 25° en permanence sauf une fois sur 1000 ou tu mesures 26° pour x ou y raison.

                Avec ton code actuel, ton afficheur va donc avoir un scintillement sur 26° tous les 1000 affichage de 25°.

                C'est donc très moche ...

                =====

                Avec mon code, c'est différent :

                Après un long affichage de 25°, la variable kelvinFiltre vaudra 25°.

                Au moment de la mesure du 26°, on a donc : kelvinFiltre = ( 25° * 19 + 26° ) / 20 = 25.05°

                Du coup, mon programme va quand même afficher 25°, même si il a mesuré 26°

                Cela s'explique par le fait que la nouvelle valeur ne compte que pour 1/20ième de la valeur affichée.

                =====

                Bref, gràce à ce 19 et ce 20, la valeur affichée est une sorte de moyenne de la mesure.

                Il n'y a pas de glitch mais le système est plus lent à réagir.

                Par exemple, si la température passe brusquement de 25° à 0° (parce que tu pose un glaçon sur la CTN par exemple) :

                - avec ton code, l'afficheur va passer directement de 25° à 0.

                - avec mon code, l'afficheur va évoluer ainsi :

                ( 25 *19 + 0 ) / 20 = 23.75 => affiche 23°

                ( 23.75 * 19 + 0 ) / 20 = 22.56 => affiche 22°

                (  22.56 * 19 + 0 ) / 20 = 21.43 => affiche 21°

                ...

                Si tu trouves que le système est trop lent, tu peux changer les coefficient du genre dire que la température mesurée compte pour 1 quart (et non 1/20) :

                kelvinFiltre = ( ( ( kelvinFiltre * 3.0 ) + SteinhartHart(Rth) ) / 4.0 );

                Inversement, si tu un système très lent t'arrange, tu peux augmenter les coeff pour passer à 1 centième par exemple :

                kelvinFiltre = ( ( ( kelvinFiltre * 99.0 ) + SteinhartHart(Rth) ) / 100.0 );

                • Partager sur Facebook
                • Partager sur Twitter
                  17 juin 2014 à 16:37:33

                  Ah merci beaucoup de tes explications claires ! :)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 juillet 2014 à 0:01:50

                    Bonsoir ! 

                    Bon voilà après quelques semaines et 4h de soudures / coupures de fils voici le shield home made :D 

                    Quelques étapes lors de la fab :

                    Encore merci pour votre aide ! Ce qui est suspendu c'est la sonde haha, un peu à l'arrache j'en conviens x)

                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 janvier 2015 à 21:36:55

                      Bonsoir, je me permet de déterrer mon topic car je me trouve avec un problème semblable mais avec une légère différence qui fait que je n'arrive pas à le résoudre.

                      Donc en gros j'utilise deux 74HC595. Un pour déterminer les segments à afficher, et l'autre pour choisir la position du chiffre sur tel ou tel afficheur.

                      Pour une simplification pour le moment j'en utilise que 3 avant de cabler le reste.

                      Donc, quand mon timeDelay est à 100ms, on peut clairement voir que les étapes de l'affichage sont bien effectuées sans problème.

                      Mais sur la deuxième partie de la video j'ai mis à 5ms de delay, et là il y à des "Sautillement", certains segments s'affiches faiblement..

                      Je pense que ça viens du fait que les deux 74HC595 sont en série et que j'envois à la suite les infos de position puis de segments, mais je n'arrive pas à caractérisé mon soucis de façon plus précise... Quelqu'un vois d'où ça peut venir? 

                      Voici la video du phénomène : https://www.youtube.com/watch?v=ybk0JbbnJYQ

                      Et mon code correspondant : 

                      //Broche connectée au ST_CP du 74HC595
                      const int verrou = 11;
                      //Broche connectée au SH_CP du 74HC595
                      const int horloge = 12;
                      //Broche connectée au DS du 74HC595
                      const int data = 10;
                      
                      byte chiffres[10]; 
                      
                      void setup(){
                      	pinMode(verrou, OUTPUT);
                      	pinMode(horloge, OUTPUT);
                      	pinMode(data, OUTPUT);
                      
                      	chiffres[0] = 0b11111100;
                      	chiffres[1] = 0b01100000;
                      	chiffres[2] = 0b11011010;
                      	chiffres[3] = 0b11110010;
                      	chiffres[4] = 0b01100110;
                      	chiffres[5] = 0b10110110;
                      	chiffres[6] = 0b10111110;
                      	chiffres[7] = 0b11100000;
                      	chiffres[8] = 0b11111110;
                      	chiffres[9] = 0b11110110;
                      }
                      
                      void loop(){
                      	digit(125);
                      }
                      
                      void digit(int i){
                      
                      	int centaine = i/100;
                        int dizaine = (i - (centaine * 100)) / 10;
                        int unite = (i - (centaine * 100) - (dizaine * 10));
                        int timeDelay = 5;
                      
                      	digitalWrite(verrou, LOW);
                      	shiftOut(data, horloge, LSBFIRST, 0b00100000);
                      	shiftOut(data, horloge, LSBFIRST, chiffres[unite]);
                      	digitalWrite(verrou, HIGH);
                      	delay(timeDelay);
                      
                      	digitalWrite(verrou, LOW);
                      	shiftOut(data, horloge, LSBFIRST, 0b01000000);
                      	shiftOut(data, horloge, LSBFIRST, chiffres[dizaine]);
                      	digitalWrite(verrou, HIGH);
                      	delay(timeDelay);
                      
                      	digitalWrite(verrou, LOW);
                      	shiftOut(data, horloge, LSBFIRST, 0b10000000);
                      	shiftOut(data, horloge, LSBFIRST, chiffres[centaine]);
                      	digitalWrite(verrou, HIGH);
                      	delay(timeDelay);
                      }



                      • Partager sur Facebook
                      • Partager sur Twitter
                        23 janvier 2015 à 22:33:54

                        Les scintillements sont très probablement du à un digit qui ne s'affiche pas au bon endroit.

                        Pourtant, le code a l'air correct.

                        Il nous faudrait un schéma de ton câblage pour te dire si oui ou non, tes 74HC sont correctement câblé en série.


                        Au passage, j'ajoute aussi que tu n'as pas besoin de faire toutes ces additions, multiplications et autre pour décomposer ton nombre en digits.

                        Une division et un modulo par digit suffit.

                        int chiffre = 2345;
                        
                        int milliers  = ( ( chiffre / 1000 ) % 10 );
                        int centaines = ( ( chiffre / 100  ) % 10 );
                        int dizaines  = ( ( chiffre / 10   ) % 10 );
                        int unites    = ( ( chiffre / 1    ) % 10 );

                        Tu peux d'ailleurs mettre ça dans une boucle pour traiter les grands nombres dans un tableau.

                        Exemple :

                        int digits[10];
                        unsigned long bigNumber = 123456789uL;
                        
                        
                        int i;
                        unsigned long div = 1;
                        
                        for ( i = 0 ; i < 10 ; i++ ) {
                            digits[i] = ( ( bigNumber / mul ) % 10 );
                            div = div * 10;
                        }

                        Avec ce code, tu auras digits[0] qui contiendra les unités, digits[1] les dizaines et ainsi de suite.


                        -
                        Edité par lorrio 23 janvier 2015 à 22:42:54

                        • Partager sur Facebook
                        • Partager sur Twitter
                          23 janvier 2015 à 22:59:51

                          Apparemment ça viens de faux contact dû à la breadboard, en bougeant un peu les connexions, le problème ne se pose plus! 

                          Et effectivement je réfléchissais à une mise sous tableau en partant d'un String, car je sais pas si on peut convertir un nombre en byte en tableau de char?

                          • Partager sur Facebook
                          • Partager sur Twitter
                            24 janvier 2015 à 12:08:06

                            CactusTribe a écrit:

                            je sais pas si on peut convertir un nombre en byte en tableau de char?

                            J'avoue ne pas trop comprendre ce que tu veux faire.

                            Pourrais tu donner un exemple de ce que tu as au départ et de ce que tu veux à l'arrivée ?

                            • Partager sur Facebook
                            • Partager sur Twitter
                              24 janvier 2015 à 12:45:45

                              Par exemple pouvoir faire quelque chose comme ça : char nombre[] = 12.toByte().toCharArray()

                              Ce qui me permettrait d'obtenir la représentation sous forme de tableau pour l'affichage tout en manipulant uniquement des int dans mon code.

                              Merci de ton aide ! Je pense pouvoir y parvenir avec des conversions en String enfait.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                24 janvier 2015 à 12:57:41

                                J'avoue ne pas trop comprendre là...

                                En quoi mon code avec la boucle for ne te plait pas ?

                                Il décompose bien le nombre dans un tableau, c'est ce que tu veux non ?


                                Enfin bon, si ça ne te plais pas, tu peux utiliser la classe String qui est implicitement un tableau de char.

                                Exemple :

                                int n = 2734;
                                
                                String s(n, DEC);
                                
                                Serial.print(s[0]); // Affiche '2'
                                Serial.print(s[1]); // Affiche '7'
                                



                                -
                                Edité par lorrio 24 janvier 2015 à 13:00:53

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  24 janvier 2015 à 13:11:03

                                  Oui c'est ce que j'ai fais, j'ai pas utiliser ton code car au final le plus simple est de décomposé chaque digit par cases je trouve, donc mon code ressemble à ça : 

                                  void loop(){
                                    digit(String(i));
                                  }
                                  
                                  void digit(String nb){
                                  
                                    int timeDelay = 5;
                                  
                                    for(int i=0; i<=3; i++){
                                  	int digit = nb.charAt(i)-'0';
                                  
                                  	digitalWrite(verrou, LOW);
                                  	shiftOut(data, horloge, LSBFIRST, position[i]);
                                  	shiftOut(data, horloge, LSBFIRST, chiffres[digit]);
                                  	digitalWrite(verrou, HIGH);
                                  	delay(timeDelay);
                                    }
                                  }

                                  Par contre je connaissais pas la possibilité de faire String(n, DEC), du coup pour le binaire String(n,BIN) et c'est parfait !

                                  Bon et bien merci de ton aide ! ^^

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  [Arduino] 74HC595 + Afficheur à segments

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown