[RISOLTO]non sempre legge pulsante.

salve, non capisco perché questo semplicissimo codice funziona solo se nel ciclo metto dei "Serrial.print": Al primo clik sul pulsante il led si accende,e rimane acceso, anche dopo altri clik. Il led si spegne solo se ci sono i print. ( se i print sono commentati, il led non si spegne mai). Ho pensato ai rimbalzi, ma in questo caso penso che dovrei vedere qualche farfallio, che invece non vedo.

Ho provato a sostituire i print con dei delay, ma non ho trovato i tempi giusti.

c 'è una spiegazione?

grazie danilo

const int OFF=0;
const int ON=1;
iint led=13;
int pinavvio =0;
int Stato1=0;

void setup()
{
  Serial.begin( 9600 );
  pinMode(pinavvio, INPUT);
  digitalWrite( pinavvio, HIGH );
  pinMode( led, OUTPUT );
}

void loop(){
  avvio();
  //  if (sw_avvio==ON){
  //      test_sonar();
  //      if (sw_avanti==OFF){
  //         avanti();
  //      }
  //  }
}

void avvio(){
  Stato1 = digitalRead(pinavvio);
  Serial.print("Stato1=");
  Serial.println(Stato1);
  if (Stato1==LOW){
    if (sw_avvio==ON){
      //    stop();
      sw_avvio=OFF;
      digitalWrite( led, LOW );
    }
    else{
      sw_avvio=ON;
      digitalWrite( led, HIGH );
    }
  }
}

Ciao Paul, premetto che non son un espertissimo di arduino (mi sono affacciato da poco), ma non sono riuscito a capire cosa devi fare. cmq io ho trovato questo errore:

iint led=13;

una i di troppo

pinMode(pinavvio, INPUT);

pinavvio è il pin del bottone?? cosa è sw_avvio??

io farei un unico void loop. Da quel che leggo il programma funziona cosi: 1) leggi e stampa lo stato del pulsante 1.1) se il bottone non è premuto e se sw_avvio è vero, spegni sw_avvio e spegni il led 1.2)se il bottone non è premuto e se sw_avvio è falso, imposta sw_avvio come vero ed accendi il led

Ma a cosa serve il bottone se il tutto è indipendente da esso??? Quindi la vera variabile è sw_avvio (tra l'altro non dichiarata da nessuna parte). Spiegaci la logica del programma. Ciao

ciao vor_paul E`difficile trovare la causa di un codice malfunzionante ( che non fa quello che vuole l'autore) se il codice non viene compilato a causa di errori di sintassi / di mancanza di definizione variabili.

if (Stato1==LOW){
    if (sw_avvio==ON){
      //    stop();
      sw_avvio=OFF;
      digitalWrite( led, LOW );
    }
    else{
      sw_avvio=ON;
      digitalWrite( led, HIGH );
    }
  }

Questa parte di codice viene ripetuta finche schiacci il pulsante. Il LED viene acceso e spento di continuo. Se il LED resta spento o acceso dopo il rilascio del pulsante dipende solo dal caso.

http://electronics.flosscience.com/Home_LE/Arduino-Lessons/toggle-on-and-off Aggiungerei a quel sketch un delay(10); dopo la lettura del pulsante in modo da fare un debouce.

Ciao Uwe

grazie per le risposte:

per nibbio99
la doppia i di iint è un refuso nella copia, nel programma originale non c’è,diversamente penso che avrei avuto un errore in compilazione.
lo sw_avvio nel programma originale c’è, non ho copiato tutte le dichiarazioni né tutto il setup,

nell’ esempio non ho riportato tutto il programma, ma solo la parte interessata dall’ errore; in loop hocommentato tutto il programma, che si sviluppa su molte subroutines.

la logica della routine avvio è quella del classico flip-flop.

lo sw_avvio serve proprio per poter attivare tutto il programma, che si avvia solo se lo sw_avvvio è in ON.
lo sw_avvio all’ inizio è in OFF, va in ON solo se premo il pinavvio, e rimane in ON (così il programma (loop) esegue le subroutines) fino a quando non premo nuovamente il pinavvio, nel qual caso lo sw_avvio ritorna un OFF (e il programma (loop) non esegue più le subroutines),fino a quando non si ripreme pinavvio e il ciclo riprende.

per uwefed

Non capisco perchè dici che Il LED viene acceso e spento di continuo; mi pare che ci siano le if e le else che dovrebbero impedirlo.

grazie ad entrambi.

Se stai lavorando con dei pulsanti, prevedi un debounce altrimenti non ne esci. Se ti funziona con i Serial.print probabilmente è perché introduci un piccolo ritardo che ti permette di fare una lettura dopo l'altra.

Prova così:

void avvio(){
  if (digitalRead(pinavvio) == LOW) { //leggo il pulsante la prima volta
    delay(50); //piccolo ritardo
    if (digitalRead(pinavvio == LOW) { //nella seconda lettura ho ancora il pulsante premuto
      if (Stato1==LOW){
        if (sw_avvio==ON){
          //    stop();
          sw_avvio=OFF;
          digitalWrite( led, LOW );
        } else{
          sw_avvio=ON;
          digitalWrite( led, HIGH );
        }
      }
    }
  }
}

Dovrebbe funzionare

ancora grazie, si, con il tuo esempio dovrei risolvere il problema dei rimbalzi.

ma il mio problema non dipende (solo) da quello.

Nell'estratto del codice che ho postato non ho inserito una cosa che pensavo ininfluente, e che invece ora ho scoperto essere la causa: utilizzo i due interrup di arduino, attivati anch'essi da pulsanti. Per qualche motivo sembra che siano sempre attivi, quindi il programma sembra bloccato (il led non si spegne) perchè è nelle routine di interrup. Di seguito la parte di codice mancante:

const int OFF=0;
const int ON=1;
int sw_avvio=OFF;
volatile int sw_avanti = OFF;

int triggerPortA = 15;
int echoPortA = 16;
int triggerPortP = 17;
int echoPortP = 18;
int EN1 = 6; //pwm
int IN1a = 7;
//int IN1b = 4;
int EN2 = 9; //pwm  
int IN2a = 8; 
//int IN2b = 12;
int led=13;
int pinavvio =0;
int Stato1=0;

void setup()
{
  Serial.begin( 9600 );
  pinMode(pinavvio, INPUT);
  attachInterrupt(0, destra, CHANGE);
  attachInterrupt(1, sinistra, CHANGE);
  digitalWrite( pinavvio, HIGH );
  pinMode( triggerPortA, OUTPUT );
  pinMode( echoPortA, INPUT );
  pinMode( triggerPortP, OUTPUT );
  pinMode( echoPortP, INPUT );
  pinMode( led, OUTPUT );
}

void loop(){
  avvio();
//    if (sw_avvio==ON){
//        test_sonar();
//        if (sw_avanti==OFF){
//           avanti();
//        }
//    }
}

void avvio(){
  Stato1 = digitalRead(pinavvio);
//  Serial.print("Stato1=");
//  Serial.println(Stato1);
  if (Stato1==LOW){
    if (sw_avvio==ON){
          stop();
      sw_avvio=OFF;
      digitalWrite( led, LOW );
    }
    else{
      sw_avvio=ON;
      digitalWrite( led, HIGH );
    }
  }
}
.........................
............................
..........................

void destra(){
  if (sw_avvio==ON){
  Serial.println("DESTRA");
    if (sw_avanti==ON){
  Serial.println("ANT");
      ost_ant_dst();
    }
    else{
  Serial.println("PST");
      ost_post_dst();
    }
  }
}

void sinistra(){
  if (sw_avvio==ON){
  Serial.println("SINISTRA");
    if (sw_avanti==ON){
  Serial.println("ANT");
      ost_ant_sin();
    }
    else{
  Serial.println("PST");
      ost_post_sin();
    }
  }
}

se commento le istruzioni relative agli interrup (desta / sinistra) oppure se scollego i loro pulsanti, la routine avvio funziona (rimbalzi permettendo).

ora devo capire perché gli interrup si attivono da soli.

danilo

Per esperienza diretta posso dirti che collegare un pulsante ad un interrupt è un'idea [u]sbagliatissima[/u] ;) Una singola pressione, a causa dei rimbalzi, equivale a CENTINAIA di chiamate alla ruotine di interrupt.

me ne sto accorgendo. ma a questo punto come si possono usare gli interrups se non con i pulsanti? mi pare che siano solo digitali, quindi quali altri input si possono utilizzare?

Puoi mettere nell'interrupt un debounce software basato su millis per considerare valido il segnale letto solo dopo che è passato un certo numero di millisecondi dalla prima chiamata alla ISR. Ho fatto una cosa simile di recente ed ha funzionato.

grazie, non conosco la tecnica del Debounce software.Ora mi documento e poi provo. Ho visto che in rete c'è molto materiale al riguardo.

Ora la routine avvio funziona bene: ho solo aggiunto un delay prima di uscire.

Continuano a funzionare male gli interrup, nel senso che se sono attive le istruzioni, il programma si blocca(senza eseguire le routine specfiche) anche senza che i sensori di interrup siano stati toccati.

Ma per questo problema aprirò un altro post, dopo averci pensato ancora un po'. Ora chiudo questo mettendo il risolto.

grazie ancora .

Metti il codice, comunque. Gli interrupt sono molto delicati, vanno gestiti bene.