Problema pulseIn

Vorrei accendere il led dopo che il pulsante viene premuto per 5 secondi se non premo il pulsante o lo premo per un tempo inferiore ai 5 secondi il led non si deve accendere.
Questo programma mi serve per eseguire un programma più complesso che sarebbe l' apertura e la chiusura di un finestrino di una macchima. Il programma dovrebbe aprire o chiudere tutto il finestrino se tengo premuto per meno di un secondo il pulsante di apertura o chiusura. Se invece tengo premuto il pulsante di apertura e chiusura il finestrino si apre o si chiude fino a quando lo volglio io.

Questo il programma ma non funziona. :sweat_smile:

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;
unsigned long durataimpulso;
unsigned long tempopressionepulsante = 5000;

void setup ()
{
  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);
   pinMode (Utilizzatorepin, OUTPUT);
}  

void loop ()
{
   Statopulsante = digitalRead (Pulsantepin);
   Statoutilizzatore = digitalRead (Utilizzatorepin);
   durataimpulso = pulseIn (Pulsantepin, HIGH);

if (Statopulsante==HIGH)
{
if (durataimpulso>tempopressionepulsante)
{
  Statoutilizzatore=HIGH;
  digitalWrite (Utilizzatorepin, Statoutilizzatore);
}
}
else
{
Statoutilizzatore = LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);  
}
}

nella pressione di un tasto devi tenere presente che possono esserci dei rimbalzi all'inizio, io di solito quando devo leggere se un tasto è stato premuto leggo una volta e poi aspetto 20ms prima di rileggerlo un'altra volta, proprio per evitare di leggere dati "falsi"...
per quanto riguarda il tuo pulsante, come l'hai collegato? è un deviatore o un semplice pulsante a due contatti? hai due pulsanti per vedere quando andare su o giù?

comunque per tirare su un finestrino con un pulsante dedicato a tale funzione io farei così (poi c'è da aggiungere un altro pulsante per fare che il finestrino vada giù):

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

void setup ()
{
Serial.begin(9600);
pinMode (Pulsantepin, INPUT);
pinMode (Utilizzatorepin, OUTPUT);
}

void loop ()
{
if (digitalRead (Pulsantepin) == HIGH) //verifico se il pulsante è stato premuto
{
unsigned long inizioPressione=millis(); // salvo il valore di millis() nel momento iniziale
delay(20); //aspetto 20ms (puoi mettere anche di più se vuoi) per evitare il rimbalzo del tasto

while(digitalRead (Pulsantepin) == HIGH) //finchè il pulsante è premuto fai questo:
{
digitalWrite (Utilizzatorepin, HIGH);
}

if(millis()-inizioPressione<5000) //se il pulsante è stato premuto per meno di 5 secondi spegni
{
digitalWrite (Utilizzatorepin, LOW);
}
else // se no tienilo acceso
{
digitalWrite (Utilizzatorepin, LOW);
}
}
else
{
digitalWrite (Utilizzatorepin, LOW);
}
}

nel programma ho usato la funzione millis() (millis() - Arduino Reference) è molto utile e vedrai che ti servirà anche in futuro..
poi secondo me devi mettere un controllo di quando il finestrino è arrivato a fine corsa

Grazie per la risposta.
Si, i pulsanti sono due NO uno deve aprire e l' altro chiudere, i due pulsanti devono avere un interblocco in modo che il motorino non abbia due alimentazione contemporaneamente.
Provo il tuo programma, lo completo se ce la faccio e lo pubblico.

si ok ma i pulsanti hanno 2 o 3 contatti? se ne hanno 2 devi mettere una resistenza di pull-up o pull-down, oppure usare quelle interne nel micro..

Ho un pulsante a 4 piedini, ma dovrà andare con un normalissimo pulsante come quelli che hai in casa.
La resistenza l' ho già messa. Ma non conosco la differenza fra resistenza di pull-up e pull-down

Nicola88:
Ho un pulsante a 4 piedini, ma dovrà andare con un normalissimo pulsante come quelli che hai in casa.

quindi deduco che hai bisogno di mettere una resistenza di pull-up o pull-down per fare in modo che l'arduino non sia connesso al nulla, io ti consiglio di usare la resistenza di pull-up interna al microcontrollore

:astonished: Non ciò capito na mazza.
Ho appena iniziato e sono a zero sia di arduino che di elettronica.
Faccio l' elettricista.
Qualche buona guida per principiante mooolto principiante da scaricare? Magari Gratis?
Ho seguito uno schema per collegare il pulsante che ho trovato su internet e ho aggiunto una resistenza come era nel disegno. Posso non aggiungere quella resistenza? Arduino ha già una resistenza al suo interno che posso utilizzare al posto di quella esterna?
Se si come devo fare?

wikipedia è buona per avere un'idea di cosa stiamo parlando Resistenza pull-up - Wikipedia :wink:

Nicola88:
Ho seguito uno schema per collegare il pulsante che ho trovato su internet e ho aggiunto una resistenza come era nel disegno. Posso non aggiungere quella resistenza? Arduino ha già una resistenza al suo interno che posso utilizzare al posto di quella esterna?
Se si come devo fare?

si puoi fare almeno di collegare quella resitenza e puoi usare quelle interne all'arduino ti basta collegare il pulsante tra il pin e la massa e scrivere:
pinMode(Pulsantepin,INPUT_PULLUP);
questo abilita una resistenza di pull up da 20k, chiaramente questo comporta che quando il pulsante non è premuto hai 5V sul pin e quindi se fai il digitalRead trovi HIGH, mentre quando premi il pulsante hai 0V, ovvero LOW

Quindi il pulsante funziona al contrario e devo invertire nel programma gli HIGH e i LOW del pulsante giusto?
Quindi tu mi consigli l' utilizzo della resistenza interna di Arduino?

Nicola88:
Quindi il pulsante funziona al contrario e devo invertire nel programma gli HIGH e i LOW del pulsante giusto?
Quindi tu mi consigli l' utilizzo della resistenza interna di Arduino?

si, ma alla fine non cambia niente, solo una resistenza in meno, vedi te cosa preferisci

Meglio senza resistenza è più comodo da collegare soprattutto se ne hai diversi di pulsanti.
Notte e grazie.

Nicola88:
Meglio senza resistenza è più comodo da collegare soprattutto se ne hai diversi di pulsanti.

in genere ragiono anche io così :slight_smile:

Nicola88:
Notte e grazie.

di niente :wink:

Ho provato il programma che hai postato ma non funziona come vorrei. Provo a spiegarmi.
Io ho due pulsanti e due led.
Utilizzerò un pulsante per far salire il finestrino. (Led 1 simula salita motore)
Utilizzerò un pulsante per far scendere il finestrino. (Led 3 simula discesa motore)
Pensiamo ora solo al programma che fa salire il finestrino.
Fase 1 Il pulsante e il led sono rispettivamente non premuto e non acceso.
Fase 2 Premo il pulsante.
Fase 3 Se il pulsante è premuto per non più di mezzo secondo il finestrino si deve aprire tutto fino al finecorsa.
Fase 4 Se il pulsante è premuto per più di mezzo secondo il finestrino si deve aprire fino a quando non rilascio il pulsante.
Ho seguito il tuo consiglio di utilizzare milli () e ho scritto questo.

const int Pulsantepin1 = 2;
const int Pulsantepin2 = 3;
const int Utilizzatorepin1 = 4;
const int Utilizzatorepin2 = 5;
unsigned long previousMillis1 = 0; 
unsigned long debounge = 200; 
unsigned long previousMillis2 = 0; 
unsigned long pressionepulsante = 500;
unsigned long previousMillis3 = 0; 
unsigned long temporizzatore = 5000;


int Statopulsante1;
int Statopulsante2;
int Statoutilizzatore1;
int Statoutilizzatore2;


void setup ()
{
  Serial.begin(9600);
  pinMode (Pulsantepin1, INPUT);
  pinMode (Pulsantepin2, INPUT);
  pinMode (Utilizzatorepin1, OUTPUT);
  pinMode (Utilizzatorepin2, OUTPUT);
}  

void loop ()
{
  unsigned long currentMillis = millis ();
  Statopulsante1 = digitalRead (Pulsantepin1);
  Statopulsante2 = digitalRead (Pulsantepin2);
  Statoutilizzatore1 = digitalRead (Utilizzatorepin1);
  Statoutilizzatore2 = digitalRead (Utilizzatorepin2);
  if (Statopulsante1==HIGH)  
  {  
    if (currentMillis - previousMillis1 > debounge)
    {
      previousMillis1 = currentMillis; 
      Statoutilizzatore1 = HIGH;
      digitalWrite (Utilizzatorepin1, Statoutilizzatore1);
      if (currentMillis - previousMillis2 < pressionepulsante)
      { 
        previousMillis2 = currentMillis;
        if (currentMillis - previousMillis3 > temporizzatore)
        {  
          previousMillis3 = currentMillis;
          Statoutilizzatore1 = LOW;
          digitalWrite (Utilizzatorepin1, Statoutilizzatore1);      
        }  
      } 
    }  
  }
  else if (Statoutilizzatore1==HIGH)
  { 
    Statoutilizzatore1 = LOW;
    digitalWrite (Utilizzatorepin1, Statoutilizzatore1);
  } 
}

Il problema che se io tengo premuto il pulsante per meno di mezzo secondo il led dovrebbe stare acceso per 10 secondi e poi spegnersi. In realtà se io tengo premuto per meno di mezzo secondo il led si spegne subito.

non ho capito la storia del mezzo secondo, prima erano 5 secondi ed andava all'incontrario, no? cosa fa il programma che ti ho dato io? cosa non va bene in quel programma? (mi sono accorto che c'era un LOW al posto di un HIGH, facendo copia incolla mi era scappato.. nel codice sotto ho risolto)

passando al tuo codice si capisce poco e secondo me non hai capito bene come funziona millis(), salvando il valore restituito da millis() su una variabile salvi su quella variabile il numero di millisecondi che sono passati dall'accensione del microcontrollore.. quindi per verificare che siano passati, per esempio, 500ms devi salvarti il valore di millis() in una variabile che sarà il riferimento di partenza, e poi andare a verificare che millis() - riferimentoPartenza sia maggiore o uguale a 500ms... ok?

poi non capisco perchè salvi gli stati dei pin su delle variabili, così facendo rischi di andare a fare i conti con delle variabili "vecchie", prendi esempio da come ho fatto io nel mio codice di prima..

per fare quello che hai detto adesso io procederei col sistemare il codice di prima:

const int Pulsantepin1 = 2;
const int Pulsantepin2 = 3;
const int Utilizzatorepin1 = 4;
const int Utilizzatorepin2 = 5;

void setup ()
{
Serial.begin(9600);
pinMode (Pulsantepin1, INPUT);
pinMode (Pulsantepin2, INPUT);
pinMode (Utilizzatorepin1, OUTPUT);
pinMode (Utilizzatorepin2, OUTPUT);
}

void loop ()
{
if (digitalRead (Pulsantepin1) == HIGH) //verifico se il pulsante è stato premuto
{
unsigned long inizioPressione=millis(); // salvo il valore di millis() nel momento iniziale
delay(20); //aspetto 20ms (puoi mettere anche di più se vuoi) per evitare il rimbalzo del tasto

while(digitalRead (Pulsantepin1) == HIGH) //finchè il pulsante è premuto fai questo:
{
digitalWrite (Utilizzatorepin1, HIGH); //metto a livello alto Utilizzatorepin1
}

if(millis()-inizioPressione>=500) //se il pulsante è stato premuto per più di 500ms spegni
{
digitalWrite (Utilizzatorepin1, LOW);
}
else // se no tienilo acceso
{
digitalWrite (Utilizzatorepin1, HIGH);
}
}
}

State incasinando il problema.
Per vedere se un pulsante è premuto per un certo lasso di tempo basta usare una variabile di stato e millis, il tutto dentro ad un while.
Alla prima pressione, memorizzate millis, date False alla variabile ed entrate in un while da cui uscite se: viene rilasciato il pulsante (in questo caso mettete a True la variabile prima di uscire), siete andati in timeout (ossia avete atteso per il tempo desiderato). Sotto al while basta controllare se la variabile di stato è a True, se ciò è vero vuol dire che siete usciti dal while per timeout quindi il pulsante è stato premuto per il tempo richiesto. Se è False vuol dire che l'utente l'ha rilasciato prima del tempo. Ed agire di conseguenza.

unsigned long tempMillis;
boolean over;

if (pulsantePremuto) { //qui mettete il digitalRead che vi piace
    tempMillis = millis();
    over = false;
    //si esce da questo ciclo nel momento in cui l'utente rilascia il pulsante
    //oppure se si è raggiunto il tempo massimo di pressione
    while (pulsantePremuto) {
        if (millis() - tempMillis > 500) { //0,5 sec di attesa massima
            over = true;
            break;
        }
    }
    //adesso controlliamo se l'utente ha premuto il pulsante per il tempo prestabilito
    if (over) { //sì, 
        ....
    } else { //no
        ....
    }
}