Timer Arduino one. Millis o MsTimer?

Ciao a tutti.
sono nuovo in questo forum ed anche nella programmazione.
Mi dispiace disturbarvi, spulciando nel forum ho visto che avete questioni ben più interessanti ed anche problemi ben più complicati da risolvere.
Ho già presentato questo problema nel forum inglese di Arduino (http://forum.arduino.cc/index.php?topic=262925.0), ma io ho la testa dura e non sono un buon programmatore.
Sintetizzo qui il problema:

su un Arduino One devo eseguire le seguenti operazioni:
verificare se su un certo pin il valore cambia da basso ad alto (normalmente è basso).
Se questo succede far partire un timer di 5 secondi.
Se durante questi 5 secondi il valore cambia ancora da basso ad alto, allora portare una certa uscita a valore alto per 15 secondi, altrimenti non fare niente.
In input c’è un pulsante ed in uscita un piccolo motore.
Questo è tutto.

Se macinate un po’ di inglese c’è il link che ho postato prima, altrimenti non esitate a farmi qualche domanda.
Posto qui il codice che ovviamente non funziona.

#define FIRST 13                // pin di input collegato al segnale  
#define EXIT 7              // pin di output dove è collegata l'uscita
int  val = 0;                 // si userà val per conservare lo stato del pin di input  
long int time1=0;
long int time2=0;
 
void setup() {  
  pinMode(FIRST,INPUT);       // imposta il pin 13 come input  
  pinMode(EXIT, OUTPUT);     // imposta il pin 7 come output  
}  
  
void loop() {  
  val = digitalRead(FIRST);
  
  if (val == HIGH){
  time1 = millis();
  delay(30);
	}
	
	if (time1<5000 && val==(HIGH)){
	time2 = millis();
		if (time2<=15000){
		digitalWrite(EXIT,HIGH);
		} else {
		digitalWrite(EXIT,LOW);
		time1= 0;
		time2= 0;
		}
	}
}

Aspetto speranzoso.

A parte che potremmo definire questo nuovo thread come cross-posting perché c'è già di là una discussione aperta, con anche alcune risposte... ma vabbè...

Devi intanto rivedere il programma perché così non va bene. Non puoi confrontare time1 con 5000 dato che millis si incrementa sempre e quindi time1 sarà inferiore a 5000 solo per i primi 5 secondi di funzionamento del programma. Azzerare time1 non ti fa poi azzerare millis. I confronti si fanno per differenza fra un valore precedentemente memorizzato di millis e quello attuale.

Ti do un link da leggere: http://www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/

For a better timer see this page http://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html uses elapsedMillis

None needs to manage the overflow of millis in such manner. Just make a proper subtraction and the problem is bypassed

TheMerovingian: Ciao a tutti. sono nuovo in questo forum ...

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni e a leggere il regolamento: Regolamento - qui una serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections - qui le pinout delle varie schede by xxxPighi: Pinout - qui una serie di link [u]generali[/u] utili: Link Utili

Ho letto il link che mi hai postato un paio di volte. Ho capito che può essere utile per il mio programma ma francamente sono in alto mare con l'effettivo utilizzo. Mi pare che il piccolo programma che devo realizzare sia molto semplice, una pagina di codice al massimo... Non è che qualcuno mi può fare una bozza?

Eppure a me pare chiaro quel che dice @Leo.
Questo non può funzionare:

if(time1<5000 ...

devi fare una differenza:

if( millis()-time1<5000 ...

Vediti la differenza tra il semplicissimo sketch Blink con il BlinkWithoutDelay (forniti con IDE Arduino).
Il pin da controllare sarebbe il pulsante (usa un altro pin, proprio il 13 cha il led collegato!!!) ?
Perchè non fare le cose un passo alla volta ?
Prima di tutto uno sketch che solo verifica e ti avvisa via Serial.println() che il tasto è premuto. Tenendo conto dei falsi contatti (vedi debounce software di un pulsante)
Poi se viene premuto, attivi una variabile booleana che esegue il codice del ciclo di 5 secondi, e in questo ciclo per ora non fai nulla. Poi si prosegue con il resto. Un passo alla volta.

Poi time1 e time2 le hai dichiarate come long int, per lavorare con i millis devono essere delle unsigned long.

http://arduino.cc/en/Reference/Millis

TheMerovingian: su un Arduino One devo eseguire le seguenti operazioni: verificare se su un certo pin il valore cambia da basso ad alto (normalmente è basso). Se questo succede far partire un timer di 5 secondi. Se durante questi 5 secondi il valore cambia ancora da basso ad alto, allora portare una certa uscita a valore alto per 15 secondi, altrimenti non fare niente. In input c'è un pulsante ed in uscita un piccolo motore.

E durante i 15 secondi il pulsante deve essere controllato ?

E durante i 15 secondi il pulsante deve essere controllato ?

No, durante i 15 secondi il pulsante deve essere ignorato.

Ok intanto ho modificato il codice con i suggerimenti dati… Che devo modificare ancora?

#define INGRESSO 10                // pin di input collegato al segnale  
#define USCITA 7              // pin di output dove è collegata l'uscita
int  val = 0;                 // si userà val per conservare lo stato del pin di input  
unsigned long time1=0;
unsigned long time2=0;
 
void setup() {  
  pinMode(INGRESSO,INPUT);       // imposta il pin 13 come input  
  pinMode(USCITA, OUTPUT);     // imposta il pin 7 come output  
}  
  
void loop() {  
  val = digitalRead(INGRESSO);
  
  if (val == HIGH){
  time1 = millis();
  delay(30);
	}
	
	if (millis()-time1<5000){
	time2 = millis();
		if (millis()-time2<=15000){
		digitalWrite(EXIT,HIGH);
		} else {
		digitalWrite(EXIT,LOW);
		}
	}
}

Non mi pare hai seguito quello che suggerivo... Mi pare in presentazione scrivi che non sei un bravo programmatore. Ti interessa imparare o vuoi che qualcuno te lo scriva ?

Stavolta ho modificato il codice in modo che scriva nel serial monitor ciò che accade… Però non mi fa vedere nulla.

#define INGRESSO 10                // pin di input collegato al segnale  
#define USCITA 7              // pin di output dove è collegata l'uscita
int  val = 0;                 // si userà val per conservare lo stato del pin di input  
unsigned long time1=0;
unsigned long time2=0;

void setup() {  
  Serial.begin(9600);
  pinMode(INGRESSO,INPUT);       // imposta il pin 13 come input  
  pinMode(USCITA, OUTPUT);     // imposta il pin 7 come output  
}  

void loop() {  
  val = digitalRead(INGRESSO);
  Serial.print("val = ");
  Serial.println(val);

  if (val == HIGH){
    time1 = millis();
    delay(30);
    Serial.print("time1 è uguale a ");
    Serial.println(time1);
  }

  if (millis()-time1<5000){
    time2 = millis();
    if (millis()-time2<=15000){
      digitalWrite(USCITA,HIGH);
      Serial.print("time2 è uguale a:");
      Serial.println(time2);
    } 
    else {
      digitalWrite(USCITA,LOW);
    }
  }
}

Prova una cosa come questa, non ho tenuto conto però dei possibili falsi contatti del pulsante. Non l'ho provato. Mi sarebbe piaciuto fartici arrivare passo dopo passo ma vedo che insisti a voler fare tutto il programma in un colpo solo, mettendo insieme molti piccoli problemi di logica.

const byte PIN_INGRESSO = 7;  // pin di input collegato al segnale  
const byte PIN_USCITA = 13;     // pin di output dove è collegata l'uscita messo su 13 per avere il led come output
const long INTERVALLO1=5000L;
const long INTERVALLO2=15000L;
byte stato = 0;                // si userà val per conservare lo stato del pin di input  
unsigned long myTime=0;

void setup() 
{  
  delay(1000);
  Serial.begin(9600);
  Serial.println("avvio");
  pinMode(PIN_INGRESSO,INPUT);       // imposta il pin 13 come input  
  pinMode(PIN_USCITA, OUTPUT);     // imposta il pin 7 come output  
}  

void loop() {  
  switch(stato)
  {
    case 0: // attende pressione pulsante
      if(digitalRead(PIN_INGRESSO)==HIGH) 
      { stato=1;
        myTime=millis();
        Serial.println("entra in stato 1");
        delay(100);
      }
      break;
    case 1: // attende 5 secondi oppure ripressione pulsante
      if(digitalRead(PIN_INGRESSO)==HIGH) 
      { stato=0;
        Serial.println("ritorna in stato 0");
        delay(100);
      }
      else
      { if( millis()-myTime > INTERVALLO1 ) 
        { stato=2;
          myTime=millis();
          digitalWrite(PIN_USCITA,HIGH);
          Serial.println("entra in stato 2");
        }
      }
      break;
    case 2: // attende 15 secondi
      if( millis()-myTime > INTERVALLO2 ) 
      { stato=0;
        digitalWrite(PIN_USCITA,LOW);
        Serial.println("ritorna in stato 0");
      }
      break;
   }  
}

Grazie davvero. Non pensavo che il programma finale fosse così complesso e vedo che ero parecchio distante dall'ottenere il risultato sperato. Per fare una cosa del genere mi ci sarebbe voluto molto tempo... O forse il tempo non c'entra. Fra poco lo provo e ti so dire.

TheMerovingian: Grazie davvero. Non pensavo che il programma finale fosse così complesso e vedo che ero parecchio distante dall'ottenere il risultato sperato. Per fare una cosa del genere mi ci sarebbe voluto molto tempo... O forse il tempo non c'entra. Fra poco lo provo e ti so dire.

Non è tanto il tempo ma bisognava arrivarci piano piano, affrontando una parte della tua analisi alla volta. Qui due link dove si parla di variabile di stato (quella che io posto da 0->1->2 e poi di nuovo a 0 ) : www.lucadentella.it/2013/04/30/macchina-a-stati-finiti-e-arduino/ www.gammon.com.au/forum/?id=11425

Grazie per i link. Purtroppo però il programma non funziona. L'output rimane sempre basso a dispetto di ciò che gli arriva al pin in input.

Imparare comporta fatica, molto più semplice un CTRL+C e CTRL+V

TheMerovingian: Grazie per i link. Purtroppo però il programma non funziona. L'output rimane sempre basso a dispetto di ciò che gli arriva al pin in input.

Rivedi il codice di prima, forse avevo invertito i pin ingresso/uscita. Ho provato e a me funziona, solo che il debounce del pulsante da molti problemi: http://arduinotutorial.altervista.org/debounce/

Inoltre sei sicuro di aver collegato bene il pulsante (con resistenza di pulldown) ? http://pighixxx.com/PNG/121.png http://arduinotutorial.altervista.org/resistenza-di-pull-updown/

Ad occhio sono da invertire gli if del case 1 ...