Accendere LED in base a stato pulsante

Ciao a Tutti,

sto cercando di realizzare un circuito che mi permetta di far lampeggiare un led 5 volte se premo e rilascio un pulsante, dopo i 5 lampeggi il LED si spegne e resta spento fino alla eventuale prossima pressione, e se il pulsante resta sempre premuto il LED deve continuare a lampeggiare fino a che non venga rilasciato il pulsante.

Il SW per il lampeggio 5 volte l'ho trovato in rete e funziona senza problemi, ma non riesco a implementare la parte dove il LED continua a lampeggiare.

Non riesco a capire come far discriminare il pulsante sempre premuto dal pulsante premuto e rilasciato...potete aiutarmi?

Grazie

Potresti provare con una macchina a stati finiti

Premi per vedere il codice
const byte pinPulsante = A0;
const byte pinLed = 13;

enum stato {RIPOSO, LAMPEGGIO, LAMPEGGIO_SE_NECESSARIO} stato = RIPOSO;
const unsigned long mezzaPeriodoDiLampeggio = 500;
const unsigned long MaxLampeggi = 5;
unsigned long contatoreLampeggi;
unsigned long tempoInizio; // Non usato ma potrebbe essere utile

// restituisce true quando il lampeggio è finito
bool lampeggia(bool iniziaLampeggio = false) {
  static unsigned long ultimoTempoLed;
  if (iniziaLampeggio) {
    contatoreLampeggi = 1;
    ultimoTempoLed = millis();
    digitalWrite(pinLed, HIGH);
  } else if (millis() - ultimoTempoLed >= mezzaPeriodoDiLampeggio) {
    digitalWrite(pinLed, (digitalRead(pinLed) == HIGH) ? LOW : HIGH);
    ultimoTempoLed = millis();
    contatoreLampeggi++;
  }
  return contatoreLampeggi >= 2 * MaxLampeggi;
}

bool pulsantePremuto() {
  return digitalRead(pinPulsante) == LOW;
}

void setup() {
  pinMode(pinPulsante, INPUT_PULLUP);
  pinMode(pinLed, OUTPUT);
}

void loop() {
  switch (stato) {
    case RIPOSO:
      if (pulsantePremuto()) {
        lampeggia(true); // forza l'inizio del lampeggio
        tempoInizio = millis();  // Non usato ma potrebbe essere utile
        stato = LAMPEGGIO;
      }
      break;

    case LAMPEGGIO:
      if (lampeggia()) {
        stato = LAMPEGGIO_SE_NECESSARIO;
      }
      break;

    case LAMPEGGIO_SE_NECESSARIO:
      if (!pulsantePremuto()) {
        digitalWrite(pinLed, LOW);
        delay(15); // rimedio anti-rimbalzo rudimentale
        stato = RIPOSO;
      } else lampeggia();
      break;
  }
}

1 Like

le tue specifiche sono abbastanza chiare, ma ci sono comunque delle ambiguità

cosa devi fare se premi, tieni premuto per un poco e poi rilasci:
fa comunque 5 lampeggi?

cosa devi fare se premi a lungo ma "meno" di 5 lampeggi:
interrompi subito o termini il ciclo di 5?
oppure il ciclo di 5 comincia quando "molli" il pulsante?

cose devi fare se premi, tieni premuto a lungo e molli il pulsnte dopo più di 5 lampeggi?
interrompi subito?

cosa devi fare se molli il pulsante "durante" un'accensione di un lampeggio?
attendi il naturale spegnimento della luce oppuri tronchi subito?

a proposito
cosa hai usato per il debounce?

1 Like

Ciao, intanto grazie per la risposta, poi...ottime domande, avevo tralasciato questi dettagli:

cosa devi fare se premi, tieni premuto per un poco e poi rilasci:
fa comunque 5 lampeggi?
si. ma credo sia da aggiungere un T minimo di pressione pulsante per ragionare nel modo corretto

cosa devi fare se premi a lungo ma "meno" di 5 lampeggi:
interrompi subito o termini il ciclo di 5?
oppure il ciclo di 5 comincia quando "molli" il pulsante?
il ciclo inizia quando il pin è HIGH

cose devi fare se premi, tieni premuto a lungo e molli il pulsnte dopo più di 5 lampeggi?
interrompi subito?
si

cosa devi fare se molli il pulsante "durante" un'accensione di un lampeggio?
attendi il naturale spegnimento della luce oppuri tronchi subito?
una volta che il livello HIGH viene letto, inizia la routine

Il sw che uso ora fa lampeggiare il LED 5 volte come il livello è HIGH, e posso tranquillamente lasciare il pulsante che avvengono comunque i 5 lampeggi.

Non riesco a pubblicare il codice perchè ne ho 3versioni e non ricordo quale è quella giusta che gira su Arduino...appena riesco a collegare Dino lo pubblico!

Cercando di esser più chiaro: se HIGH dura meno di 1 sec, faccio 5lampeggi, se dura di più ignora la routine di 5 lampeggi, e semplicemente lampeggio fino a che tengo premuto il pulsante...

ok

se hai un debounce HW è semplice

pubblica quello che hai che vediamo

però non ti do la soluzione, ma ti ci porto con una serie di domande ed indicazioni, perché non do la "pappa pronta" ma voglio far "pensare"

senza per questo intendere nulla, sia chiaro

Avete provato il codice del post N° 2?

Ciao, scusa ma l'avevo perso!

Ora provo

La pappa pronta è bella ma serve poco...più che altro mi trovo spaesato con i vari comandi del codice...a memora parallax è più semplice....

1 Like
#define LED 13        // LED collegato al pin digitale 13 
#define BOTTONE 7     // pin di input collegato al pulsante 
int val = 0;        // val conserva lo stato attuale del pin di input (7)
int prec_val;         // Variabile per valutare lo stato del precedente Loop
bool accendi;       // Accendi = true  => devo accendere il LED
int conta=1;
 
void setup()
{ 
  pinMode(LED, OUTPUT);       // imposta il pin digitale (13) come output 
  pinMode(BOTTONE, INPUT);    // imposta il pin digitale (7) come input 
  digitalWrite(LED, LOW);     // spegne inizialmente il led
  accendi = false;
} 
 
void loop()
{ 
  
  val = digitalRead(BOTTONE);  // leggo il valore dell'input e lo conservo in val 
  if (val==prec_val) return;   // Se lo stato del bottone è invariato (esempio continuo a
                               // premere il pulsante) non faccio nulla ed esco dal loop
  prec_val=val;                // salvo lo stato come precedente per la prossima esecuzione di loop()
 
  // controllo se lo stato del pulsante sia diventato "premuto" (lo stato cambia anche quando
  // rilascio il bottone!)
  if (val == HIGH)      // se premuto ...
     accendi = !accendi; // cambio lo stato 
 
  if (accendi) 
  ripeti: 
  {
    conta++;
    digitalWrite(LED, HIGH);// accende il led 
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
  if (conta <5) { goto ripeti;  } 
    
    }
  else
    { 
     
     conta=1;
     
   
  }
    
}

ammetto di non aver provato il codice al #2

mi sembra ben fatto, ma non entro nel merito

invece per il codice di timestamp:
bravo, non è scritto male, c'è solo un uso di goto: che fa sempre inorridire i puristi

il vero problema è che è pensato in termini di delay e cicli bloccanti
serve di ragionare in termini di macchine a stati e azioni frequenti ma non bloccanti

se vuoi, potresti provare a fare un lampeggio incondizionato senza usare delay (esistono esempi)
e questo incomincia ad avviarti verso l'idea generale, poi bisogna aggiungere passo a passo tante altre cosette

comunque il punto di arrivo è come ha indicato J-M-L

o meglio, UN punto di arrivo è quello
ci sono tante maniere per risolvere lo stesso problema, una per ogni programmatore grosso modo

La macchina a stati sembra così

La funzione 'lampeggia' incorpora la sua gestione del timing che assomiglia al codice dell'esempio 'blink without delay'

1 Like

Stato 0. Se premi il pulsante: stato 1.
Se stato 1: 5 lampi -> stato 2.
Se stato 2: se il pulsante è ancora premuto, il LED ancora lampeggia; altrimenti -> stato 0.

1 Like

Grazie ma non è farina del mio sacco, purtroppo! io ho solo sistemato 2 cosette, ma nulla di che.

Confesso che mi aspettavo un linguaggio più semplice....alla fine ci sono 1000 modi per fare la stessa cosa....quale sarà quello più efficiente???

Praticamente funziona come serve a me....l'unica cosa è che si attiva con GND.
Non ho capito se c'è un motivo per il quale usi un pin analogico invece che digitale...ma sicuramente è fondamentale per il funzionamento!

Quale è la parte nella quale misuri il tempo di pressione del pulsante, per decidere se eseguire la routine oppure continuare a lampeggiare?

Sembra semplice...ma sinceramente fatico a comprendere come funziona

Il flusso è cosi, ma il programma scritto è complicato per me...c'è molto da studiare

@timestamp: allora, al punto 16.1 del REGOLAMENTO trovi il link a vari pdf ed ad un ottimo libro ... considera che senza studiare, solo con i copia/incolla ... più che far lampeggiare un LED, o poco più, non si arriva a fare ... quindi ... vedi un po' tu ... :roll_eyes:

Guglielmo

Ciao Guglielmo, grazie per il messaggio! Si ovviamente come per tutte le cose, il copia-incolla non insegna niente...anzi.
Grazie per il link, vediamo se riesco a capirci qualcosa!

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