probleme pour mettre 3 sept-segment avec une arduino nano

hello world,

voila j'ai un problème je doit absolument afficher des nombres a centaine (reçu par le serial) en 7seg mais avec une seul arduino (pas de méga ca doit être petit) j'ai eu l'idée de faire comme beaucoup de monde allumer le 7seg-1 afficher le nombre qui va bien quelque ms on allume le deuxième on affiche la dizaine sur le 7seg-2 et ainsi de suite mais la j'ai beau faire ce que je veux mon code ne fonctionne pas quand je veux afficher des nombre supérieur a 99 il m'affiche n'importre quoi et quand c'est un nombre en dessou de 100 il n'y a pas de problème ... j'ai supprimer les delay et ca ne marche toujours pas. voila que je m’arrache les cheveux depuis 2 semaines

/*
   _______
  |       A   |
F|            |B
  |______|
  |      G    |
E|            |C
  |______| 
         D
      
A a la pin 3
B a la pin 4
C a la pin 5
D a la pin 6
E a la pin 7
F a la pin 8
G a la pin 9
*/

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define f 7
#define G 8

#define alim_1 11
#define alim_2 12
#define alim_3 13

char afficheur;
char data[3];
unsigned int nombre;

void setup()
{
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(G, OUTPUT);
  
  pinMode(alim_1, OUTPUT);
  pinMode(alim_2, OUTPUT);
  pinMode(alim_3, OUTPUT);
  
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(G, HIGH);
  
  digitalWrite(alim_1, LOW);
  digitalWrite(alim_2, LOW);
  digitalWrite(alim_3, LOW);
  
  Serial.begin(9600);
}
void loop()
{
    if (Serial.available() == 3)
    {
        Serial.readBytes(data, 3);
        nombre = atoi(data);
    } 
    afficher(nombre);    
}
void afficher(int chrono)
{
  int unite, dizaine, centaine;
  if (chrono >= 100)
  {
    centaine =  chrono / 100;    
  }
  dizaine = chrono - (centaine * 100);
  dizaine = dizaine / 10;
  unite = chrono - (dizaine * 10) - (centaine * 100);
  
  afficheur = (millis() % 15)/5;
  
  if(afficheur = 0)
  {  
    digitalWrite(alim_1, HIGH);
    digitalWrite(alim_2, LOW);
    digitalWrite(alim_3, LOW);
    printchiffre(centaine);
  }
  
  if (afficheur = 1)
  {
    digitalWrite(alim_1, LOW);
    digitalWrite(alim_2, HIGH);
    digitalWrite(alim_3, LOW);
    printchiffre(dizaine);
  }
    
  if (afficheur = 2)
  {
    digitalWrite(alim_1, LOW);
    digitalWrite(alim_2, LOW);
    digitalWrite(alim_3, HIGH);
    printchiffre(unite);
  }
}

void printchiffre(char chiffre)
{
  switch(chiffre)
  {
    case 0:
    
    digitalWrite(A, LOW);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, LOW);
    digitalWrite(E, LOW);
    digitalWrite(f, LOW);
    digitalWrite(G, HIGH);
    break;
    
    case 1:
    digitalWrite(A, HIGH);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, HIGH);
    digitalWrite(E, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(G, HIGH); 
    break;
    
    case 2:
    digitalWrite(A, LOW);
    digitalWrite(B, LOW);
    digitalWrite(C, HIGH);
    digitalWrite(D, LOW);
    digitalWrite(E, LOW);
    digitalWrite(f, HIGH);
    digitalWrite(G, LOW);
    break;
    
    case 3:
    digitalWrite(A, LOW);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, LOW);
    digitalWrite(E, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(G, LOW);
    break;
    
    case 4:
    digitalWrite(A, HIGH);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, HIGH);
    digitalWrite(E, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(G, LOW);
    break;
    
    case 5:
    digitalWrite(A, LOW);
    digitalWrite(B, HIGH);
    digitalWrite(C, LOW);
    digitalWrite(D, LOW);
    digitalWrite(E, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(G, LOW);
    break;
    
    case 6:
    digitalWrite(A, LOW);
    digitalWrite(B, HIGH);
    digitalWrite(C, LOW);
    digitalWrite(D, LOW);
    digitalWrite(E, LOW);
    digitalWrite(f, LOW);
    digitalWrite(G, LOW);
    break;
    
    case 7:
    digitalWrite(A, LOW);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, HIGH);
    digitalWrite(E, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(G, HIGH);
    break;
    
    case 8:
    digitalWrite(A, LOW);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, LOW);
    digitalWrite(E, LOW);
    digitalWrite(f, LOW);
    digitalWrite(G, LOW);
    break;
    
    case 9:
    digitalWrite(A, LOW);
    digitalWrite(B, LOW);
    digitalWrite(C, LOW);
    digitalWrite(D, LOW);
    digitalWrite(E, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(G, LOW);
    break;
  }
}

merci d'avance de votre aide ivanutsu

Bonjour Ivan,

Je dirais quelques erreurs de codage et un peu de mauvaise stratégie

  1. Tu stockes les 3 caractères dans un tableau de 3 caractères. Ca te semble logique mais la définition d’une chaine de caractère en C est “suite de caractère terminés par le caractère nul ‘\0’”
    Pour stocker correctement une chaine de 3 caractères, il te faut 4 octets
    Et t’assurer que le 4eme est bien à ‘\0’
    Sinon la fonction atoi() ne sait pas quand se termine ta chaine de caractères et risque de faire n’importe quoi (ou de marcher par hasard)

→ change data pour un tableau de 4 caractères
→ Fait suivre le readbytes par data[3] = ‘\0’;

  1. Réception série : tu suppose que tu va recevoir systématiquement 3 caractères pour chaque valeur.
    Est-tu sur à 100% que celui qui fournit les valeurs fournit toujours 3 caractères ? Que 3 est fournit sous la forme “003” et non pas “3” tout court ?
    Il serait mieux de considérer une transmission de nombres normaux, sans forcement être précédés de 0 et terminé par un retour chariot

Par exemple :

char data[8]; // je prend un peu de marge mais j'ai besoin de 3 chiffres + CR + LF + '\0' = 6 caractères

void loop()
{
    if ( Serial.available()  ) // peut importe combien. s'il y en a un, on est sur qu'il va y avoir la suite
    {
        // on lit un max de 7 caractères mais on s'arrête si on trouve le retour chariot avant
        byte count = Serial.readBytesUntil( '\n', data, 7 );
        // on s'assure de terminer la chaine par '\0' pour que atoi() fonctionne bien
        data[count] = '\0';
        // conversion ASCII vers nombre
        nombre = atoi(data);
    }
    afficher(nombre);    
}

L’emetteur doit envoyer le nombre suivit d’un retour chariot. L’équivalent de Serial.println().
Ca marche qu’il y ait des 0 devant ou pas : ca marche avec “3\n” comme avec “003\n”.

  1. Dans la fonction afficher() tu écris :
 if (chrono >= 100)
  {
    centaine =  chrono / 100;    
  }

Sauf que ton code ne définit pas la valeur de centaine si chrono est < 100.
→ Il faut un else à ton if sinon to printchiffre(centaine) va afficher n’importe quoi
Si tu veux pouvoir afficher les nombre sans 0 devant, je te suggère par exemple de mettre

  if (chrono >= 100)
    centaine =  chrono / 100;    
  else
    centaine = -1; // signifie 0 a ne pas afficher

et dans la fonction printchiffre() de faire en sorte de n’allumer aucun segment si la valeur est négative (tous les segments à HIGH)
Tu peux le faire par un default: à la fin de ton case

.....
default:
    digitalWrite(A, HIGH);
    digitalWrite(B, HIGH);
    digitalWrite(C, HIGH);
    digitalWrite(D, HIGH);
    digitalWrite(E, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(G, HIGH);
}

PS: est-ce normal que f soit en minuscule ?
Ah oui, probablement un problème de conflit avec la macro F() qui existe déjà
Eventuellement, tu pourrais les appelle SEG_A, SEG_B pour Segment A, …
Des macros sur une seule lettre c’est pas terrible, ca peut créer des problèmes car le préprocesseur C peut remplacer toutes les lettres concernées brutalement.

  1. la logique de ton code n’est pas parfaite. Tu ne devrais calcule centaine, dizaine et unité qu’une seule fois quand la valeur change.
    De même là tu met à jour en permanence les broches alors que tu pourrais te contenter de mettre à jour que toute les 5 ms.

j’espère que cela va t’aider.
A+

je vais tester cela j'ai effectivement compris pas mal et j’espère que je vais pouvoir apprendre de ces erreur ^^

encore merci ivanutsu

je ne connaissait pas la fonction default: ... faut il aussi mettre un break; a la fin ?

non, si tu le mets en dernier pas besoin