Afficheur 7 segments 4 digits, segments qui reste mystérieusement allumé . . .

Bonjour à tous,

Dans le cadre de mon cours, je dois afficher en utilisant des tableaux et des bibliothèques un compteur et un décompteur sur un afficheur.
le soucis est que mon segment 0 reste toujours allumé, donc mon 1 est un 7 et mon 4 est un 9 :frowning:

J’ai beau retourner le code dans tout les sens, je ne vois pas le soucis, ce n’est pas un problème hardware parce que j’arrive à éteindre le segment si je change mon programme . . .

  int Digit1=13;
  int Segments[8] = {2, 3, 4, 5, 6, 7, 8, 9};
  int compte;    
  void setup() {     
   pinMode(Digit1, OUTPUT);   
   digitalWrite(Digit1, 1);  
   for(int i=-1; i < 8; i++)   
   pinMode(Segments[i], OUTPUT);   
  }   
 void loop() {      
   for(int compte=0; compte<9; compte++)            
    if(compte < 1)//0
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 0);  
   digitalWrite(Segments[5], 0);      
   digitalWrite(Segments[6], 1);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   if (compte>1 && compte<2)  //1
   digitalWrite(Segments[0], 1);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 1);  
   digitalWrite(Segments[4], 1);  
   digitalWrite(Segments[5], 1);      
   digitalWrite(Segments[6], 1);   
   digitalWrite(Segments[7], 1);
   delay(1000);
      if (compte>2 && compte<3)//2
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 1);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 0);  
   digitalWrite(Segments[5], 1);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000);
     if (compte>3 && compte<4) //3
       
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 1);  
   digitalWrite(Segments[5], 1);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   if (compte>4 && compte<5)     //4
   digitalWrite(Segments[0], 1);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 1);  
   digitalWrite(Segments[4], 1);  
   digitalWrite(Segments[5], 0);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   if (compte>5 && compte<6)       //5
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 1);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 1);  
   digitalWrite(Segments[5], 0);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000); 
   if (compte>6 && compte<7)  //6
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 1);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 0);  
   digitalWrite(Segments[5], 0);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   if (compte>7 && compte<8)        //7
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 1);  
   digitalWrite(Segments[4], 1);  
   digitalWrite(Segments[5], 1);      
   digitalWrite(Segments[6], 1);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   if (compte>8 && compte<9)       //8
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 0);  
   digitalWrite(Segments[5], 0);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   if (compte>8 && compte<9)       //9
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0);  
   digitalWrite(Segments[4], 1);  
   digitalWrite(Segments[5], 0);      
   digitalWrite(Segments[6], 0);   
   digitalWrite(Segments[7], 1);
   delay(1000);
   
   }

Il y a des erreurs, cela peut déja venir de là:

 for(int i=-1; i < 8; i++) pinMode(Segments[i], OUTPUT);

Pour parcourir de 0 à 7, c’est:

 for(int i=0; i < 8; i++) pinMode(Segments[i], OUTPUT);

 if (compte>1 && compte<2)  //1

Il n’existe aucun entier entre 1 et 2 exclu, Je pense que tu voulais dire

 if (compte>=1 && compte<2)  //1

1 est inclus, 2 est exclus. Mais ce qu’il vaut mpeux faire c’est:

 if (compte==1)  //1

    if(compte < 1)//0
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0); 
   digitalWrite(Segments[4], 0); 
   digitalWrite(Segments[5], 0);     
   digitalWrite(Segments[6], 1);   
   digitalWrite(Segments[7], 1);

La condition ne porte que sur l’instruction qui suit le if. Comme il est toujours faux le segment 0 sera toujours allumé.
Si on veut que la condition porte sur toutes les lignes, il faut mettre des accolades:

    if(compte < 1)//0
{
   digitalWrite(Segments[0], 0);   
   digitalWrite(Segments[1], 0);
   digitalWrite(Segments[2], 0);   
   digitalWrite(Segments[3], 0); 
   digitalWrite(Segments[4], 0); 
   digitalWrite(Segments[5], 0);     
   digitalWrite(Segments[6], 1);   
   digitalWrite(Segments[7], 1);
}

Je viens de modifier le programme selon vos remarques, tout marche au poil :smiley:
Un grand merci à toi :slight_smile:

OK.

Il peut aussi rester à simplifier l’écriture, par exemple stocker l’information dans un seul octet pour un chiffre

uint8_t chiffres[10] = {0b11000000, 0b11111001,.....(a compléter)

le premier entier est pour le chiffre 0, le bit0 de poids faible à droite c’est pour le segment 0, celui d’après vers sa gauche pour le segment 1…
Pour afficher un chiffre:
Mettre la macro avant le setup par exemple:

#define testbit(data,bitno) ((data>>bitno)&1)

Puis pour afficher le chiffre N

for (uint8_t i=0; i<8, i++) digitalWrite(Segments[i], testbit(chiffre[N],i);

explication:
Pour afficher un chiffre, on fait une boucle sur les 8 segments

  • pour i=0: chiffre[N] donne la définition du chiffre, par exemple pour N=0, c’est le nombre binaire 0b11000000, testbit(chiffre[N],i) retourne le bit n°i de chiffre[N], ici le bit 0 (celui de poids 20, le LSB, celui de droite), c’est à dire 0. Pour i=à cela donne digitalWrite(Segments[0], 0);
  • pour i=1 on va prendre le bit de poids 21, c’est encore 0 → digitalWrite(Segments[1], 0);
  • pour i=7 testbit(chiffre[0],7) retourne le bit N°7 (ou de poids 27), c’est 1 → digitalWrite(Segments[7], 1);

Éventuellement, on peut faire une fonction, dans laquelle on y met tout:

void affiche(uint8_t N)
{
  #define testbit(data,bitno) ((data>>bitno)&1)
  uint8_t chiffres[10] = {0b11000000, 0b11111001,.....
  for (uint8_t i=0; i<8, i++) digitalWrite(Segments[i], testbit(chiffre[N],i);
}

Pour afficher le chiffre 3, il suffit alors de faire

affiche(3);

On peut aussi développer la macro:

void affiche(uint8_t N)
{
  uint8_t chiffres[10] = {0b11000000, 0b11111001,.....
  for (uint8_t i=0; i<8, i++) digitalWrite(Segments[i], (chiffre[N]>>i)&1);
}

C'est justement dans la suite de mon TP, je dois faire appel à une bibliothèque de fonction que je devais crée, donc ton post est super super utile, tu m'as appris beaucoup :).
Par contre quand tu définis le chiffre dans ton {0b11000000, je vois à quoi correspond les 8 bits mais le 0b corresponds à quoi?

Dans l'exemple que tu as mis, le code de la fonction affiche3() est dans le même fichier? Si oui, y'a t'il moyen de le stocker, avec tout les autres nombres de 0 à 9 dans un seul fichier qui deviendrait alors une bibliothèque qui serait insérée avec un include?

J’ai hélas une erreur dans mon programme quand je le compile, j’avoue être totalement débutant en arduino, je n’ai cours que depuis 1 mois :wink:
Voici ce que j’ai fais et l’erreur :

  int Digit1=13;
  int Segments[8] = {2, 3, 4, 5, 6, 7, 8, 9};
  
 void affiche(uint8_t N)
  {
    #define testbit(data,bitno) ((data>>bitno)&1)
    uint8_t chiffres[10] = {0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001, 0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10010000}
    for (uint8_t i=0; i<8, i++) digitalWrite(Segments[i], testbit(chiffre[N],i);
  }
  
  void setup() {     
   pinMode(Digit1, OUTPUT);   
   digitalWrite(Digit1, 1);
   for(int i=0; i < 8; i++) pinMode(Segments[i], OUTPUT);
               }   
 void loop() 
 
{
  affiche(3);
}

Dans mon esprit, je pensais crée la fonction avant le setup pour qu’il la reconnaisse et ensuite l’utilisée mais je n’arrive pas à comprendre l’erreur que j’ai, je ne comprends pas également quand tu écris testbit(data,bitno) ((data>>bitno)&1)

Je comprends que tu fais un décalage avec le >> mais ça s’arrête là :smiley:

0b corresponds à quoi?

si on écrit 1000, ce n’est pas le nombre binaire 8, c’est le nombre décimal mille. Pour avoir du binaire on met 0b devant. Si on veut de l’hexadécimal, ce serait 0x
Des fois on met aussi un suffixe L pour long (32 bits) UL pour lon non signé…

Dans l’exemple que tu as mis, le code de la fonction affiche3() est dans le même fichier? Si oui, y’a t’il moyen de le stocker, avec tout les autres nombres de 0 à 9 dans un seul fichier qui deviendrait alors une bibliothèque qui serait insérée avec un include?

Bien sûr, il faut alors mettre la fonction et ce qui va avec dans un fichier trucmuche.ccp et leprototype de la fonction seul dans trucmuche.h
Si cette bibliothèque (composée de deux fichiers .cpp et .h) est dans le répertoire du projet, il faut l’appeler par
#include “trucmuche.h”
Si cette bibliothèque est dans le répertoire des librairies (genre Program Files\Arduino\libraries\trcmuche); on l’appelle en général par
#include <trucmuche.h>
Le prototype c’est comme la fonction mais avec ; à la place du corps
{

}
Mais pour ça il doit bien y avoir des tutos.
Avant de faire un bibliothèque, il faut la mettre dans le même fichier, puis après, quand cela fonctionne, on sépare. C’est beaucoup plus facile.

    uint8_t chiffres[10] = {0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001, 0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10010000}
    for (uint8_t i=0; i<8, i++) digitalWrite(Segments[i], testbit(chiffre[N],i);
  • il manque un point-virgule à la première ligne. Pour le compilateur, il en a besoin, mais on pourrait le mettre à la ligne. C’est pour cela qu’il ne dit rien. Seulement quand arrive le for, il n’est plus d’accord car il n’a pas eu son ; C’est pour cela que l’erreur est sur le for (test:8:5: error: expected ‘,’ or ‘;’ before ‘for’)
  • derrière i<8 il faut un ; pas une ,
  • il manque une ) a la fin du digitalWrite: autant de ( que de )
#define testbit(data,bitno) ((data>>bitno)&1)

Ce n'est pas de moi! je l'ai pompé! Bon. C'est une macro. Le #define indique au préprocesseur (il passe avant le compilateur) de remplacer les testbit(data,bitno) par des ((data>>bitno)&1). En fait cela revient presque à faire:
char testbit(char data,char bitno)
{
return (data>>bitno)&1;
}

Supposons que data=0b11011100, bitno=3 (bitno, c'est bit numéro)
data >>bitno va décaler data de bitno positions vers la droite; On va décaler 0b11011100 de trois positions vers la droite (cela remplit par des 0 à gauche. data >>bitno vaudra 0b00011011 Puis on fait & avec 1.& indique une opération ET logique bit à bit:
0b00011011
0b00000001

0b00000001
et cela retourne le 1 qui était en 3ème position

Cette macro retourne donc le bit de data qui est en position bitno.