Progetto Arduino

Salve, sto sviluppando un progetto, ho 10 cavi da collegare in due ordini differenti, quando sono ben collegati si accendono 3 led. Per vedere i collegamenti uso un partitore di tensione con resistenze diverse per ogni cavo.
Il problema è che la verifica dell'ordine deve avvenire dopo aver premuto un pulsante e rilasciarlo, se rimane premuto non deve succedere niente, funziona tutto tranne la parte del pulsante, ovvero funziona dopo che lo premo un paio di volte, uso quello dell'immagine e il codice è questo:

int Vd0,Vd1,Vd2,Vd3,Vd4;      //tensione rilevata
float V0,V1,V2,V3,V4;      //tensione per ogni cavo
boolean val;      //controllo pulsante
int condizione_pulsante;
boolean ultima_condizione_pulsante;
void setup() {
  pinMode(8,INPUT_PULLUP);      //pulsante
  pinMode(11,OUTPUT);      //led1
  pinMode(10,OUTPUT);      //led2
  pinMode(9,OUTPUT);      //led3
}

void loop() {
  val=digitalRead(8);
  if(val==HIGH){
    condicion_boton=1;
  }
  else{
    condicion_boton=0;
  }
  delay(500);
  ultima_condizione_pulsante=digitalRead(8);
  if((condizione_pulsante==1)&&(ultima_condizione_pulsante==LOW)){
    
    //misura tensione punti di connessione

    //calcolo tensione cavi

  }
  
  //verifica ordine cavi
  //accensione led

}

Ciao,

che tipo di Arduino stai utilizzando? non hai uno schema elettrico del tuo progetto?

Cmq non è il massimo utilizzare il dalay in quanto blocca il micro dovresti fare una differenza sui tempi utilizzando millis.. Normalmente per l'anti-rimbalzo vanno bene 50/80 ms

Utilizzo Arduini Nano con uno shield, non ho lo schema elettrico. Sono sicuro che i collegamenti hardware siano fatti bene, credo di avere un problema col codice

>VittoM: evitati tanti problemi ed inutili ritardi nel software, il debouncing fallo hardware ... basta un paio di resistenze ed un consensatore. Ti allego uno schema ...

Guglielmo

Se volessi risolvere il problema senza modificare la parte hardware?

Dal codice che hai postato, la cosa strana non è che non funziona il pulsante ma che funzione dopo un po' di volte che lo premi.

Mi sa che hai ripulito un po' troppo il codice prima di postarlo.
Es. condicion_boton è usato ma non dichiarato.
condizione_pulsante è dichiarato e inizializzato ma non più modificato
usi variabili di tipo diverso per fare le stesse cose, boolean int e poi mescoli valori e costanti.
Questo denota un po' di confusione in generale.
Procedendo in questo modo oltre ai problemi che puoi inserire nella stesura di codice rischi anche di aggiungerne di altri ben più subdoli evitabili semplicemente con un po' di ordine.

Visto che il codice che hai testato non è quello postato perchè mi sa che non si compila neppure, il mio consiglio è di provare a mettere il codice corretto cercando di ripulirlo un po' per evitare errori collaterali?
Magari dichiara tutto int e usa solo HIGH e LOW che non sono altro che 1 e 0, invece di valori booleani che poi testi per == 0...

Il codice completo è questo:

int Vd0,Vd1,Vd2,Vd3,Vd4;      //tension detectada
float V0,V1,V2,V3,V4;      //tension por cada cable conectado
int val;      //control boton
int condicion_boton;
int ultima_condicion_boton;
void setup() {
  pinMode(8,INPUT_PULLUP);      //boton
  pinMode(11,OUTPUT);      //led1
  pinMode(10,OUTPUT);      //led2
  pinMode(9,OUTPUT);      //led3
}

void loop() {
  val=digitalRead(8);
  if(val==1){
    condicion_boton=1;
  }
  else{
    condicion_boton=0;
  }
  delay(500);
  ultima_condicion_boton=digitalRead(8);
  if((condicion_boton==1)&&(ultima_condicion_boton==0)){
    Vd0=analogRead(A0);     //tension A0
    Vd1=analogRead(A1);     //tension A1
    Vd2=analogRead(A2);     //tension A2
    Vd3=analogRead(A3);     //tension A3
    Vd4=analogRead(A4);     //tension A4

    //calculo caida de tension por cada resistencia
    V0=Vd0*5.0/1023;
    V1=Vd1*5.0/1023;
    V2=Vd2*5.0/1023;
    V3=Vd3*5.0/1023;
    V4=Vd4*5.0/1023;
  }
  
  //verifica cables conectado corectamente
  if(((V0>=2.22)&&(V0<=2.32))&&((V1>=2.95)&&(V1<=3.05))&&((V2>=2.67)&&(V2<=2.77))&&((V3>=4.49)&&(V3<=4.59))&&((V4>=1.35)&&(V4<=1.45))){     //primera combinacion
    digitalWrite(11,HIGH);      //encender luces
    digitalWrite(10,HIGH);
    digitalWrite(9,HIGH);
  }
  else if(((V0>=2.22)&&(V0<=2.32))&&((V1>=4.49)&&(V1<=4.59))&&((V2>=1.35)&&(V2<=1.45))&&((V3>=2.95)&&(V3<=3.05))&&((V4>=2.67)&&(V4<=2.77))){      //segunda combinacion
    digitalWrite(11,HIGH);      //encender luces
    digitalWrite(10,HIGH);
    digitalWrite(9,HIGH);
  }
  else{
    digitalWrite(11,LOW);     //apagar luces
    digitalWrite(10,LOW);
    digitalWrite(9,LOW);
  }
}

Tieni premuto il pulsante per almeno mezzo secondo quando fai le prove?
Perchè congeli tutto per mezzo secondo da quando inizi la lettura iniziale a quando fai quella finale.
Se pigi e rilasci dentro questo mezzo secondo non intercetti l'evento.
Pigiando un po' di volte, statisticamente prima o poi becchi il caso in cui pigi prima di iniziale il delay e rilasci durante il delay intercettando l'evento correttamente, altre volte, mi sa, pigi e rilasci tutto dentro lo stesso delay leggendo sempre 0.

Se premo e rilascio subito non si accendono, quando tengo premuto per mezzo secondo o più si accendono, dovrei ottenere il contrario

Ho risolto con questa parte di codice:

void loop(){
  val=digitalRead(8);
  delay(200);
  condicion_boton=digitalRead(8);
  delay(200);
  ultima_condicion_boton=digitalRead(8);
  if(((condicion_boton==0)&&(ultima_condicion_boton==1)||val==1)){
//codice
}

Grazie mille per i consigli :slight_smile:

il problema è come usi il delay
leggi il pulsante, congeli tutto per mezzo secondo, rileggi il pulsante.

Se il pulsante lo premi e rilasci rapido e tutto dentro questo mezzo secondo non scatta nulla perchè il delay ha congelato tutto.
Se tieni premuto, anche se salti il primo mezzo secondo, arriverai ad uno successivo con lettura 1 iniziale e rilascio dentro il mezzo secondo, condizione che ti fa partire la tua logica di verifica.

Qui il problema è il debounce sul pulsante, da risolvere in qualche modo per non avere letture istantanee di acceso spento appunto per queste oscillazioni.

La cosa migliore sarebbe di farlo hardware, per farlo software potresti usare un delay di 50ms (non ho mai provato per cui non so darti un valore più esatto ma si mormora che sia sufficiente)
Eliminare il delay da 500 e lasciare il loop che frulli con il minimo ritardo per il debounce che ho detto sopra.
Ad ogni ciclo testi una variabile che riporta il valore del pulsante al giro prima con la nuova lettura.
A fine del loop salvi su questa variabile il valore letto nel loop usandolo quindi come valore precedente alla successiva iterazione.

Dentro il loop se la vecchia è 1 e la nuova è 0 parti con la tua logica di test.

Non so se mi sono spiegato sufficientemente bene.
In pratica cambi il momento in cui scrivi nelle tue due variabili e non metti il delay da mezzo secondo ma solo uno breve dopo la lettura per evitare il debounce.
Con questo delay di debounce da 50 millisecondi intercetti pigiate anche rapide, non rapidissime ma ti sfido a fare pigia e rilascio in meno di 50 millisecondi.

Mi sa che così hai solo mitigato il problema, ti sembra risolto ma invece lo hai reso solo meno probabile.
Inoltre hai creato una nuova finestra da 200 mS su cui perderti delle letture.

Diciamo che premi il pulsante poco prima che inizi il loop, questo parte, legge 1 e aspetta 200, rilegge e vede ancora 1, poco dopo, durante il secondo delay(200) rilasci il pulsante, il sistema non si è accorto del rilascio.
Al giro successivo parti con 0 e magari non pigi nulla, dopo 200 mS legge ancora 0 e non fa niente.
Morale, non ti sei accorto del click.

Il pulsante non sta sull'I/O 53?

Comunque, se proprio ti fa fatica aggiungere un condensatore, puoi fare così:

#define PULSANTE 8
byte pulsPremuto=0; // 1: Pulsante premuto.
unsigned long t0=0; // Per prendere il tempo per l'antirimbalzo.

void setup() {}

void loop()
// ... ... ...
{
if(digitalRead(PULSANTE)==0) {pulsPremuto=1; t0=millis();} // Il pulsante è premuto! Mette pulsPremuto a 1. Prende millis() con t0 e tiene t0 aggiornato finché il pulsante rimane premuto.
if(pulsPremuto && millis()-t0>200) pulsPremuto=0; // Se il pulsante è stato premuto e poi è stato lasciato per più di 200ms, mette pulsPremuto a 0.
}
if(pulsPremuto) {/* Fa quello che deve fare */}
// ... ... ...

Si comporta esattamente come un condensatore e una resistenza con un tempo di 200ms.
Naturalmente, per funzionare bene, il loop deve essere mantenuto veloce.