Go Down

Topic: Pulsante premuto tot tempo? (Read 2370 times) previous topic - next topic

Gustav_Ygman

Ciao a tutti!
per il mio progetto del telecomando cercavo di fare in modo che se tengo premuto un pulsante per 2 o 3 secondi, si generi un interrupt, il problema è che non so come fare per controllare se il pulsante viene premuto il tempo giusto?
Ho provato con la funzione millis:

Code: [Select]

pressTime = millis();
if ((millis() - pressTime) > delayPress)


ma non mi convince perchè da quello che ho capito, io premo il pulsante, e dopo che è passato un tot di tempo avviene quello che c'è tra le graffe dell'if, ma non è quello che devo fare.

Qual'è il miglior modo per fare quello che mi interessa?

Grazie a tutti!

leo72

Puoi fare così. Metti un contatore ed una variabile tampone, entrambe unsigned long.
Alla variabile tampone assegni millis(). Ad ogni loop controlli se il pulsantino è premuto. Se è premuto e se la variabile tampone è diversa da millis() vuol dire che è passato 1 ms con il pulsante premuto. Aggiorni quindi il contatore. Se invece il pulsantino non è premuto, azzeri il contatore (il conteggio viene interrotto). Se raggiungi la soglia da te impostata di millisecondi col pulsante premuto, fai partire la routine desiderata.

Code: [Select]
unsigned long contatore;
unsigned long contaimpulsi;
void setup() {
  contatore=millis();
  contaimpulsi=0;
}

void loop() {
  if (contatore!=millis()) { //è tempo di un controllo
    contatore=millis();
    if (digitalRead(PULSANTE)) {
      contaimpulsi++;
    } else {
    contaimpulsi=0;
  }
  if (contaimpulsi>SOGLIA) {
    .....CI SIAMO...
    contaimpulsi=0;
  }
}       


Prova, non so se funziona.

Gustav_Ygman

Grazie per il suggerimento :)
ma non è ancora focalizzato sul tempo :) sto provando a concepire qualcosa...per te funzionerebbe questo?

Code: [Select]

pressTime = millis();
volatile int flag = LOW;


while ((millis() - pressTime) < deelayTime)
{
   if (digitalRead(PULSANTE) != HIGH)
   {
      flag = LOW;
      break;
   }
   else
   {
      flag = HIGH;
   } 
}

if (flag == HIGH)
{
   eseguo questo blocco solo se il pulsante e' sempre
   rimasto premuto
}

leo72

La tua soluzione entra in un ciclo e controlla se il pulsante è premuto: esce solo se lo stacchi. Con il mio codice non fermi l'esecuzione dello sketch.
Cioè, controlla per il tempo che vuoi dal momento in cui preme il pulsante ma nel contempo (scusa il gioco di parole) continua ad eseguire il resto dello sketch nel caso ti serva l'esecuzione di qualcosa.

Un'alternativa è mettere un interrupt sul pin collegato al pulsante e contare ogni volta quanti millisecondi vede il pulsante premuto.

Gustav_Ygman

il pin a cui è collegato il pulsante deve generare un interrupt :D per quello mi va bene che entri nel ciclo e aspetti, quando è stato premuto per 3 secondi allora accende un led, legge il tasto su cui va memorizzato il codice accende un led, memorizza il codice, fa lampeggiare il led :) poi riprende dal cercare il prossimo tasto da memorizzare. Se viene ripremuto il tasto memorizza, allora esce dalla funzione :)

Credo di essermi confuso tra questo topic e quello del telecomando  :smiley-mr-green:

leo72

Io per "interrupt" intendo un interrupt hardware, non una soluzione come quella proposta da me o da te.

Gustav_Ygman

cioè un pulsante che viene premuto, blocca l'esecuzione di uno sketch e salta ad un certo punto giusto?

Quando nel telecomando si preme il tasto mem per tre secondi allora si blocca il programma base del telecomando e si passa alla modalità di memorizzazione :)

veseo

Ciao,

io uso una funzione strutturata in questo modo, è applicata ad una libreria, ma dovrebbe essere semplice adattarla alle proprie esigenze:

Code: [Select]
U8 Souliss_DigIn2State(U8 pin, U8 value_state1, U8 value_state2, U8 *memory_map, U8 slot)
{
// If pin is on, set the "value"
if(digitalRead(pin) && !InPin[pin])
{
// Write input value in memory map
memory_map[MaCaco_IN_s + slot] = value_state1;
time = millis(); // Record time

InPin[pin] = true;
return MaCaco_DATACHANGED;
}
else if(digitalRead(pin) && abs(millis()-time) > 1500)
{
time = millis(); // Record time

// Write timer value in memory map
memory_map[MaCaco_IN_s + slot] = value_state2;
}
else if(!digitalRead(pin))
{
InPin[pin] = false;
return MaCaco_NODATACHANGED;
}
}


Le azioni sono quelle dove trovi il codice memory_map[] = ..., distingue il caso in cui il tasto è premuto ma non mantenuto e quello in cui è premuto e mantenuto allo stesso tempo.
Il vettore InPin[] è utilizzato per matenere lo stato del pin, viene usato come flag per "ricordare" nei cicli successivi se il pulsante era stato premuto o meno. In questo modo il codice non è bloccante.

Saluti,
Dario.

Souliss - Open-source Distributed Home Automation with Arduino and Android

http://www.souliss.net
Follow at @soulissteam

@veseotech

Gustav_Ygman

credo di non aver capito come funziona il tuo codice :D

veseo

Nel primo IF verifica se il pulsante associato al pin è premuto, se si: esegue un'azione, fa partire il timer, setta un flag.
A questo punto, anche se il pulsante continua ad essere premuto non entrerà più nel primo IF, ma solo nell'ELSEIF se il pulsante è ancora premuto ed il timer ha superato valore 1500 millisecondi. Se entra nell'ELSEIF: esegue un'azione, resetta il timer.

Quando il pulsante è rilasciato, resetta il flag InPin[].

Saluti,
Dario.

Souliss - Open-source Distributed Home Automation with Arduino and Android

http://www.souliss.net
Follow at @soulissteam

@veseotech

Gustav_Ygman

Tutto chiaro a questo punto :) Grazie!

Go Up