Monitor Seriale Risposta singola

Salve,
sto provando a scopo didattico eseguire l'accensione fissa di un led che poi si dovrebbe leggere nel monitor seriale Led Acceso ma solo una volta.
Io l'ho scritto il banale codice solo che non arrivo a capire come fargli stampare la scritta una sola volta.
tutte le volte mi esce la scritta ripetitiva Led Acceso.
Esiste una stringa che faccia scrivere una sola volta?

pseudo codice:

se stato_precedente_LED != stato_LED
    stampo stato_LED
    stato_precedente_LED = stato_LED

No, non esiste. Quando serve si può creare una funzione che svolga questo compito quando chiamata. Il codice scritto dentro la funzione loop() viene eseguito ciclicamente, la funzione termina e re-inizia all'infinito.

Se posti lo sketch che hai realizzato proviamo a modificarlo secondo necessità. Copia lo sketch con arduino IDE, qui nell'editor dei post del forum clicca su pulsante "<code>" e premi CTRL+v.

Ciao.

Per iniziare posto questo semplice sketch.
In questo momento si accende il led Fisso e nel serial monitor esce la scritta Led Acceso ( al infinito )
quello che volevo capire era come stampare la scritta una sola vota se possibile.

// C++ code
// Accensione di un Led (senza lampeggio)

const int PinLed = 11;
bool prevLedState; // stato precedente
void setup() {
  pinMode(PinLed, OUTPUT);
  Serial.begin(9600);
}
void loop() {
 prevLedState = digitalRead(PinLed);
  digitalWrite(PinLed, HIGH);
  if (digitalRead(PinLed) != prevLedState) {
    Serial.println("LED acceso");
  }
}

Hai letto attentamente la risposta di "andreaber"? Ti ha chiaramente spiegato come devi fare utilizzando una variabile per memorizzare lo stato del LED ... ora a TE trasformare il tutto in codice.

Guglielmo

Ci sono diversi modi per ottenere il comportamento desiderato, in questo caso Led Acceso è la stringa che deve comparire nel serial monitor solo se il led è acceso e se lo è deve comparire una sola volta.

bool prevLedState; // stato precedente
void loop() {
  prevLedState = digitalRead(PinLed);
  digitalWrite(PinLed, HIGH);
  if (digitalRead(PinLed) != prevLedState) {
    Serial.println("LED acceso");
  }
}

La variabile prevLedState ha valore false, mentre digitalRead(pinLed) ha valore true, per cui l'espressione tra parentesi dopo if sarà questa: Se (true != false) {...
Questo accade al primo ciclo del loop, tutti i cicli successivi, invece prevLedState ha valore true e l'espressione precedente risulta: Se (true != true).

Le cose cambiano di molto quando l'obbiettivo è di fare comparire la stringa in relazione allo stato del led, stampando una sola volta se lo stato precedente è diverso da quello corrente. Quindi Led Acceso quando è passato da spento ad acceso. Invece Led Spento quando è passato da acceso a spento. Il passaggio di stato di dice transizione: 1 -> 0 o l'inverso 0 -> 1.

Ciao.

Ho modificato lo sketch che avevo posto e sembra funzionare.

Prova a partire dallo stato inverso, cioè il led lo accendi nel setup() e nel loop invece lo spegni, vedrai che comparirà la scritta Led Acceso quando in realtà è spento.

void loop() {
  
  if (digitalRead(PinLed) == LOW) {
    Serial.println("LED acceso");
    digitalWrite(PinLed, HIGH);
  }
}

Questo è ben differente dal precedente, l'espressione ora è:
Se (LOW == LOW) al primo ciclo.
Tutti i cicli successivi invece: Se (HIGH == LOW) la quale viene valutata falsa e non esegue il blocco di codice delimitato da graffe associato al comando if.

Ciao.

Non capisco perchè non vada;
faccio accendere il led nel setup ed il resto dovrebbe essere giusto, ma non va.

const int PinLed = 13;
bool prevLedState;  // stato precedente

void setup() {

  Serial.begin(9600);

  pinMode(PinLed, OUTPUT);
  digitalWrite(PinLed, HIGH);
}

void loop() {

  if (digitalRead(PinLed) == LOW) {
    Serial.println("LED acceso");
    digitalWrite(PinLed, HIGH);
  }
}

Non so se possa dipendere da cio ma invertendo nel loop LOW con HIGH e HIGH con LOW allora funziona ma ripeto non so se sia esatto fare cosi.

Risolvi questa "istruzione" prima trascrivendola:

if   (digitalRead(PinLed)     ==       LOW) 
Se   (        HIGH          uguale a   LOW) { esegui }

Visto che HIGH uguale a LOW risulta falsa, non esegue il blocco delimitato dalle graffe.

  if (digitalRead(PinLed) == LOW) {
    Serial.println("LED acceso");
    digitalWrite(PinLed, HIGH);
  } else { // altrimenti
    Serial.println("LED spento");
    digitalWrite(PinLed, LOW);
  }
  delay(2000); // provvisorio solo per vedere il led accendersi e spegnersi e non intasare il monitor seriale di scritte.

Ritorniamo al problema principale, cioè eseguire una sola volta una porzione di codice all'interno di un ciclo infinito. Serve una variabile globale inizializzata a false e un if.

bool oneShot = false; // oneShot un colpo solo
void loop() {
  if (oneShot == false) {
    if (digitalRead(PinLed) == LOW) {
      Serial.println("LED acceso");
      digitalWrite(PinLed, HIGH);
    } else { // altrimenti
      Serial.println("LED spento");
      digitalWrite(PinLed, LOW);
    }
    oneShot = true;  // il colpo è stato eseguito e ne prendo nota
  } // end if (oneShot == false)
}

Adesso funzionerà sia che nel setup accendi o spegni il led.
Ciao.

Perché, come si è già discusso in passato, andrebbe prima scritta bene in pseudocodice/italiano la logica . Con il codice del post #9 in pratica hai scritto:

SETUP:
    PREDISPONI SERIALE
    ACCENDI LED

LOOP:
    SE LED SPENTO:
        SCRIVI LED ACCESO
        ACCENDI LED

Ed è subito evidente che la condizione "LED SPENTO" sarà sempre falsa, perché lo hai già acceso prima.

Non è giusto, nel senso che sembra un tentativo a caso più che qualcosa di appositamente progettato. Prima si deve "progettare" in pseudocodice/italiano chiaro ed eplicito quello che si vuole ottenere.

...

Quindi, invece di:

SETUP:
    PREDISPONI SERIALE
    ACCENDI LED

LOOP:
    SE LED SPENTO:
        SCRIVI LED ACCESO
        ACCENDI LED

cosa realmente volevi ottenere? (descrivendolo in italiano allo stesso modo)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.