Pages: [1]   Go Down
Author Topic: [RISOLTO]problemi con debounce + chiarimento switch case per gestione menu  (Read 781 times)
0 Members and 1 Guest are viewing this topic.
Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buona sera a tutti, sto sperimentando un modo per crearmi un menu che abbia un carattere speciale che mi faccia da cursore per selezionare le varie voci del menu, non riesco a far funzionare correttamente il debounce sul pulsante up,
sul down mi funziona perfettamente. cosa dovrei modificare?
Grazie

Code:
// include the library code:
#include <LiquidCrystalFast.h>

// initialize the library with the numbers of the interface pins
LiquidCrystalFast lcd(23, 25, 27, 29, 31, 33, 35, 37);
         // LCD pins: RS RW  E1  E2 D4 D5 D6 D7

// costanti per assegnazione pin
const int pulsanteUp = 1;     // pin pulate Up
const int pulsanteDown = 2;   // pin pulsante Down
const int pulsanteLeft = 3;   // pin pulsante Left
const int pulsanteRight = 4;  // pin pulsante Right
const int pulsanteEnter = 5;  // pin pulsante Enter
const int pulsanteEsc = 6;    // pin pulsante Esc

// variabili per lettura pulsanti
int statopulsanteUp = 0;
int statopulsanteDown = 0;
int statopulsanteLeft = 0;
int statopulsanteRight = 0;
int statopulsanteEnter = 0;
int statopulsanteEsc = 0;

// variabili per debouncing
int lastButtonState = LOW;
boolean flag = false;
long lastDebounceTime = 0;
long debounceDelay = 30;
//variabili lettura colonne e righe lcd
int numRighe = 0;
int numColonne = 0;

//carattere speciale per cursore di selezione menu
byte boccale[8] = {B00000, B01000, B11100, B11111, B11101, B11111, B11100, B00000,};


void setup() {
  //inizializza pin input dove sono collegati i pulsanti
  pinMode(pulsanteUp, INPUT);
  pinMode(pulsanteDown, INPUT);
  pinMode(pulsanteLeft, INPUT);
  pinMode(pulsanteRight, INPUT);
  pinMode(pulsanteEnter, INPUT);
  pinMode(pulsanteEsc, INPUT);
  

//creazione carattere speciale
  lcd.createChar(0, boccale);
  
// set lcd numero colonne e righe:
  lcd.begin(40, 4);

}

void loop() {
// lettura stato dei vari pulsanti
  statopulsanteUp = digitalRead(pulsanteUp);
  statopulsanteDown = digitalRead(pulsanteDown);
  statopulsanteLeft = digitalRead(pulsanteLeft);
  statopulsanteRight = digitalRead(pulsanteRight);
  statopulsanteEnter = digitalRead(pulsanteEnter);
  statopulsanteEsc = digitalRead(pulsanteEsc);
 // prova menu principale
  lcd.setCursor (numColonne, numRighe); lcd.write(0);
  lcd.setCursor (1, 0); lcd.print ("voce 1");
  lcd.setCursor (1, 1); lcd.print ("voce 2");
  lcd.setCursor (1, 2); lcd.print ("voce 3");
  lcd.setCursor (1, 3); lcd.print ("voce 4");
  lcd.setCursor (21, 0); lcd.print ("voce 5");
  lcd.setCursor (21, 1); lcd.print ("voce 6");
  lcd.setCursor (21, 2); lcd.print ("voce 7");
  lcd.setCursor (21, 3); lcd.print ("voce 8");
  
  {      
   if ((statopulsanteDown != lastButtonState) && (flag==false))
     {
     flag=true;
     lcd.clear();
     if (statopulsanteDown==HIGH)// se premo Down sposto verso il basso il cursore per selezionare una voce del menu
     numRighe--; lcd.setCursor (numColonne, numRighe); lcd.write(0);
     lastDebounceTime = millis();
     if (numRighe == -1 && numColonne == 0){numRighe = 3; numColonne = 20;}
     if (numRighe == -1 && numColonne == 20){numRighe = 3; numColonne = 0;lcd.clear();}
    
     }    
         if (millis() > (lastDebounceTime + debounceDelay))
      flag = false;
      lastButtonState = statopulsanteDown;
      }
  
 {
  if ((statopulsanteUp != lastButtonState) && (flag==false))
     {
     flag=true;
     lcd.clear();
     if (statopulsanteUp==HIGH)// se premo Up sposto il cursore verso l'alto per selezionare una voce del menu
     numRighe++; lcd.setCursor (numColonne, numRighe); lcd.write(0);
     lastDebounceTime = millis();
     if (numRighe == 4 && numColonne == 0){numRighe = 0; numColonne = 20;}
     if (numRighe == 4 && numColonne == 20){numRighe = 0; numColonne = 0;lcd.clear();}

     }
        if (millis() > (lastDebounceTime + debounceDelay))
      flag = false;
      lastButtonState = statopulsanteUp;
  
    }  
  }
« Last Edit: December 10, 2012, 03:30:39 am by peppe123 » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

La via più semplice è mettere 2 letture del pin a cui hai collegato il pulsante separate da un piccolo delay. Senza stare ad usare codici più complessi.
Code:
if (digitalRead(pin) == stato) {
  delay(30);
  if (digitalRead(pin) == stato) {
    ....
  }
}
Funzionamento garantito al 99%  smiley-wink (l'1% è per scaramanzia)
Logged


Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nulla.. direi che sono capitato nell' 1%  smiley

forse c'è qualcosa di sbagliato nel codice?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nulla.. direi che sono capitato nell' 1%  smiley

forse c'è qualcosa di sbagliato nel codice?
Beh, intanto tu non usi il metodo che ti ho detto io ma uno basato sugli intervalli misurati con millis().  smiley-wink

E poi mi pare che tu condivida la variabile lastButtonState per entrambi i pulsanti. Prova a mettere lastButtonStateDown e lastButtonStateUp perché ho come il timore che il problema sia qui.
Logged


rome
Offline Offline
Sr. Member
****
Karma: 15
Posts: 474
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ci sono molte semplici librerie che gestiscono i buttons con molte funzioni oltre al deboncing.
Io suggerisco, per semplicità e robustezza, la seguente

http://playground.arduino.cc/Code/Buttons


Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Io non voglio passare da quello che pontifica a destra e manca però dico e domando: se puoi fare una cosa con un semplice delay messo fra 2 letture successive perché andare a scomodare una libreria?  smiley-sweat
Logged


Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nulla.. direi che sono capitato nell' 1%  smiley

forse c'è qualcosa di sbagliato nel codice?
Beh, intanto tu non usi il metodo che ti ho detto io ma uno basato sugli intervalli misurati con millis().  smiley-wink

E poi mi pare che tu condivida la variabile lastButtonState per entrambi i pulsanti. Prova a mettere lastButtonStateDown e lastButtonStateUp perché ho come il timore che il problema sia qui.

risolto smiley
ho messo lastButtonStateDown.. Up.. Left.. etc.. ora va perfettamente

grazie!
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bravo.
Ora arrivano le tiratine d'orecchie  smiley-twist

Code:
const int pulsanteUp = 1;     // pin pulate Up
const int pulsanteDown = 2;   // pin pulsante Down
const int pulsanteLeft = 3;   // pin pulsante Left
const int pulsanteRight = 4;  // pin pulsante Right
const int pulsanteEnter = 5;  // pin pulsante Enter
const int pulsanteEsc = 6;    // pin pulsante Esc

// variabili per lettura pulsanti
int statopulsanteUp = 0;
int statopulsanteDown = 0;
int statopulsanteLeft = 0;
int statopulsanteRight = 0;
int statopulsanteEnter = 0;
int statopulsanteEsc = 0;

// variabili per debouncing
int lastButtonState = LOW;
boolean flag = false;
long lastDebounceTime = 0;
long debounceDelay = 30;
//variabili lettura colonne e righe lcd
int numRighe = 0;
int numColonne = 0;
Sai queste dichiarazioni di variabili di tipo "int" quanto consuma in RAM?
30 byte! 30 byte quando ne potresti consumare 15 semplicemente usando il typo "byte".
A meno che tu non voglia ad esempio leggere il pulsante -15000 smiley-wink
I pin del microcontrollore non arriveranno mai a 255, basta un tipo "byte"

Altra cosa.
Code:
long lastDebounceTime = 0;
long debounceDelay = 30;
è sbagliato. Ammettiamo che il tuo Arduino resti acceso per più di 25 giorni. Arriverai ad avere problemi con la gestione del valore restituito da millis() perché quest'ultimo è di tipo "unsigned long", non "long". Per cui quando arriverai a memorizzare un valore più grande di 2147483647 ti ritroverai con numeri negativi e non saprai perché  smiley-razz
Logged


Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie, praticamente sono al mio primo progetto, critiche e consigli sono ben accetti.
riposto il codice, magari mi aiutate a capire come posso creare un menu con sottomenu.. sto provando utilizzando solo switch case ma dal case 0 riesco a passare al case 1 poi sono bloccato li. come faccio a saltare da un case all'altro?
grazie
Code:
// include the library code:
#include <LiquidCrystalFast.h>

// initialize the library with the numbers of the interface pins
LiquidCrystalFast lcd(23, 25, 27, 29, 31, 33, 35, 37);
         // LCD pins: RS RW  E1  E2 D4 D5 D6 D7

// costanti per assegnazione pin
const int pulsanteUp = 1;     // pin pulate Up
const int pulsanteDown = 2;   // pin pulsante Down
const int pulsanteLeft = 3;   // pin pulsante Left
const int pulsanteRight = 4;  // pin pulsante Right
const int pulsanteEnter = 5;  // pin pulsante Enter
const int pulsanteEsc = 6;    // pin pulsante Esc

// variabili per lettura pulsanti
byte statopulsanteUp = 0;
byte statopulsanteDown = 0;
byte statopulsanteLeft = 0;
byte statopulsanteRight = 0;
byte statopulsanteEnter = 0;
byte statopulsanteEsc = 0;

// variabili per debouncing
int lastButtonStateUp = LOW;
int lastButtonStateDown = LOW;
int lastButtonStateLeft = LOW;
int lastButtonStateRight = LOW;
int lastButtonStateEnter = LOW;
int lastButtonStateEsc = LOW;


boolean flag = false;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 30;
//variabili lettura colonne e righe lcd
int numRighe = 0;
int numColonne = 0;

//variabile menu
unsigned int cont_pag = 0;

//carattere speciale per cursore di selezione menu
byte boccale[8] = {B00000, B01000, B11100, B11111, B11101, B11111, B11100, B00000,};


void setup() {
  //inizializza pin input dove sono collegati i pulsanti
  pinMode(pulsanteUp, INPUT);
  pinMode(pulsanteDown, INPUT);
  pinMode(pulsanteLeft, INPUT);
  pinMode(pulsanteRight, INPUT);
  pinMode(pulsanteEnter, INPUT);
  pinMode(pulsanteEsc, INPUT);
  

//creazione carattere speciale
  lcd.createChar(0, boccale);
  
// set lcd numero colonne e righe:
  lcd.begin(40, 4);

}

void loop() {
// lettura stato dei vari pulsanti
  statopulsanteUp = digitalRead(pulsanteUp);
  statopulsanteDown = digitalRead(pulsanteDown);
  statopulsanteLeft = digitalRead(pulsanteLeft);
  statopulsanteRight = digitalRead(pulsanteRight);
  statopulsanteEnter = digitalRead(pulsanteEnter);
  statopulsanteEsc = digitalRead(pulsanteEsc);
  
    
  
  
switch (cont_pag) {

  case 0:
  lcd.setCursor (numColonne, numRighe); lcd.write(0);
  lcd.setCursor (1, 0); lcd.print ("voce 1");
  lcd.setCursor (1, 1); lcd.print ("voce 2");
  lcd.setCursor (1, 2); lcd.print ("voce 3");
  lcd.setCursor (1, 3); lcd.print ("voce 4");
  lcd.setCursor (21, 0); lcd.print ("voce 5");
  lcd.setCursor (21, 1); lcd.print ("voce 6");
  lcd.setCursor (21, 2); lcd.print ("voce 7");
  lcd.setCursor (21, 3); lcd.print ("voce 8");
  
   if ((statopulsanteDown != lastButtonStateDown) && (flag==false))
     {
     flag=true;
     lcd.clear();
     if (statopulsanteDown==HIGH)//premo Down per spostare il cursore char
     numRighe--; lcd.setCursor (numColonne, numRighe); lcd.write(0);
     lastDebounceTime = millis();
     if (numRighe == -1 && numColonne == 0){numRighe = 3; numColonne = 20;lcd.clear();}
     if (numRighe == -1 && numColonne == 20){numRighe = 3; numColonne = 0;lcd.clear();}
    
     }    
         if (millis() > (lastDebounceTime + debounceDelay))
      flag = false;
      lastButtonStateDown = statopulsanteDown;
      
  
 
  if ((statopulsanteUp != lastButtonStateUp) && (flag==false))
     {
     flag=true;
     lcd.clear();
     if (statopulsanteUp==HIGH) //sposto verso l'alto il cursore char per selezionare voci del menu principale
     numRighe++; lcd.setCursor (numColonne, numRighe); lcd.write(0);
     lastDebounceTime = millis();
     if (numRighe == 4 && numColonne == 0){numRighe = 0; numColonne = 20;}
     if (numRighe == 4 && numColonne == 20){numRighe = 0; numColonne = 0;lcd.clear();}

     }
        if (millis() > (lastDebounceTime + debounceDelay))
      flag = false;
      lastButtonStateUp = statopulsanteUp;
      
  
     break;
  
  
        case 1:
  lcd.setCursor (1, 0);lcd.print("menu2");
  if ((statopulsanteRight != lastButtonStateRight) && (flag==false))
     {
     flag=true;
     lcd.clear();
     if (statopulsanteRight==HIGH)
     cont_pag = 2;
     lastDebounceTime = millis();
     lcd.clear();
     if (millis() > (lastDebounceTime + debounceDelay))
      flag = false;
      lastButtonStateRight = statopulsanteRight;
      
     }
  
     break;
    
     case 2:
  lcd.setCursor (1, 0);lcd.print("menu3");
     if ((statopulsanteLeft != lastButtonStateUp) && (flag==false))
     {
     flag=true;
     lcd.clear();
     if (statopulsanteLeft==HIGH)
     cont_pag = 0;
     lastDebounceTime = millis();
     lcd.clear();
     if (millis() > (lastDebounceTime + debounceDelay))
      flag = false;
      lastButtonStateLeft = statopulsanteLeft;
    
     }
  
     break;
    
  }

 }
« Last Edit: December 10, 2012, 03:35:19 am by peppe123 » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Secondo me stai sbagliando la logica del tuo programma.
cont_pag, che è la variabile controllata dallo switch, devi modificarla esternamente allo switch stesso, altrimenti non ha senso come hai fatto tu: mi pare di vedere che tu entri in uno case, lì dentro cambi il valore di cont_pag e poi il tuo programma riparte e rientra nello switch e da lì nel case impostato in precedenza, dove poi ricambi ancora cont_pag ecc....

La logica alla base dello switch..case è
Code:
var = imposto_la_variabile_con_qualcosa;
switch (var) {
  case 0:
    ...
    break;
  case 1:
    ..
    break;
  ecc....
}
Tu lo usi come una specie di salto, alla fine, per passare da un case all'altro.
Logged


rome
Offline Offline
Sr. Member
****
Karma: 15
Posts: 474
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@leo72
nessun problema, pontifica pure :-). La libreria serve se peppe, come mi è sembrato e come conferma negli ultimi post, vuole avere una gestione un po più sofisticata dei button senza inserire delay.

@peppe123
se può interessarti guarda anche la mia libreria per la gestione dei menu. Ho visto chè è stata scaricata da qualche centinaio di utenti. La dovrei anche migliorare, tempo permettendo:

https://github.com/brunialti/MENWIZ
(vai sul download per scaricare tutto). Se non ti spaventi per topics molto lunghi vai anche su  http://arduino.cc/forum/index.php?topic=99693.new;topicseen#new
« Last Edit: December 10, 2012, 03:26:59 pm by brunialti » Logged

Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@leo72
nessun problema, pontifica pure :-). La libreria serve se peppe, come mi è sembrato e come conferma negli ultimi post, vuole avere una gestione un po più sofisticata dei button senza inserire delay.

@peppe123
se può interessarti guarda anche la mia libreria per la gestione dei menu. Ho visto chè è stata scaricata da qualche centinaio di utenti. La dovrei anche migliorare, tempo permettendo:

https://github.com/brunialti/MENWIZ
(vai sul download per scaricare tutto). Se non ti spaventi per topics molto lunghi vai anche su  http://arduino.cc/forum/index.php?topic=99693.new;topicseen#new

Grazie, intanto sperimento qualcosa senza usare librerie, puo' essere che imparo qualcosa smiley

Secondo me stai sbagliando la logica del tuo programma.
cont_pag, che è la variabile controllata dallo switch, devi modificarla esternamente allo switch stesso, altrimenti non ha senso come hai fatto tu: mi pare di vedere che tu entri in uno case, lì dentro cambi il valore di cont_pag e poi il tuo programma riparte e rientra nello switch e da lì nel case impostato in precedenza, dove poi ricambi ancora cont_pag ecc....

La logica alla base dello switch..case è
Code:
var = imposto_la_variabile_con_qualcosa;
switch (var) {
  case 0:
    ...
    break;
  case 1:
    ..
    break;
  ecc....
}
Tu lo usi come una specie di salto, alla fine, per passare da un case all'altro.

praticamente io utilizzo un cursore per spostarmi nelle varie voci del menu: quindi se il cursore si trova nella riga x e nella colonna x con la funzione if premo enter per accedere a quel sottomenu.
per ora lo sto sperimentando con successo, nel senso che sembra fare il suo dovere. magari il codice diventa un po' contorto pero' non sono riuscito a trovare una strada alternativa.
a quanto pare in questo modo con un unico switch riesco a fare menu e sottomenu.
che ne pensate?
potrei incontrare qualche difficolta' nell'implementazioni di ulteriori funzioni nei case visto che dovro' gestire temperature rele e funzioni timer?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@peppe:
non mi sono messo ad analizzare a fondo il tuo codice.

Logged


Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

per ora imposto menu e sottomenu.. poi vediamo piu avanti quali complicanze di presenteranno  smiley-grin

in questo momento sono alle prese con una parte del menu che deve avere una decina di voci, una per ogni riga.. come posso fare per far comportare il mio lcd (posseggo un lcd 40, 4) come se fosse un 40x12 scorrendo come se fossero continue.

non so se ho reso l'idea smiley

grazie
Logged

Pages: [1]   Go Up
Jump to: