Go Down

Topic: Action après appui sur un bouton - Problème (Read 1 time) previous topic - next topic

NancyBoy

Bonjour à tous,

Je tente depuis quelques jours de créer un déclencheur laser et sonore pour appareil photo.L'idée est simple: une laser avec détecteur, un capteur son et un lcdshield avec keypad.
J'ai créé un menu pour choisir si on veut le laser ou le son comme détecteur.
Mon problème: quand je sélectionne un des deux (bouton select du keypad), on dirait que ça bloque, plus rien ne se passe (si je lis les données du capteur son en serial par exemple, ça ne défile pas).

Je n'y connais pas grand chose, peut-être que mon problème est simple à résoudre.

Merci d'avance pour vos conseils.

Mon code:

Code: [Select]

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int lcd_key     = 0;
int adc_key_in  = 0;
int choix       = 10;
int laser = 12;
int capteurlaser = A1;
int caplaser = analogRead(capteurlaser);


#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5


int read_LCD_buttons()
{
adc_key_in = analogRead(0);      
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50)   return btnRIGHT;  
if (adc_key_in < 195)  return btnUP;
if (adc_key_in < 380)  return btnDOWN;
if (adc_key_in < 555)  return btnLEFT;
if (adc_key_in < 790)  return btnSELECT;    
}



void setup()
{
pinMode(laser, OUTPUT);  
Serial.begin(115200);
lcd.begin(16, 2);            
lcd.setCursor (2,0);
lcd.print ("Laser");
lcd.setCursor (2,1);
lcd.print ("Son");
}

void loop()
{        
caplaser = analogRead(capteurlaser);
lcd_key = read_LCD_buttons();  

switch (lcd_key)               // depending on which button was pushed, we perform an action
{
 
  case btnUP:
    {
    lcd.setCursor (0,0);
    lcd.print ((char)126);
    lcd.setCursor (0,1);
    lcd.print (' ');
    choix= 11;
    //Serial.println(choix);
    break;
    }
   
  case btnDOWN:
    {
    lcd.setCursor (0,1);
    lcd.print ((char)126);
    lcd.setCursor (0,0);
    lcd.print (' ');
    choix= 9;
    //Serial.println(choix);
    break;      
    }
   
    case btnSELECT:
    {
    if (choix == 9)
    {
    lcd.clear();
    lcd.setCursor (0,0);
    lcd.print("Son");
    }
    if (choix == 11)
    {
    lcd.clear();
    lcd.setCursor (0,0);  
    lcd.print("Laser");
    digitalWrite(laser, HIGH);
    Serial.println(caplaser);
    lcd.setCursor (0,1);
    lcd.print(caplaser);
   
    }
    }

}
}
   


fdufnews

Pour le son on ne peut rien dire cette partie n'apparait pas dans le code.
Pour le laser, lorsque tu sélectionnes le laser, tu entres dans le if (choix==11) qui modifie le libellé sur l'afficheur et qui affiche l'état de caplaser. Mais dès que tu relâches le bouton tu ne passes plus dans cette partie de la boucle et tu n'as donc plus d'affichage.

Le codage de ta gestion de clavier est propre avec une petite machine d'états. Il faudrait continuer pour gérer la suite. C'est à dire, que se passe-t-il après que l'on a choisi un mode de fonctionnement.
Dans quel état entres-tu?
Quel action te fera quitter cet état vers quel autre état?

NancyBoy

Quand j'appuie sur le bouton haut ou bas, la valeur de "choix" change (9 ou 11).
En appuyant ensuite sur le bouton select, le lcd indique si on a 9 ou 11.
A partir de là, j'aimerais qu'un action soit déclenché d'après la valeur "choix".
En faisant le test avec laser, mon laser s'allume, mais c'est au niveau du capteur que ça bloque. Le moniteur série affiche quelques données, mais s'arrête (c'est ce qu'il me semble en tout cas).  Que le laser soit dessus ou non, rien ne change.
Pour la suite de l'action à donner, je devrais pouvoir trouver, mais comme ça bloque, ça ne me sert pas à grand chose.




B83s

Tu veux afficher les valeur du capteur en continu ?

Il faut prévoir un affichage de sa valeur en dehors du switch (lcd_key) ... Car tu as mis des actions dans le switch, mais si tu n'appuies pas sur un bouton, dans ton loop il n'y a rien (à part lire les valeurs du capteur et de lcd_key)

D'ailleurs fdufnews a déjà relevé cette erreur ...

NancyBoy

Oui, c'est ça, je voudrais avoir la valeur en continu.

Désolé, étant complètement débutant, je n'avais pas compris ça dans la première réponse.

J'ai refait mon code (pour améliorer certains problèmes), mais le problème était toujours le même.

Avec vos réponses, je vais voir ce que je peux faire.

Merci.

Mon nouveau code:
Code: [Select]
#include <LiquidCrystal.h>              //on définie la librairie LCD


LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // on definie les broches du LCD


int lcd_key     = 0;
int adc_key_in  = 0;
int choix       = 0;
int laser = 12;
int capteurlaser = A1;
//int caplaser = analogRead(capteurlaser);
int capteurson = A2;
//int capson = analogRead(capteurson);
int relais = 11;
int etat_btn;
int leson;
int valson;
int lelaser;
int vallaser;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
#define Haut      6
#define Bas       7

int niveauson()
{
leson = analogRead(A2);
if (leson > 50) return Haut;
if (leson < 50) return Bas;
}

int niveaulaser()
{
lelaser = analogRead(A1);
if (lelaser > 50) return Haut;
if (lelaser < 50) return Bas;
}


int read_LCD_buttons()
{
adc_key_in = analogRead(0);     
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50)   return btnRIGHT; 
if (adc_key_in < 195)  return btnUP;
if (adc_key_in < 380)  return btnDOWN;
if (adc_key_in < 555)  return btnLEFT;
if (adc_key_in < 790)  return btnSELECT;   
}

// On définit ce qui sera fait par "fonctionson"
int fonctionson()
  {
    valson = niveauson();
    switch(valson) {

  case Haut:     
   lcd.clear();
   lcd.setCursor (0,0); 
   lcd.print("Haut");
   lcd.setCursor (0,1);
   lcd.print(leson);
   Serial.println(leson);
   break;
 
  case Bas:
   lcd.clear();
   lcd.setCursor (0,0); 
   lcd.print("Bas");
   lcd.setCursor (0,1);
   lcd.print(leson);
   Serial.println(leson);
   break;
 
  }}
 
// On définit ce qui sera fait par "fonctionlaser"
int fonctionlaser()
  {
    vallaser = niveaulaser();
    switch(vallaser) {

  case Haut:     
   lcd.clear();
   lcd.setCursor (0,0); 
   lcd.print("Haut");
   lcd.setCursor (0,1);
   lcd.print(lelaser);
   Serial.println(lelaser);
   break;
 
  case Bas:
   lcd.clear();
   lcd.setCursor (0,0); 
   lcd.print("Bas");
   lcd.setCursor (0,1);
   lcd.print(lelaser);
   Serial.println(lelaser);
   break;
 
  }}


// On définit ce qui sera fait par "Action"
int Action()
{
  switch(choix)   {
  case 9:             
    {lcd.clear();
     fonctionson();
     break;
    }

  case 10:
     {lcd.clear();
     fonctionlaser();
     break;}
  }}
 


void setup()
{
pinMode(laser, OUTPUT); 
pinMode(relais, OUTPUT);
int capteurlaser = A1;
int caplaser = analogRead(capteurlaser);
int capteurson = A2;
int capson = analogRead(capteurson);
Serial.begin(115200);
lcd.begin(16, 2);
lcd.setCursor (2,0);
lcd.print ("Son");
lcd.setCursor (2,1);
lcd.print ("Laser");
}

void loop()
{
GestionMenu();
}

void GestionMenu()
{
 
  lcd_key = read_LCD_buttons() ;     
   
    switch (lcd_key)  {
    case btnSELECT:   
    {   
    Action();
    break;
    }

    case btnUP:
    {
    digitalWrite(laser, LOW);
    lcd.clear();     
    lcd.setCursor (2,0);
    lcd.print ("Son");
    lcd.setCursor (2,1);
    lcd.print ("Laser");
    choix= 9;     
    Serial.println(choix);
    lcd.setCursor (0,0);
    lcd.print ((char)126);
    lcd.setCursor (0,1);
    lcd.print (' ');
    break;
    }
   
    case btnDOWN:
    {   
    digitalWrite(laser, LOW); 
    lcd.clear() ;   
    lcd.setCursor (2,0);
    lcd.print ("Son");
    lcd.setCursor (2,1);
    lcd.print ("Laser");
    choix= 10;   
    Serial.println(choix);
    lcd.setCursor (0,1);
    lcd.print ((char)126);
    lcd.setCursor (0,0);
    lcd.print (' ');
    break; 
    }


};
}

/* Mettre les alimentations laser et capteurs sur des sorties digitales pour pouvoir les arrêter (comme le laser) quand on appuie à nouveau sur haut ou bas.

*/


NancyBoy

Effectivement, si je garde le bouton appuyé, les données continuent à défiler.

Je vais essayer de trouver comment changer, mais mes connaissances semblent être à leur max pour le moment.  :-D

B83s

Ce n'est pas bien compliqué :
Dans ton loop, tu ajoutes un fonction d'affichage des valeurs que tu appelles toutes les x millisecondes ( sans utiliser le delay() sinon ça met des latences dans la réaction de ton code)

Code: [Select]

Unsigned long last_affichage; // déclaration en global

void loop() {
If ( millis() - last_affichage > x) { // tu entres dans cette condition toutes les x millisecondes
        afficher_les_valeurs();      // tu appelles une fonction qui va afficher tes valeurs comme tu veux
        last_affichage = millis();  // tu retiens la date du dernier affichage
  }
  GestionMenu(); // tu surveilles l'appui sur les boutons
}


Et voilà !

PS:  dans ton prog tu dis mettre l'alimentation du laser et capteur sur sortie digitale  ... Pourquoi pas, mais fais attention au courant absorbé par la laser et le capteur, car ton micro contrôleur ne peut sortir que 20mA (à vérifier) avant de partir en fumée

NancyBoy

Au pire, je positionne les alimentations sur les +5v, les mettre sur en digital me permet de les allumer ou les éteindre d'après le cas.

Je vais étudier un peu le langage Arduino, là, je bloque totalement.


B83s

Fais attention au courant consommé par le laser si tu le mets sur une sortie digitale pour pouvoir l'arrêter ... Tu risques de griller ta carte ...

tu bloques ou ? Dans l'exemple que je t'ai donné tu mets par exemple 500 à la place de x pour afficher les valeurs toutes les 500 ms ... afficher_valeurs() est une fonction que tu dois écrire pour afficher les valeurs comme tu le souhaites ...

NancyBoy

#9
Mar 23, 2014, 08:27 pm Last Edit: Mar 23, 2014, 08:29 pm by NancyBoy Reason: 1
Ok, je vais l'enlever d'une sortie digitale, ça ne posera pas spécialement de problème.

J'ai ajouté

Code: [Select]
unsigned long last_affichage;

int lecture()
{analogRead(A1);
analogRead(A2);


en début de code et ensuite j'ai modifié

Code: [Select]
void loop()
{if ( millis() - last_affichage > 500) { // tu entres dans cette condition toutes les x millisecondes
       lecture();      // tu appelles une fonction qui va afficher tes valeurs comme tu veux
       last_affichage = millis();  // tu retiens la date du dernier affichage
}

{
GestionMenu();
}


La définition de GestionMenu est remonté avec les autres fonctions, ça posait problème.

La valeur ne se rafraîchit pas.


B83s

Ta fonction lecture() lit les valeurs ... Mais ne les affiche pas !
Ajoute dans lecture() l'affichage sur ton lcd ou sur le port série  !

NancyBoy

Ce n'est pas encore ça, la valeur ne se rafraîchit pas.

Code: [Select]
#include <LiquidCrystal.h>              //on définie la librairie LCD


LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // on definie les broches du LCD


int lcd_key     = 0;
int adc_key_in  = 0;
int choix       = 0;
int laser = 12;
int capteurlaser = A1;

int capteurson = A2;
int relais = 11;
int etat_btn;
int seuillaser = 50;
int seuilson = 50;

unsigned long last_affichage;

int lecturelaser()
{analogRead(A1);}

int lectureson()
{analogRead(A2);}

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
#define Haut      6
#define Bas       7


int read_LCD_buttons()
{
adc_key_in = analogRead(0);     
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50)   return btnRIGHT; 
if (adc_key_in < 195)  return btnUP;
if (adc_key_in < 380)  return btnDOWN;
if (adc_key_in < 555)  return btnLEFT;
if (adc_key_in < 790)  return btnSELECT;   
}

// On définit ce qui sera fait par "fonctionson"
int fonctionson()
   {if ( millis() - last_affichage > 2000) {
        lectureson();     
        last_affichage = millis();} 
   
   lcd.clear();
   lcd.setCursor (0,0);
   lcd.print("Son:");
   lcd.setCursor (7,0);
   lcd.print (lectureson());
   Serial.print(lectureson());
   lcd.setCursor (0,1);
   lcd.print("Seuil:");
   lcd.setCursor (7,1);
   lcd.print(seuilson);
   

   if (capteurson >50)
   {digitalWrite(relais, HIGH);
   delay(1000);
   digitalWrite(relais, LOW);}
   }

 
// On définit ce qui sera fait par "fonctionlaser"
int fonctionlaser()

{if ( millis() - last_affichage > 2000) {
        lecturelaser();   
        last_affichage = millis(); }


lcd.clear();
lcd.setCursor (0,0);
lcd.print("Laser:");
lcd.setCursor (7,0);
lcd.print (lecturelaser());
Serial.print(lecturelaser());
lcd.setCursor (0,1);
lcd.print("Seuil:");
lcd.setCursor (7,1);
lcd.print(seuillaser);


if (capteurlaser < seuillaser)
   {digitalWrite(relais, HIGH);
   delay(1000);
   digitalWrite(relais, LOW);}
   }


// On définit ce qui sera fait par "Action"
int Action()
{
  switch(choix)   {
  case 9:             
    {lcd.clear();
     fonctionson();
     break;
    }

  case 10:
     {lcd.clear();
     fonctionlaser();
     break;}
  }}
 
 
 
void GestionMenu()
    { 
    lcd_key = read_LCD_buttons() ;     
   
    switch (lcd_key)  {
    case btnSELECT:   
    {   
    Action();
    break;
    }

    case btnUP:
    {
    digitalWrite(laser, LOW);
    lcd.clear();     
    lcd.setCursor (2,0);
    lcd.print ("Son");
    lcd.setCursor (2,1);
    lcd.print ("Laser");
    choix= 9;     
    Serial.println(choix);
    lcd.setCursor (0,0);
    lcd.print ((char)126);
    lcd.setCursor (0,1);
    lcd.print (' ');
    break;
    }
   
    case btnDOWN:
    {   
    digitalWrite(laser, LOW); 
    lcd.clear() ;   
    lcd.setCursor (2,0);
    lcd.print ("Son");
    lcd.setCursor (2,1);
    lcd.print ("Laser");
    choix= 10;   
    Serial.println(choix);
    lcd.setCursor (0,1);
    lcd.print ((char)126);
    lcd.setCursor (0,0);
    lcd.print (' ');
    break; 
    }};
    }
 


void setup()
{
pinMode(laser, OUTPUT); 
pinMode(relais, OUTPUT);
int capteurlaser = A1;
int caplaser = analogRead(capteurlaser);
int capteurson = A2;
int capson = analogRead(capteurson);
Serial.begin(115200);
lcd.begin(16, 2);
lcd.setCursor (2,0);
lcd.print ("Son");
lcd.setCursor (2,1);
lcd.print ("Laser");
}

void loop()
{
GestionMenu();
}


B83s

Et si tu enlèves les roues de ton vélo, il roule encore ?

Je t'ai montré comment faire l'affichage  ... Si tu ne fais pas l'effort de l'intégrer ... Je ne peux plus rien pour toi


NancyBoy

Mea culpa, mauvaise lecture de ta réponse, ça doit être la fatigue...

Merci de t'intéresser à mon cas, même si je fais le boulet .   :)

NancyBoy

Voilà, ça progresse.
J'arrive à rafraîchir le relevé du capteur, c'est déjà ça.
Mon problème actuel est qu'il s'affiche dès le début du programme lors que je voudrais que ça ne s'affiche que quand j'arrive à fonctionlaser() ou fonctionson(). 


Mon nouveau code:

Code: [Select]
#include <LiquidCrystal.h>              //on définie la librairie LCD


LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // on definie les broches du LCD


int lcd_key     = 0;
int adc_key_in  = 0;
int choix       = 0;
int laser = 12;
int capteurlaser = A1;

int capteurson = A2;
int relais = 11;
int etat_btn;
int seuillaser = 50;
int seuilson = 50;

unsigned long last_affichage;


int lecturelaser()
{
analogRead(A1);
Serial.print (analogRead(A1));
lcd.setCursor (7,0);
lcd.print (analogRead(A1)) ;
}


int lectureson()
{
analogRead(A2);
Serial.print (analogRead(A2));
lcd.setCursor (7,0);
lcd.print (analogRead(A2)) ;
}

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
#define Haut      6
#define Bas       7


int read_LCD_buttons()
{
adc_key_in = analogRead(0);     
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50)   return btnRIGHT; 
if (adc_key_in < 195)  return btnUP;
if (adc_key_in < 380)  return btnDOWN;
if (adc_key_in < 555)  return btnLEFT;
if (adc_key_in < 790)  return btnSELECT;   
}

// On définit ce qui sera fait par "fonctionson"
int fonctionson()
   
   {
   lcd.clear();
   lcd.setCursor (0,0);
   lcd.print("Son:");
      lcd.setCursor (0,1);
   lcd.print("Seuil:");
   lcd.setCursor (7,1);
   lcd.print(seuilson);
   
   if (capteurson >50)
   {digitalWrite(relais, HIGH);
   delay(1000);
   digitalWrite(relais, LOW);}
   }

 
// On définit ce qui sera fait par "fonctionlaser"
int fonctionlaser()

   {
   lcd.clear();
   lcd.setCursor (0,0);
   lcd.print("Laser:");
   lcd.setCursor (0,1);
   lcd.print("Seuil:");
   lcd.setCursor (7,1);
   lcd.print(seuillaser);
   
   if (capteurlaser < seuillaser)
   {digitalWrite(relais, HIGH);
   delay(1000);
   digitalWrite(relais, LOW);}
   }


// On définit ce qui sera fait par "Action"
int Action()
{
  switch(choix)   {
  case 9:             
    {lcd.clear();
     fonctionson();
     break;
    }

  case 10:
     {lcd.clear();
     fonctionlaser();
     break;}
  }}
 
 
 
void GestionMenu()
    { 
    lcd_key = read_LCD_buttons() ;     
   
    switch (lcd_key)  {
    case btnSELECT:   
    {   
    Action();
    break;
    }

    case btnUP:
    {
    digitalWrite(laser, LOW);
    lcd.clear();     
    lcd.setCursor (2,0);
    lcd.print ("Son");
    lcd.setCursor (2,1);
    lcd.print ("Laser");
    choix= 9;     
    Serial.println(choix);
    lcd.setCursor (0,0);
    lcd.print ((char)126);
    lcd.setCursor (0,1);
    lcd.print (' ');
    break;
    }
   
    case btnDOWN:
    {   
    digitalWrite(laser, LOW); 
    lcd.clear() ;   
    lcd.setCursor (2,0);
    lcd.print ("Son");
    lcd.setCursor (2,1);
    lcd.print ("Laser");
    choix= 10;   
    Serial.println(choix);
    lcd.setCursor (0,1);
    lcd.print ((char)126);
    lcd.setCursor (0,0);
    lcd.print (' ');
    break; 
    }};
    }
 


void setup()
{
pinMode(laser, OUTPUT); 
pinMode(relais, OUTPUT);
int capteurlaser = A1;
int caplaser = analogRead(capteurlaser);
int capteurson = A2;
int capson = analogRead(capteurson);
Serial.begin(115200);
lcd.begin(16, 2);
lcd.setCursor (2,0);
lcd.print ("Son");
lcd.setCursor (2,1);
lcd.print ("Laser");

}

void loop()
{
if ( millis() - last_affichage > 2000) {
   lecturelaser();
   last_affichage = millis(); }
GestionMenu();
}


Go Up