[Demande d'aide] Gérer afficheur 7segments 4 digits avec clavier

Bonjour je suis en train de rréalise un montage qui est composé d'un clavier

et d'un afficheur 4 digits

voici le câblage

voici le code pour afficher des chiffres sur mes 4 digits; il marche

#include "SevSeg.h"
 
//Create an instance of the object.
SevSeg sevseg;
int nombre = 0;
void setup() {
  // Set up pins
  // Arguments : 
  // First 0 is for common cathode
  // Following 0 to 11 numbers are for Arduino pins
  // connected to display in the following order
  // 1,2,3,4,A,B,C,D,E,F,G,DP
  sevseg.Begin(0,0,1,2,3,4,5,6,7,8,9,10,11);
}
 
void loop() {   
  nombre = 1234;
  // Prepare number to display, and dot position 
  // (0 to 3, other number means no dot)  
  sevseg.NewNum(nombre,0);
  // Display number
  sevseg.PrintOutput();  
}

  // To maintain display with this wiring, 
  // we are forced to loop over those commands rapidly

par contre je ne sais pas comment gérer le clavier j'ai essayé avec la librairie <SevSeg.h> mais je n'y arrive pas.

Le but du programme:

je souhaiterais que chaque chiffre taper sur le clavier s'affiche sur l'écran... pour au final obtenir le mème effet qu'un micro-onde et une fois le chiffre (minutes) saisie et appuyé sur la touche D (départ) l'afficheur décrémente la valeur de l'afficheur

Merci pour votre aide

pour votre clavier Membrane vous pouvez utiliser la librairie Keypad

il y a des exemples fournis pour comprendre comment gérer le clavier

Merci, depuis ce matin j'essaie la librairie keypad;
j'arrive a afficher sur le moniteur série le bon chiffre par contre comment faire pour afficher le chiffre lue sur mon ecran 4digits?

PS:J'arrive a créer un compte a rebours sur mon écran, avec le code suivant mais je n'arrive pas a assemblé les deux pour que mon montage régisse comme celui d'un micro onde...

code pour l'afficheur

/*Written by Dean Reading, 2012.  deanreading@hotmail.com
 
 This example is a centi-second counter to demonstrate the
 use of my SevSeg library.
 */

#include "SevSeg.h"

//Create an instance of the object.
SevSeg sevseg;

//Create global variables
unsigned long timer;
int nombre=500;

void setup() {
  //I am using a common cathode display, with the digit pins connected
  sevseg.Begin(0,0,1,2,3,4,5,6,7,8,9,10,11);
  //Set the desired brightness (0 to 100);
  sevseg.Brightness(90);

  timer=millis();
}

void loop() {
  //Produce an output on the display
  sevseg.PrintOutput();

  //Check if 10ms has elapsed
  unsigned long mils=millis();
  if   (mils-timer>=100) {
    timer=mils;
    nombre--;
    if (nombre==0) { // Reset to 0 after counting for 100 seconds.
      nombre=0;
    }
    //Update the number to be displayed, with a decimal
    //place in the correct position.
    sevseg.NewNum(nombre,(byte) 1);
  }
}

code pour le clavier

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
};
byte rowPins[ROWS] = {39, 41, 43, 44}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {47, 49, 51, 53}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.println(customKey);
  }
}

montrez nous au moins comment vous avez essayé d'intégrer les deux..

Ça ne marche pas, je ne suis pas assez fort en programmation alors j’essaie d'assemblé des programmes entre eux. Pourtant ça ne doit pas être très compliqué.
Si une âme charitable peut m'aider: je souhaite aevc mon montage (clavier + afficheur 4digits) reproduire l'affichage d'un micro onde. J'ai fait un micro onde en bois pour ma fille et je veux qu'elle puisse faire comme les grande cad saisir une valeur avec le clavier et quand appuyant sur la touche "d" lancer le décompte...

/*Written by Dean Reading, 2012.  deanreading@hotmail.com
 
 This example is a centi-second counter to demonstrate the
 use of my SevSeg library.
 */

#include "SevSeg.h"
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
};

byte rowPins[ROWS] = {39, 41, 43, 44}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {47, 49, 51, 53}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


boolean blink = false;



//Create an instance of the object.
SevSeg sevseg;

//Create global variables
unsigned long timer;
int nombre=0;

void setup() {

  Serial.begin(9600);
    
   
  
  //I am using a common cathode display, with the digit pins connected
  sevseg.Begin(0,0,1,2,3,4,5,6,7,8,9,10,11);
  //Set the desired brightness (0 to 100);
  sevseg.Brightness(90);
  timer=millis();
}

void loop() {
  //Produce an output on the display
  sevseg.PrintOutput();

char key = keypad.getKey();

nombre= key;
  //Check if 10ms has elapsed
  unsigned long mils=millis();
  if   (mils-timer>=100) {
    timer=mils;
    nombre--;
    if (nombre==0) { // arrete le decomptage
      nombre=0;
    }
    //Update the number to be displayed, with a decimal
    //place in the correct position.
    sevseg.NewNum(nombre,(byte) 1);
  }
}

J'ai pas d'afficheur 7 segments sous la main (enfin, la flemme de mettre tous les fils :slight_smile: ) mais voici un petit programme qui devrait vous aider

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = { 34, 36, 38, 40 };
byte colPins[COLS] = {41, 39, 37, 35};

Keypad membraneKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

boolean affichageModifie;
unsigned long duree = 0;
unsigned long chrono;

enum {REPOS, CUISSON} etat;

void setup() {
  Serial.begin(115200);
  etat = REPOS;
}

void lireClavier()
{
  affichageModifie = false;
  char entry = membraneKeypad.getKey();
  if (entry != NO_KEY) {
    // une touche du clavier a été appuyée

    if (etat != REPOS) { // si on était en train de décompter on arrête
      etat = REPOS;
      duree = 0; // et on remet à 0
    }

    if ((entry >= '0') && (entry <= '9')) { // si c'est un chiffre
      affichageModifie = true;
      duree = 10 * duree + entry - '0';
      if (duree > 9999) duree -= (duree / 10000ul) * 10000ul; // on a dépassé les 4 chiffres, on conserve les 4 derniers
    } else if (entry == 'D') { // on déclenche le compte à rebours
      etat = CUISSON;
      chrono = millis();
    } else { // N'importe quelle autre touche efface l'écran et remet à 0
      affichageModifie = true;
      duree = 0;
    }
  }
}


void loop() {

  lireClavier(); // gestion des évènements

  if (etat == CUISSON) {
    if (millis() - chrono >= 1000) {
      affichageModifie = true;
      chrono += 1000ul;
      duree--;
      if (duree == 0)  {
        etat = REPOS;
        Serial.println(F("C'EST CUIT - DING DONG")); // si vous avez un buzzer, faites le sonner au lieu de cette ligne
      }
    }
  }

  if (affichageModifie) { 
    Serial.println(duree); // c'est ici qu'il faut demander à votre afficheur 7 segments d'afficher
    affichageModifie = false;
  }
}

--> Adaptez les N° de pin pour le clavier à ce que vous avez

Compilez et charger le code dans votre arduino. Ouvrez la console série à 115200 bauds

le clavier maintenant vous sert à rentrer un nombre à 4 chiffres (si vous en tapez plus il ne conserve que les 4 derniers entrés) si vous tapez autre chose qu'un chiffre ou D, ça remet à 0 et quand vous appuyez sur D, le Décompte commence.

Arrivé à 0 l'affichage vous le dira. Si vous appuyez sur le clavier en cours de décompte, ça arrête et remet à 0

--> ce qu'il vous reste à faire:

  • changez le Serial.println(duree); par une demande d'affichage sur votre afficheur 7 segments (je crois que la librairie sait directement afficher un nombre donc ce ne doit pas être très compliqué :slight_smile: )

  • ajouter un buzzer à votre montage et utilisez tone() pour faire un bruit au lieu d'afficher C'EST CUIT - DING DONG

  • le nombre affiché n'est pas tout à fait comme un vrai micro-onde, ce n'est pas minute et secondes, c'est juste des secondes. je vous laisse modifier le code si vous souhaitez le gérer de cette façon

voilà - j'ai tapé cela un peu au kilomètre mais ça devrait fonctionner

Un grand merci à toi J-M-L, je viens de prendre connaissance de ta réponse. Je l'essai ce soir en rentrant à la maison. J'ai essayé de comprendre le programme, ça va j'arrive à peu près à comprendre par contre j'étais incapable de fournir un tel code.
Merci je te tiens informé et promis je te poste une photo du montage une fois fini.

Salut J-M-L, je viens de tester ton programme, il me convient bien dans le principe; j'ai rajouter deux lignes pour afficher le résultat sur mon afficheur, et le problème c'est que les chiffres scintillent à chaque fois que je tape un chiffre puis s’éteint jusqu’à se que je tape un nouveau chiffre... Et lorsque je déclenche le décompte les chiffre s'affiche puis s'efface toute les seconde en scintillant...
Peux tu me dire si ça vient de moi ou de ton programme?
En tout cas merci une fois ce problème résolu je serais comblé :slight_smile:

voici le code et les deux lignes rajouté:
sevseg.NewNum( duree,0);
sevseg.PrintOutput();

#include <SevSeg.h>

#include <Keypad.h>


const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = { 39, 41, 43, 45 };
byte colPins[COLS] = {47, 49, 51, 53};

Keypad membraneKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

boolean affichageModifie;
unsigned long duree = 0;
unsigned long chrono;

enum {REPOS, CUISSON} etat;

SevSeg sevseg;


void setup() {
  Serial.begin(115200);
 sevseg.Begin(0,0,1,2,3,4,5,6,7,8,9,10,11);
  etat = REPOS;
}

void lireClavier()
{
  affichageModifie = false;
  char entry = membraneKeypad.getKey();
  if (entry != NO_KEY) {
    // une touche du clavier a été appuyée

    if (etat != REPOS) { // si on était en train de décompter on arrête
      etat = REPOS;
      duree = 0; // et on remet à 0
    }

    if ((entry >= '0') && (entry <= '9')) { // si c'est un chiffre
      affichageModifie = true;
      duree = 10 * duree + entry - '0';
      if (duree > 9999) duree -= (duree / 10000ul) * 10000ul; // on a dépassé les 4 chiffres, on conserve les 4 derniers
    } else if (entry == 'D') { // on déclenche le compte à rebours
      etat = CUISSON;
      chrono = millis();
    } else { // N'importe quelle autre touche efface l'écran et remet à 0
      affichageModifie = true;
      duree = 0;
    }
  }
}


void loop() {

  lireClavier(); // gestion des évènements

  if (etat == CUISSON) {
    if (millis() - chrono >= 1000) {
      affichageModifie = true;
      chrono += 1000ul;
      duree--;
      if (duree == 0)  {
        etat = REPOS;
        Serial.println(F("C'EST CUIT - DING DONG")); // si vous avez un buzzer, faites le sonner au lieu de cette ligne
      }
    }
  }

  if (affichageModifie) {
    Serial.println(duree); // c'est ici qu'il faut demander à votre afficheur 7 segments d'afficher
sevseg.NewNum( duree,0);
sevseg.PrintOutput();
    affichageModifie = false;
  }
}

Bonjour,

sevseg.PrintOutput(); doit être appelé suffisamment souvent pour rafraîchir l'affichage. Sors le de la condition if (affichageModifie) { et mets le pas exemple en dessous.

oui il faut mettre sevseg.PrintOutput(); par exemple juste au début de la boucle comme ça il est appelé souvent - la librairie joue sur la persistance rétinienne pour l'affichage

Un grand merci à vous!!!
Effectivement ça marche au top maintenant; par contre j'ai un petit souci:

Sur mon moniteur série j'ai bien les 4 derniers chiffres qui s'affiche mais sur mon afficheur j'ai que les deux premiers digits qui fonctionne. Pourtant j'ai testé avec un petit programme et j'arrive bien a écrire sur les 4 digits!!! bizarre

ps: peux ton faire apparaitre un zero a mise sous tension avant la premier saisie?

programme test 4 digits qui marche

#include "SevSeg.h"
 
//Create an instance of the object.
SevSeg sevseg;
int nombre = 0;
void setup() {
  // Set up pins
  // Arguments : 
  // First 0 is for common cathode
  // Following 0 to 11 numbers are for Arduino pins
  // connected to display in the following order
  // 1,2,3,4,A,B,C,D,E,F,G,DP
  sevseg.Begin(0,0,1,2,3,4,5,6,7,8,9,10,11);
}
 
void loop() {   
  nombre = 1230;
  // Prepare number to display, and dot position 
  // (0 to 3, other number means no dot)  
  sevseg.NewNum(nombre,0);
  // Display number
  sevseg.PrintOutput();  
}

  // To maintain display with this wiring, 
  // we are forced to loop over those commands rapidly

ps: peux ton faire apparaitre un zero a mise sous tension avant la premier saisie?

mettez le dans le setup() ou initialiser affichageModifie à true, comme ça il fait un affichage et au début durée vaut zéro

pour le problème d'affichage c'est peut être parce que j'utilise un unsigned long et pas un int

essayez cela à la fin de la boucle

if (affichageModifie) {
    Serial.println(duree); // c'est ici qu'il faut demander à votre afficheur 7 segments d'afficher
    sevseg.NewNum( (int) duree,0);
    sevseg.PrintOutput();
    affichageModifie = false;
  }

Je viens de tester J-M-L
alors c'est OK pour le zéro du démarrage merci

void setup() {
  Serial.begin(115200);
  sevseg.Begin(0,0,1,2,3,4,5,6,7,8,9,10,11);
  etat = REPOS;
  affichageModifie = true;
  sevseg.NewNum( 0,(byte)0);
  sevseg.PrintOutput();
  affichageModifie = false;
   //monMoteur.setSpeed(9);
}

Par contre j'ai changé le unsigned par int ça change rien et le remplacement de la dernière parti du code fait pire que mieux.
Pas grave au pire je vais mettre que deux digit c'est déjà beaucoup 99secondes lol

Tant que j'y suis j'ose profiter de votre bonté; je souhaiterais faire tourner un moteur pap avec la libraire stepper lorsqu'on appuie sur "D" et qu'il s’arrête lorsqu'on arrive à zéro.

Je me répète mais encore merci sans toi je n'aurais jamais réussi et en+ j’apprends car j’essaie de comprendre ton code...

pour le zéro du démarrage L'un ou l'autre suffit - pas besoin des 2 (c'est ceinture bretelle là :slight_smile: )

Conservez le unsigned long mais transformez en int à la fin juste pour l'affichage comme proposé

sevseg.NewNum([color=red] (int)[/color] duree,0);

Vous êtes bien avec une mega ? Il n'y a pas des fils qui vont sur les pins 0 et 1 ?

Pour le moteur vous avez quel équipement ?

Bonjour J-M-L, pour mon soucis de insigned transformé en int j'ai l'impression que le décompte passe en négatif et ne s'arrête pas à zéro? Je revérifie ce soir.
Oui j'ai une Mega et effectivement j'ai l'afficheur qui est branché sur le 0 et 1
sevseg.Begin(0,0,1,etc), cela pose problème? J'essaie de le décaler ce soir.

Pour le moteur, c'est un28BYJ-48 5DC couplé à une carte ULN2003APG

Oui c'est un problème - les pins 0 et 1 c'est le port série utilisé par vos Serial.print - donc il faut soit enlever tout ce qui touche Serial soit bouger ces fils

Il faut conserver le type long : sur un int signé on ne peut pas aller au delà de 32767 - disons que vous ayez déjà tapé 5432 et quand vous tapez un 5eme chifffre - disons 1 je - construis d'abord le chiffre 54321 qui est au delà de 32767 et donc durée n'est plus cohérent et peut passer en négatif - alors que sur un long ça rentre sans problème - ensuite je regarde si c'est plus de 9999 (4 digits) et si c'est le cas je fais un peu de maths pour garder les 4 derniers chiffres tapés

Donc il faut un long pour tous les calculs mais seulement lors de l'affichage rebasculer sur un int

Ok je regarde ça ce soir en rentrant... Merci

Je vais essayer de me débrouiller/bidouiller pour faire fonctionner mon moteur de plateau micro-onde...
Si j'ai des soucis je te demande mais je voudrais essayer par moi même avant de demander ton aide.
MERCI

Pour le moteur il suffit de lancer l'ordre de tourner au moment où je passe l'état au mode CUISSON (après etat = CUISSON;) et l'arrêter à chaque fois que je passe en mode REPOS (après etat = REPOS;)

Donc si vous avez un bout de code dans le setup() qui configure le moteur il ne reste plus qu'à l'activer et arrêter en rajoutant une ligne adaptée à chaque fois que l'état change

Attention - connecter un moteur ne se fait pas en branchant directement le moteur sur les pins !

Lisez le tuto sur Le moteur à courant continu (au moins toute la partie après 'Alimenter un moteur')

Je passe par un pont en h et une carte SBT0811 donc pour le câblage ça va le faire normalement. J'ai déjà par le passé fait un bout de programme pour faire tourner ce genre de moteur, par contre j'étais obligé de lui donner le nbre d'impulsio. Je ne sais pas lui dire marche tant que je ne te dis pas stop en gros.

Ah c'est un stepper (moteur pas à pas) donc pas un moteur tout bête

dans ce cas il vous faut lire en plus le tuto [ Arduino 603] A petits pas, le moteur pas-à-pas

La librairie Stepper ne fonctionne que pour les moteurs unipolaire et bipolaire - je suppose que c'est ce que vous avez.

Vous verrez que la fonction step([color=blue]x[/color]) est bloquante. Cela signifie quelle agit comme un délai. Tant que le moteur n’a pas fait les [color=blue]x[/color] pas demandés, le reste du programme est en attente. On ne peut donc pas utiliser cette fonction en lui disant de faire 3000 steps sinon le décompte et le clavier ne fonctionneront plus

L'idée serait de faire comme pour votre raffraîchissage des LEDs, faire avancer d'un pas de temps en temps le moteur si vous êtes en mode CUISSON. Pour cela en début de boucle vous pourriez faire un truc du genre

si état est CUISSON alors moteur.step(1);

ce sera bloquant mais 1 step se fait très vite et donc pas gênant - mais dans ce cas le moteur va tourner à la vitesse de la loop (en mode cuisson, à chaque tour de loop() on fait 1 step). ce ne sera sans doute pas adapté et il faudra donc introduire une gestion du temps, un peu comme je le fais pour le décompte de la durée - vous allez mesurer si vous êtes en mode cuisson et s'il s'est écoulé plus de n millisecondes depuis la dernière commande pour faire 1 pas. ainsi vous règlerez la vitesse de votre plateau

je vous laisse coder cela - soumettez votre code ensuite :slight_smile: on vous dira si c'est bon !