Chiarimenti su un if

Salve a tutti seguivo una video lezione,ma vi è venuto un dubbio sua una parte del codice e chiedo a voi di aiutarmi a capire,ecco il codice:

  int ledPin = 9;
int pulsantePin = 2;
int ledStato = LOW;
int pulsanteStato = LOW;

void setup(){
  pinMode(ledPin, OUTPUT);
  pinMode(pulsantePin, INPUT);
  digitalWrite(ledPin, ledStato);
}

void loop(){
  int lettura = digitalRead(pulsantePin);
  if(lettura != pulsanteStato and lettura == HIGH){
    ledStato = !ledStato;
    digitalWrite(ledPin, ledStato);
  }
  pulsanteStato = lettura;
  delay(10);
}

Non riesco a capire una cosa nel codice , il signore che spiegava ,inizialmente mente scriveva il codice
scriveva:

if(lettura != pulsanteStato

dicendo però non era sufficiente perché questa situazione sempre vera e qundi codice tra le graffe veniva eseguito, facendo un po di ragionamento non mi trovo cioè sè il pulsante clikkato nella variabile lettura c'è HIGH e quindi if sarà vero perché lettura e diverso di pulsanteStato ( che stato dichiarato LOW),se rilascio il pulsante nella variabile lettura c'è LOW ,if non risulta più vero ,perche lettura non è più diversa da pulsanteStato (LOW) ma uguale giusto?perché dice sempre vera? Cosa va nel ragionamento che faccio che non va ?
Grazie a tutti

Non so cosa ha detto o cosa ha pensato dicendo quello che ha detto.

Suppongo che il pin é HIGH quando il pulsante é premuto.

int lettura = digitalRead(pulsantePin);
  if(lettura != pulsanteStato and lettura == HIGH){
    ledStato = !ledStato;
    digitalWrite(ledPin, ledStato);
  }
  pulsanteStato = lettura;
  delay(10);

Questo é un codice tipico dove si vuole trovare i cambi di stato ovvero la prima volta dove uno stato cambia. Questo vuol dire che alla prima attuazione del pulsante il LED si accende e al successivo si Spegne ecc.

Nella variabile pulsanteStato é memmorizzato lo stato del pulsante nello precendente ciclo loop(), in questo caso LOW perché il pulante non é premuto.
Percui nel primo passaggio del loop() quando stai premendo il pulsante la lettura é HIGH e pulsanteStato é LOW perché prima il pulsante non era premuto. Entrambe le condizioni nel IF sono vere e il LED viene acceso. Alla fine la variabile pulsanteStato riceve il valore attuale dello pulsante.
Il delay serve per eliminare il bounce del pulsante (Il contatto chiudendo salta alcune volte e percui risulta un aprire/chiudere di 3-4V prima che sia chiuso. Switch - Wikipedia I microcontroller sono abbastanza veloci da rilevare questo ripatuto aprire/chiudere e lo leggono come un ripetuto azionamento del pulsante.

Ciao Uwe

Cioè facendo un ragionamento più lento lo possiamo sintetizzare in questo modo:
Supponiamo di mettere il dito sul pulsante senza alzare
Variabile lettura diventa HIGH diversa da pulsanteStato ==HIGH condizioni vera avviene il cambio di stato del led nella variabile pulsanteStato =lettura cioè pulsanteStato HIGH loop torna da capo nel if lettura risulta HIGH pulsanteStato HIGH e non succede niente appena alziamo il dito da pulsante variabile lettura diventa LOW PulsanteStato HIGH sono diversi ma non uguale a lettura ==HIGH quindi non succede niente,loop continua ad seguire il codice pulsanteStato =lettura diventa pulsanteStato LOW e viene inserito nel if ,quindi ci troveremo nelle situazione del if lettura LOW pulsanteStato LOW al prossimo clikko sul pulsante si avrà il cambio di stato giusto come ragionamento?
Grazie

È giusto. Quel codice nel suo insieme è un rilevatore dell'istante di pressione, insensibile al momento del rilascio e alla permanenza nei due livelli.

Si compone di un rilevatore di variazione (il confronto con la lettura precedente, e l'aggiornamento di lettura precedente = lettura attuale per predisporsi al prossimo giro) e una condizione AND per considerare buona solo la variazione da non premuto a premuto, e ignorare l'altra.

Salve provo a fare qualche esercizio :slight_smile:

 : [Select]
  int ledPin = 9;
int pulsantePin = 2;
int ledStato = LOW;
int pulsanteStato = LOW;
int prova=HIGH;
void setup(){
  pinMode(ledPin, OUTPUT);
  pinMode(pulsantePin, INPUT);
  digitalWrite(ledPin, ledStato);
}

void loop(){
  int lettura = digitalRead(pulsantePin);
  if(lettura != pulsanteStato and lettura == HIGH){
    ledStato = !ledStato;
    digitalWrite(ledPin, ledStato);
 
While  (prova==ledStato){
              crono++;
Serialprintln (crono);

 }

 }
  pulsanteStato = lettura;
  delay(10);
}

In pratica volevo provare un cronometro in seriale,mi parte al clikko del pulsante ,ma poi non si ferma e come nel while non cambia ledStato al prossimo clikko,qualcuno mi può spiegare grazie sono ancora in fase di studio e prove grazie mille

Il ciclo while non termina mai, una volta entrati la condizione controllata è sempre vera.

While  (prova==ledStato){
              crono++;
Serialprintln (crono);
 }

Nel ciclo while deve SEMPRE essere una lettura o aggiornamento delle variabili che vengono controllati (prova==ledStato) per poter uscire. Devi in qualche modo variare la variabile ledStato.

Ciao Uwe

Grazie quindi in questo modo dovrebbe funzionare (ora sono a lavoro non posso provare)

 While  (prova==ledStato){
              ledStato ==HIGH;
                crono++;
Serialprintln (crono);
 }

ago1980:
Grazie quindi in questo modo dovrebbe funzionare (ora sono a lavoro non posso provare)

ago1980:
Grazie quindi in questo modo dovrebbe funzionare (ora sono a lavoro non posso provare)

Credo proprio di no, visto che "prova" è sempre HIGH se imposti anche ledStato a HIGH quindi resta comunque all'infinito nel ciclo. Tu dentro al ciclo dovresti rileggere lo stato del pulsante e quando viene premuto la prima volta deve partire il conteggio, ed una seconda volta deve fermare il conteggio. Tra l'altro non dichiari neanche la variabile "crono" quindi non compila.

Per farti fare esercizio, prova questo codice e se funziona (anche io sono al lavoro e l'ho scritto al volo modificando il tuo) a parte l'indentazione ma che è molto importante imparare da subito a farla correttamente soprattutto quando farai programmi più lunghi di questi, cerca di capire le differenze col tuo e dimmi secondo te se/come funziona:

int ledPin = 9;
int pulsantePin = 2;
int ledStato = LOW;
int pulsanteStato = LOW;
long crono = 0;
void setup(){
  pinMode(ledPin, OUTPUT);
  pinMode(pulsantePin, INPUT);
  digitalWrite(ledPin, ledStato);
}

void loop(){
  int lettura = digitalRead(pulsantePin);
  if(lettura != pulsanteStato and lettura == HIGH){
    ledStato = !ledStato;
    digitalWrite(ledPin, ledStato);
	delay(10);
  }
  pulsanteStato = lettura;
  if ( ledStato == HIGH ) {
	crono++;
	Serial.println(crono);
        delay(100);
  }
}

Si così funziona grazie

Bene! Ma hai capito la differenza tra i due metodi? Quale sarebbe? Perché non è solo per farti funzionare il codice, ma per capire perché funziona o non funziona una cosa, ed insieme imparare qualcosa in più! :wink: