[Risolto]Ciclo for per gestire più input.

Salve a tutti,
Vorrei sapere se e normale che quando un pin cambia stato nel ciclo for non torna nello stato di riposo o nello stato iniziale ?
Allego sketch.[code

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

int key[3] = {HIGH,HIGH,HIGH};
int pin[3]= {5,6,7};


int  banconota10  = 0;
int  banconota20  = 0;
int  sommapar = 0;

void setup() {
    lcd.init();
    lcd.backlight();
    lcd.setCursor(1,0);
    lcd.print("WIN GAMES");
    lcd.setCursor(0,1);
    lcd.print("TOTALI");  

    
for (int i= 0;i<3 ; i++){
  pinMode(pin[i],INPUT_PULLUP);
}
Serial.begin(9600);
}

void loop() {
for (int i= 0;i<3 ; i++){
 if(digitalRead(pin[i]) ==LOW){
  key[i] = !key[i];
  
  delay(200);

 
 }
}
for (int i= 0;i<3 ; i++){
  if(key[i]== LOW){
    
    Serial.print("PIN");
    Serial.print(pin[i]);
    Serial.print("     BANCONOTA EURO ");
    if (pin[i]==6)
     banconota20 = banconota20 + 20;
     sommapar = banconota20 +  banconota10;
    Serial.println("20");
     if (pin[i]==7)
     banconota10 = banconota10 + 10;
     sommapar = banconota20 +  banconota10;
    Serial.println("10");
  }else{
    Serial.print("PIN");
    Serial.print(pin[i]);
    Serial.println("  ");
    
    
  }
}

  lcd.setCursor(8, 1);  
       lcd.print(sommapar); 

}

][/code]

con queste righe di codice:

for (int i= 0;i<3 ; i++){
 if(digitalRead(pin[i]) ==LOW){
  key[i] = !key[i];

tu indichi che key abbia il valore invertito di key stessa ma solo se il pulsante è nello stato low, e questo viene invertito ad ogni ciclo di for se il pulsante è low mentre non succede nulla se il pulsante è high.

Per fare quello che vuoi basta scrivere semplicemente:

for (int i= 0;i<3 ; i++)
  {
  key[i] = digitalRead(pin[i]);
  ]

Grazie per l 'aiuto ho modificato il codice in questo modo ma non rivela più la pressione dei pulsanti.
allego il codice.

[code]
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

int key[3] = {HIGH,HIGH,HIGH};
int pin[3]= {5,6,7};


int  banconota10  = 0;
int  banconota20  = 0;
int  sommapar = 0;

void setup() {
    lcd.init();
    lcd.backlight();
    lcd.setCursor(1,0);
    lcd.print("WIN GAMES");
    lcd.setCursor(0,1);
    lcd.print("TOTALI");  

    
for (int i= 0;i<3 ; i++){
  pinMode(pin[i],INPUT_PULLUP);
}
Serial.begin(9600);
}

void loop() {
for (int i= 0;i<3 ; i++){
  key[i] = digitalRead(pin[i]);
  delay(200);

 
 }

for (int i= 0;i<3 ; i++){
  if(key[i]== LOW){

    Serial.print("PIN");
    Serial.print(pin[i]);
    Serial.print("     BANCONOTA EURO ");
    if (pin[i]==6)
     banconota20 = banconota20 + 20;
     sommapar = banconota20 +  banconota10;
    Serial.println("20");
     if (pin[i]==7)
     banconota10 = banconota10 + 10;
     sommapar = banconota20 +  banconota10;
    Serial.println("10");
  }else{
    Serial.print("PIN");
    Serial.print(pin[i]);
    Serial.println("  ");
    
    
  }
}

  lcd.setCursor(8, 1);  
       lcd.print(sommapar); 

}

[/code]

Ma nemmeno se mantieni il pulsante premuto succede nulla? :confused: Sarà un problema elettrico, dal listato dovrebbe variare quanto inviato con serial.print in base alla pressione dei pulsanti

Allora, ho alcune cosette da consigliarti.

Primo, indenta bene. Non per questioni estetiche ma soprattutto per farti capire ad esempio che questo codice:

    if (pin[i]==6)
     banconota20 = banconota20 + 20;
     sommapar = banconota20 +  banconota10;
    Serial.println("20");

non credo che faccia quello che pensi debba fare perché se non metti le graffe, la if() in caso sia soddisfatta eseguirà solamente la prima istruzione (banconota20) e non anche le successive che vengono eseguite sempre e comunque (quindi ad esempio calcola inutilmente 2 volte sommapar).
Per indentare automaticamente premi Ctrl-T nell’IDE ma abituati a scrivere con cura le istruzioni.

Secondo, non ho capito perché fai un delay(200) dopo ogni lettura di un pin. Se vuoi fare il debounce devi farlo solo se lo stato cambia! Attualmente se leggi 3 pulsanti e per ognuno attendi 200mS fai poco più di una lettura al secondo (e se un impulso dura di meno rischi di non leggerlo).

Terzo, hai 3 pulsanti ma ne controlli solo 2, il pin 5 che fine fa?..

Inoltre ti consiglio di mettere anche qualche #define per i valori di configurazione, ad esempio i pin.

Quindi prova questo codice, vedi cosa ho cambiato (ovviamente se hai domande chiedi pure) e soprattutto se è questo che volevi fare.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

#define MONETA 5
#define BANCONOTA20 6
#define BANCONOTA10 7

int key[3] = {HIGH,HIGH,HIGH};
int pin[3]= {MONETA, BANCONOTA20, BANCONOTA10 };

int  banconota10  = 0;
int  banconota20  = 0;
int  sommapar = 0;

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(1,0);
  lcd.print("WIN GAMES");
  lcd.setCursor(0,1);
  lcd.print("TOTALI");  

  for (int i= 0;i<3 ; i++)
  {
    pinMode(pin[i],INPUT_PULLUP);
  }
  Serial.begin(9600);
}

void loop() 
{
  int k;
  
  for (int i= 0;i<3 ; i++)
  {
    k = digitalRead(pin[i]);
    if ( k != key[i] )
    {
      key[i] = k;
      delay(50); // Debounce software
    }
  }

  for (int i= 0;i<3 ; i++)
  {
    if(key[i]== LOW)
    {
      Serial.print("PIN");
      Serial.print(pin[i]);

      switch (pin[i]) 
     {
        case MONETA:
          // Mettere qui i calcoli per la moneta
          Serial.println(" MONETA");
          break;
        case BANCONOTA20:
          banconota20 = banconota20 + 20;
          sommapar = banconota20 +  banconota10;
          Serial.println(" BANCONOTA 20");
          break;
        case BANCONOTA10:
          banconota10 = banconota10 + 10;
          sommapar = banconota20 +  banconota10;
          Serial.println(" BANCONOTA 10");
          break;
      }
      Serial.print("Totale = ");
      Serial.println(sommapar);    
    }
  }
  
  lcd.setCursor(8, 1);  
  lcd.print(sommapar); 

}

Buona sera a tutti un grazie particolare a" DocDoc",
il codice che hai postato funziona in parte perchè lo stato del pin non torna nello stato iniziale velocemente
e il contatore continua a conteggiare velocemente .

Dopo un paio di tentativi ho messo il "delay(300); // Debounce software"

va meglio nel ritorno dello stato ma mi salta qualche lettura del pin.

WinGamesyun:
Dopo un paio di tentativi ho messo il "delay(300); // Debounce software"
va meglio nel ritorno dello stato ma mi salta qualche lettura del pin.

Credo che tu abbia problemi proprio di rimbalzi sui pulsanti, e con delay(300) attendi 3 decimi di secondo per ogni tasto premuto o rilasciato per questo non hai rimbalzi ma perdi alcuni click, 300ms sono decisamente troppi.

Però prima cosa: parli di banconote, quindi questi non saranno veri pulsanti ma l'uscita di un qualche lettore di banconote (che teoricamente non dovrebbe avere rimbalzi) è così?

Per seconda cosa dicci esattamente come hai collegato i pulsanti (fai uno schemino anche a mano e fotografato, e/o fotografa il circuito) e quali pulsanti stai usando.

Poi prova a premere e tenere premuto un pulsante un paio di secondi e poi rilascialo, e riporta qui con copia/incolla l'output del monitor seriale.

In ogni caso ti consiglio comunque un debounce hardware, sono collegamenti semplici (dovrai solo aggiungere una resistenza e un condensatore per pulsante) a quel punto puoi anche rimuovere del tutto il delay():

Buongiorno.
Hai ragione ho collegato una scheda tra il lettore di banconote e la scheda madre di un cambiamonete che individua tutte le transazioni e da un 'impulso a caduta di circa 100 ms per ogni banconota .
Il costruttore di questa schedina mi ha solo consigliato di mettere la funzione di pullup .
Più tardi metto la foto e le caratteristiche della scheda.

WinGamesyun:
individua tutte le transazioni e da un 'impulso a caduta di circa 100 ms per ogni banconota .

Ecco perché delay() superiori a 100 ms ti fanno perdere impulsi.

Però a meno che il lettore non dia impulsi meccanicamente (100ms non credo lo sia), il problema potrebbe essere proprio nel cablaggio e/o in come il lettore gestisce quelle sue uscite dal punto di vista elettrico. Una uscita digitale TTL non può avere rimbalzi, se ci sono c’è qualcosa da verificare.

Intanto fatti un programmino ancora più semplice collegando un solo pin e mostrando sulla seriale lo stato del pin in continuo e vedi cosa ne ottieni (posta poi qui l’output), una cosa di questo tipo, collegando solo il pin 6:

void setup()
{
  Serial.begin(9600);
  pinMode(pin[i],INPUT_PULLUP);
}

void loop() 
{
  Serial.print(digitalRead(6));
  Serial.print(" ");
  delay(10);
}

PS: a questo punto una volta capito il problema, magari meglio gestire gli impulsi con gli interrupt, ma ne parliamo dopo… :wink:

Buona sera ,sono appena rientrato da lavoro ho trovato lo schema della scheda che sto provando a collegare.
cosi descrive l’uscita del pin: Questo pin open collector darà un segnale negativo per 100ms
tutte le volte che l’ accettatore accetterà una banconota.

Se è open collector e poi va a GND è corretto mettere la pullup, se non ci sono altre cose strane dovrebbe funzionare correttamente, per cui inizia a fare la prova con un singolo pin (ma tu stai provando il programma con il lettore, o lo simuli con i pulsanti??) e posta il risultato.

Ciao ti spiego io sto usando un lettore di banconote con protocollo cctalk
Con una schedina che mi converte il segnale cctalk a impulsi
Con il codice che mi hai consigliato funziona bene nel senso che
Non salta nessuno impulso ma legge molte volte in più,
l’impulso.
Nella prova che ho fatto era senza il circuito con la resistenza.

WinGamesyun:
Ciao ti spiego io sto usando un lettore di banconote con protocollo cctalk Con una schedina che mi converte il segnale cctalk a impulsi

Ok quindi non dovrebbero esserci problemi di rimbalzi perché non è nulla di meccanico, almeno per il segnale.

Con il codice che mi hai consigliato funziona bene nel senso che Non salta nessuno impulso ma legge molte volte in più, l’impulso.

Se parli dell’ultimo codice, quello con il solo loop si, è normale. Ma se posti qui il risultato (copia/incolla del monitor seriale) magari capiamo meglio. Anzi prova questo codice che dà anche le tempistiche:

void setup()
{
  Serial.begin(9600);
  pinMode(pin[i],INPUT_PULLUP);
}

void loop() 
{
  Serial.print(millis());
  Serial.print(" ");
  Serial.print(digitalRead(6));
  Serial.print(" ");
  delay(10);
}

Nella prova che ho fatto era senza il circuito con la resistenza.

L’uscita è open collector e tu hai INPUT_PULLIP quindi non dovrebbe avere problemi.

Buongiorno questo è il risultato inserendo una sola banconota .

8846 0  BANCONOTA 20
Totale = 20
8857 0  BANCONOTA 20
Totale = 40
8868 0  BANCONOTA 20
Totale = 60
8879 0  BANCONOTA 20
Totale = 80
8890 0  BANCONOTA 20
Totale = 100
8901 0  BANCONOTA 20
Totale = 120
8912 0  BANCONOTA 20
Totale = 140
8923 0  BANCONOTA 20
Totale = 160
8934 0  BANCONOTA 20
Totale = 180
8945 0  BANCONOTA 20
Totale = 200
8956 0  BANCONOTA 20
Totale = 220
8967 0  BANCONOTA 20
Totale = 240
8978 0  BANCONOTA 20
Totale = 260
8989 0  BANCONOTA 20
Totale = 280
9000 0  BANCONOTA 20
Totale = 300

Si, ma io parlavo dell’ultimo listato, che mostra solamente i tempi del segnale, fatto questo volevo passare al “vero” programma, riprendendo da lì.

Rivedendo il mio listato però mi sono accorto che non era del tutto corretto.

Per cui prova comunque prima il semplice dump dei segnali:

void setup()
{
  Serial.begin(9600);
  pinMode(pin[i],INPUT_PULLUP);
}

void loop() 
{
  Serial.print(millis());
  Serial.print(" ");
  Serial.print(digitalRead(6));
  Serial.print(" ");
  delay(10);
}

e posta l’output.

Poi prova questa versione, nella quale ho semplicemente aggiunto il reset del valore di key[ i ] (se diventava LOW restava LOW e quindi continuava a sommare) e tolto il delay (che non serve il debounce se non parliamo di pulsanti fisici) e messo solo alla fine del loop():

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

#define MONETA 5
#define BANCONOTA20 6
#define BANCONOTA10 7

int key[3] = {HIGH,HIGH,HIGH};
int pin[3]= {MONETA, BANCONOTA20, BANCONOTA10 };

int  banconota10  = 0;
int  banconota20  = 0;
int  sommapar = 0;

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(1,0);
  lcd.print("WIN GAMES");
  lcd.setCursor(0,1);
  lcd.print("TOTALI");  

  for (int i= 0;i<3 ; i++)
  {
    pinMode(pin[i],INPUT_PULLUP);
  }
  Serial.begin(9600);
}

void loop() 
{
  int k;
  
  for (int i= 0;i<3 ; i++)
  {
    k = digitalRead(pin[i]);
    if ( k != key[i] )
      key[i] = k;
      
    if(key[i] == LOW)
    {
      Serial.print("PIN");
      Serial.print(pin[i]);

      switch (pin[i]) 
     {
        case MONETA:
          // Mettere qui i calcoli per la moneta
          Serial.println(" MONETA");
          break;
        case BANCONOTA20:
          banconota20 = banconota20 + 20;
          sommapar = banconota20 +  banconota10;
          Serial.println(" BANCONOTA 20");
          break;
        case BANCONOTA10:
          banconota10 = banconota10 + 10;
          sommapar = banconota20 +  banconota10;
          Serial.println(" BANCONOTA 10");
          break;
      }
      Serial.print("Totale = ");
      Serial.println(sommapar);    
      key[i] = HIGH;
    }
  }
  
  lcd.setCursor(8, 1);  
  lcd.print(sommapar); 

}

Quando funziona tutto, magari se vuoi approfondiamo anche il discorso interrupt, se ti interessa.
Fammi sapere

Grazie ancora per la tua disponibilità.
Sono tornato a lavoro,piu tardi rientro a casa e faccio tutte le prove .

Buona sera ora posterò il risultato del test millis:10721 0 10731 0 10741 0 10752 0 10762 0 10772 0 10782 0 10793 0 10804 0 10814 0 10824 0 10834 0 10845 0 10855 0 10865 0 10875 0 10887 0 10897 0 10907 0 10917 0

Questa invece e con il tuo ultimo sketch senza delay:

PIN6 BANCONOTA 20
Totale = 20
PIN6 BANCONOTA 20
Totale = 40
PIN6 BANCONOTA 20
Totale = 60
PIN6 BANCONOTA 20
Totale = 80
PIN6 BANCONOTA 20
Totale = 100
PIN6 BANCONOTA 20
Totale = 120
PIN6 BANCONOTA 20
Totale = 140
PIN6 BANCONOTA 20
Totale = 160

Ok. E il codice quale é?