petit soucis

bonjour a tous !!!

je suis aujourd'hui sur problème qui me parait ultra bénin et vous allez rire, mais bon je ne trouve pas la solution donc je viens vers vous.
voici mon code:

#include <Keypad.h>

int i=0;
char motdepassetaper[]={'0','0','0','0'};
char motdepasse [] ={'4','3','2','1'};
int ledok = 12;
const byte ROWS = 2; 
const byte COLS = 4; 

char hexaKeys[ROWS][COLS] = {
  {'1','2','3','4'},
  {'5','6','7','8'},
                        };

byte rowPins[ROWS] = {7, 6}; 
byte colPins[COLS] = {5, 4, 3, 2}; 


Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

const byte nombrePin=4;
byte ledPin[]={8,9,10,11};

void setup(){
  Serial.begin(9600);
  for(int y =0; y<nombrePin; y++){
    pinMode (ledPin[y], OUTPUT);}
    pinMode (ledok, OUTPUT);
}
  
void loop(){
  
  char customKey = customKeypad.getKey();
  
    
[color=red] /* do{ 
    mafonction3();}
    while (i<0);*/[/color]
    
  if (customKey){
    Serial.println(customKey);
    motdepassetaper[i]=customKey;
    digitalWrite (ledPin[i],HIGH);
    i++;}
    
  
    if ( i == 4){
     
      if (memcmp(motdepasse, motdepassetaper, sizeof(motdepasse)) == 0){
        Serial.println("code bon");
         delay(10);
      mafonction2();
       i=0;
      }
      
      else{Serial.println ("mauvais code");
    mafonction();
           i=0;}
    }
    }

void mafonction(){
      delay(100);
       for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);}   
      delay(100);
       for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], HIGH);}
           delay(100);
          for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);}   
      delay(100);
       for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], HIGH);}   
          delay(100); 
         for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);}   
      delay(100);
}

void mafonction2(){
   for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);
   digitalWrite (ledok, HIGH);}
       delay(5000);
  digitalWrite (ledok , LOW);
}
  
void mafonction3(){
  for(int i=0 ;i<4 ;i++){
    digitalWrite(ledPin[i], HIGH);
      timer();}
  for(int i=4; i>-1; i--){
    digitalWrite (ledPin[i],LOW);
    timer();}
}
 void timer()
{

  unsigned long startMillis = millis();
  unsigned long currentMillis = millis();

  while ( (currentMillis - startMillis) < 30)
  {
    currentMillis = millis();

  }
}

voici le probleme:

le projet est un digicode. j'ai voulu rajouter avec des led des effets lumineux.
voila tout fonctionne très bien c'est a dire qu'a chaque appuie sur une touche du clavier une led s allume .Premier appuie = première led allumée ensuite deuxième appuie = seconde led etc jusqu’à 4.A 4 je verifie mon code et :
ou j'ai le bon code et la fonction "mafonction2"s enclenche.
ou bien j'ai le mauvais code et la fonction " mafonction" s'enclenche.
et je reviens au début de mon loop.
tout ceci fonction très bien, mais comme dit j'ai voulu rajouter un petit truc.
en fait j'ai crée une fonction "mafonction3" qui doit être active tant qu'aucune touche n a été appuyée.
une fois la première touche appuyée la led 1 s allume et la fonction "mafonction3" s arrete et ne doit recommencer qu'une fois le code vérifie et l une des 2 fonctions "mafonction" et "mafonction2" a été exécutée donc en début de loop.
en fait la fonction "mafonction3" ne s arrête jamais et du coup empêche la lecture des touches du clavier.
quelle méthode dois je utiliser car j'ai même utiliser le "switch...case"sans succès.
un détail doit m’échapper et je ne trouve pas.

merci d'avance pour vos lumière si précieuse :slight_smile:

essayez un if (i==0) mafonction3(); // tant qu'on n'a pas commencé à remplir le code on appelle la fonction3 au début de la loop()

merci beaucoup

j'avais essayé cette méthode mais le premier appuie et difficile a rentrer, il faut appuyer plusieurs fois sur une touche du clavier pour que se soit pris en compte. Ensuite pour l appuie 2 et les autres aucun soucis ça tourne impeccable.

je suis sur simulateur (tinkercad) c'est peut être à cause de ça. Je vais faire un vrai montage physique pour voir.

merci encore

je reviendrai pour confirmer

Tout dépend de la durée d’execution de mafonction3() puisque la boucle passe dedans à tous les coups tant que vous n’avez pas entré au moins un élément....

(Et comme là c’est codé avec les pieds...:slight_smile: —> relisez les tutos sur millis() )

re bonjour

après la nuit blanche sur ce problème je n ai pas trouvé la solution.
j ai juste réussi a faire en sorte que le premier appuie soit pris en compte , c'est pas mal me direz vous :slight_smile: mais maintenant les led ne se comportent plus du tout comme je le souhaite, elles restent allumer dans la fonction"mafonction3".

décidément la fonction millis est vraiment complexe et tordu à mon gout. A moins que se soit toute la structure de mon programme qui n est pas correcte.
je vais me coucher peut etre que le nuit me portera conseil a moins que l un de vous puisse m aiguiller.

merci les arduinistes

#include <Keypad.h>

unsigned long startMillis = millis();
  unsigned long currentMillis =millis();

int i=0;
char motdepassetaper[]={'0','0','0','0'};
char motdepasse [] ={'4','3','2','1'};
int ledok = 12;
const byte ROWS = 2; 
const byte COLS = 4; 

char hexaKeys[ROWS][COLS] = {
  {'1','2','3','4'},
  {'5','6','7','8'},
                        };

byte rowPins[ROWS] = {7, 6}; 
byte colPins[COLS] = {5, 4, 3, 2}; 


Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

const byte nombrePin=4;
byte ledPin[]={8,9,10,11};

void setup(){
  
  Serial.begin(9600);
  for(int y =0; y<nombrePin; y++){
    pinMode (ledPin[y], OUTPUT);}
    pinMode (ledok, OUTPUT);
}
  
void loop(){
  
  while (i==0){
    mafonction3();
    break;}

  char customKey = customKeypad.getKey();
   
  if (customKey){
    Serial.println(customKey);
    motdepassetaper[i]=customKey;
    digitalWrite (ledPin[i],HIGH);
    i++;}
  
    if ( i == 4){
     
      if (memcmp(motdepasse, motdepassetaper, sizeof(motdepasse)) == 0){
        Serial.println("code bon");
         delay(10);
      mafonction2();
       i=0;
      }
      
      else{Serial.println ("mauvais code");
    mafonction();
           i=0;}
    }
    }

void mafonction(){
      delay(100);
       for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);}   
      delay(100);
       for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], HIGH);}
           delay(100);
          for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);}   
      delay(100);
       for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], HIGH);}   
          delay(100); 
         for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);}   
      delay(100);
}

void mafonction2(){
   for(int y =0; y<nombrePin; y++){
    digitalWrite (ledPin[y], LOW);
   digitalWrite (ledok, HIGH);}
       delay(5000);
  digitalWrite (ledok , LOW);
}
  
void mafonction3(){
   
   
  for ( int i = 0; i <nombrePin ; i++)
  {

    digitalWrite( ledPin[i], HIGH );
    digitalWrite( ledPin[i], LOW );
    intelligentDelay();
  }

  for ( int i = nombrePin - 1; i >= 0; i--)
  {
    for ( int iBrowser = 0; iBrowser < nombrePin; iBrowser++ )
    {
      if ( iBrowser == (i - 1) || iBrowser == (i + 1) || iBrowser == i )
        digitalWrite( ledPin[iBrowser], HIGH );
      else
        digitalWrite( ledPin[iBrowser], LOW );
    }
    intelligentDelay();
  }

   }

void intelligentDelay()
{

  while ( (currentMillis-startMillis) < 100)
  {
    currentMillis = millis();
   
  }
}

A moins que se soit toute la structure de mon programme qui n est pas correcte.

bingo :slight_smile:

Faire

  while (i==0){
    mafonction3();
    break;}

en début de loop() c'est vraiment du grand n'importe quoi, vous étiez désespéré ou quoi ? faut réfléchir un peu et aller dormir quand ça vient pas... --> ça revient EXACTEMENT à faire if (i==0) mafonction3(); puisque vous faites break à tous les coups après avoir appelé la fonction...

Un des problèmes est dans

 void intelligentDelay()
{
  while ( (currentMillis-startMillis) < 100)
  {
    currentMillis = millis();  
  }
}

qui est tout sauf intelligent (et montre que vous n'avez pas encore compris l'usage de millis()) puisque vous ne mettez jamais à jour startMillis de toutes façons et qu'on ne sait pas trop ce que currentMillis est en entrant dans cette fonction... vous feriez un delay(100); que ce serait sans doute plus proche de votre intention dans ce code et tout aussi bloquant..

décidément la fonction millis est vraiment complexe et tordu à mon gout.

millis() est super simple, ça vous retourne comme son nom l'indique le nombre de millisecondes écoulées depuis le dernier reset de la carte... mais si vous faites un while() en attendant que millis() atteigne une certaine valeur, votre processeur est bloqué dans cette attente et ne fait RIEN D'AUTRE...

ce qui est un peu plus "compliqué" c'est de s'en servir correctement pour gérer le temps SANS bloquer votre micro-processeur en attente... sinon c'est comme delay()

--> une fois reposé, lire les tutos référencés sur la gestion du temps (tutos d'eskimon, celui sur Introduire le temps) et la programmation par machine à états (cf mon tuto éventuellement)

Je verras bien une structure de code autour d'un switch dépendant du nombre de touches tapées. Tu crées et initialises à 0 une variable byte NbTouches.

La loop ferait alors (pseudocode) :

Lire le clavier
Si touche : incrémenter NbTouches, ajouter le caractère au pass
switch NbTouches
0 : exécuter mafonction3
1 : allumer led 1
2 : allumer led 2
3 : allumer led 3
4 : allumer led 4, tester le pass
    si pass ok : exécuter mafonction2 sinon exécuter mafonction
    puis exécuter mafonction3 (ou remettre NbTouches à 0)

Est-ce que j'ai bien compris ton besoin ?

lesept:
Je verras bien une structure de code autour d'un switch dépendant du nombre de touches tapées. Tu crées et initialises à 0 une variable byte NbTouches.

La loop ferait alors (pseudocode) :

Lire le clavier

Si touche : incrémenter NbTouches, ajouter le caractère au pass
switch NbTouches
0 : exécuter mafonction3
1 : allumer led 1
2 : allumer led 2
3 : allumer led 3
4 : allumer led 4, tester le pass
    si pass ok : exécuter mafonction2 sinon exécuter mafonction
    puis exécuter mafonction3



Est-ce que j'ai bien compris ton besoin ?

ce qu'il faut surtout c'est changer mafonction3() pour qu'elle n'incorpore pas d'attente active --> elle fait un truc que si c'est le bon moment. (donc les techniques de millis())

Je ne suis pas rentré dans les fonctions car le besoin n'est pas clairement exprimé pour l'instant, mais voyant ça

    digitalWrite( ledPin[i], HIGH );
    digitalWrite( ledPin[i], LOW );
    intelligentDelay();

je me dis que ça ne sert à rien : l'allumage de la LED ne sera pas visible. Donc, cette fonction est à revoir entièrement à mon humble avis.

Que doit-elle faire exactement ?

lesept:
Je ne suis pas rentré dans les fonctions car le besoin n'est pas clairement exprimé pour l'instant, mais voyant ça

    digitalWrite( ledPin[i], HIGH );

digitalWrite( ledPin[i], LOW );
    intelligentDelay();


je me dis que ça ne sert à rien : l'allumage de la LED ne sera pas visible. Donc, cette fonction est à revoir entièrement à mon humble avis.

Que doit-elle faire exactement ?

cf le "bingo" ci dessus :slight_smile:

bonjour

le but de "mafonction3" est de créer un effet "k2000".
j allume les led une a une dans un intervalle de 100 millisecondes. puis une fois qu'elles sont toutes allumées je les éteint une a une dans le même intervalle.
quand j appuie sur un des bouton du clavier je dois sortir de ma "fonction3" et allumer la première led qui symbolise le premier appuie puis la deuxième au deuxième appuie etc ... jusqu’à la 4eme.

void mafonction3(){
  
  int y=0;
  
  if((millis() - temps)>100){
    digitalWrite (ledPin[y],HIGH);
    for( y = 0; y<nombrePin ;y++){
      }  
  temps = millis();
   }
 
  }

voici la partie qui me pose un problème.
pourquoi il n y a que la première led qui s allume?
pourquoi mon incrémentation ne se fait pas. Pourtant le delais de 100 millisecondes se fait avec l allumage de la première led, mais ensuite plus rien.
je sais il y a des erreurs mais j aimerais vraiment incrementer mon tableau toute les 100 millisecondes sans que se soit bloquant.
merci d avance :slight_smile:

Si on lit ton code :

void mafonction3(){
  
  int y=0;

Tu initialises y à 0

if((millis() - temps)>100){
    digitalWrite (ledPin[y],HIGH);

Tu allumes la led numéro 0 au bout de 100ms

   for( y = 0; y<nombrePin ;y++){
      }

Tu fais compter y mais tu ne fais rien pendant ce temps, donc les autres leds restent dans leur état initial

 temps = millis();
   }
 
  }

Tu remets le chrono à 0 mais ça ne sert à rien puisque tu sors de la fonction immédiatement après

Je verrais plutôt un truc comme ceci :

void mafonction3(){
  int delai = 100/nombrePin;
  for (y = 0; y<nombrePin ;y++){
    digitalWrite (ledPin[y],HIGH);
    delay(delai);
  }
}

Ceci les allume une par une dans une durée totale proche de 100 ms. Pour les éteindre ensuite (dans le sens contraire), c'est pareil :

void mafonction3(){
  int delai = 100/nombrePin;
  for (y = 0; y<nombrePin ;y++){
    digitalWrite (ledPin[y],HIGH);
    delay(delai);
  }
  for (y = nombrePin-1; y>=0 ;y--){
    digitalWrite (ledPin[y],LOW);
    delay(delai);
  }
}

Cette fonction est bloquante pendant 200ms (ou presque). Pour que ce ne soit pas bloquant, tu dois (par exemple) écouter le clavier pendant les boucles et sortir de la fonction si une touche est appuyée. Tu insères ceci juste après les digitalWrite.

  char customKey = customKeypad.getKey();
  if (customKey) return;

lesept:
Cette fonction est bloquante pendant 200ms (ou presque). Pour que ce ne soit pas bloquant, tu dois (par exemple) écouter le clavier pendant les boucles et sortir de la fonction si une touche est appuyée. Tu insères ceci juste après les digitalWrite.

  char customKey = customKeypad.getKey();

if (customKey) return;

ça c'est pas très évolutif.. si plus tard il y a d'autres conditions de sortie alors il va aussi falloir venir bidouiller... il faut garder la "machine" propre... (lire le clavier à un seul endroit, etc)

acedar:
pourquoi il n y a que la première led qui s allume?
pourquoi mon incrémentation ne se fait pas.

parce que

for( y = 0; y<nombrePin ;y++){}

ne fait absolument rien... ça compte mais n'affiche rien (et c'est même viré par l'optimiseur de code) et la prochaine fois que vous revenez dans la fonction, y qui est une variable locale non static reprend sa valeur 0...

si vous ne souhaitez pas que la fonction soit bloquante et que chaque tour de loop() l'appelle pour faire l'animation, il faut bâtir un peu de mémoire dans la fonction

const unsigned long delaiAttente = 100;

void mafonction3() {
  static byte y = 0; // static fait qu'on n'initialise qu'une fois et après la valeur est mémorisée entre 2 appels
  // j'utilise un byte car je pense que vous avez moins de 255 pins :)
  if ((millis() - temps) >= delaiAttente) {
    if (y >= nombrePin) {
      // on éteint tout par exemple et remet y à 0
      for (byte i = 0; i < nombrePin; i++) digitalWrite (ledPin[i], LOW);
      y = 0;
    } else {
      digitalWrite (ledPin[y++], HIGH); // allume la LED y et augmente y
    }
    temps += delaiAttente;
  }
}

bien sûr il faut que temps soit initialisé une seule fois en dehors de la fonction proprement

Oui, c'est plus propre et ça limite la lecture du clavier à celle qui est faite dans le programme principal.

hello

merci pour vos conseil la fonction fait parfaitement son travail.

juste un peu déçu de pas y entre arrivé tout seul pour une chose qui me paraissait aussi simple lol.

en tout cas la fonction millis est très utile une fois assimilé correctement et pour se faire il va falloir que je la travaille un peu plus et surtout sur des projet plus complexe ce qui me fera travailler aussi mes structures programme.

merci encore a vous J-M-L et LESEPT

super - oui il faut lire les tutos sur millis() et pratiquer un peu, ensuite ça vient tout seul :slight_smile: