Inizio loop con ingresso sensore o pulsante

Ciao a tutti:
Come da oggetto dovrei far iniziare in un ciclo chiuso, un X numero di volte, avviato da un ingresso attivato da pulsante o sensore o relè.

Mi serve per misurare il tempo che c’è tra un impulso e l’altro.

Praticamente una volta che entra un segnale su un ingresso, nel mio caso il pin 2, deve iniziare un’altro loop per X volte e conteggiati i loop fino al ciclo sucessivo dove verrà azzerato il conteggio dei loop e il conteggio inizierà di nuovo.

Devo tener presente anche che ci dovrà essere la condizione di “antirimbalzo”, praticamente non ci dovranno essere interferenze di falso contatto che mi disturbino il conteggio. Il tutto senza utilizzare la funzione delay perchè alla fine dello sketch mi serve proprio che non ci siano istruzioni di ritardo perchè mi servirà fare un cronometro.

Magari fare “l’autoritenuta” software per molti sarà uno scherzo ma in questo caso non sono riuscito a ottenerla senza usare l’istruzione delay.

Ho provato conle funzioni “if”, “while” e anche “for” che sarebbe la più adatta ma senza sucesso. non riesco a capire dove sto sbagliando.

Sicuramente sono due righe di schetch, ma oggi proprio non ci arrivo.

Saluti,

Gustavo

Gustavo74: Ho provato conle funzioni "if", "while" e anche "for" che sarebbe la più adatta ma senza sucesso. non riesco a capire dove sto sbagliando.

Pubblica il codice che stai usando.

Ciao Leo company:
Intanto grazie della tempestiva risposta.
Proprio adesso ho trovato l’errore, alla fine era una stupidata, dovevo iniziare un loop d’istruzione “for”(conteggio) internamente al paragrafo di un istruzione “if”.

Allego il codice, ho usato dei delay per i lampeggi dei led ma solo per verificare sulla bread board il funzionamento. poi lo sketch definitivo non avrà alcun delay

per quel che riguarda l’antirimbalzo credo che venga anullato dal ciclo “for” perchè che ci sia o meno il pulsante premuto o rimbalzante non mi influisce sul conteggio in corso.

Dimmi se è possibile con qualche istruzione diversa fare lo sketch più corto e semplice!!! :

// dai un nome agli ingressi e definisci il tipo di variabile
int ledrosso = 9;//variabili intere
int ledverde = 10;
int pulsante ;
int conteggio;

// the setup
void setup()
 {  
  pinMode(ledrosso, OUTPUT); // initialize the digital pin as an output.
  pinMode(ledverde, OUTPUT);  
  pinMode(pulsante, INPUT);
  Serial.begin(9600); //faciamo anche il monitoraggio.
}

// inizio loop infinito
void loop() 

{

  pulsante = digitalRead(2); //definizione ingresso digitale al pin 2
  
  if (pulsante == LOW)//se il pulsante va a massa segui le operazioni sotto
                      //altrimenti saltale fino alla prima parentesi graffa sucessiva
{
  for (int conteggio=0; conteggio<=100; conteggio++)//conteggio
  {
  digitalWrite(ledrosso, HIGH);   // lampeggi dei due led velocemente  con autoritenuta perchè funziona anche se il
  delay(20);                                        // pulsante viene rilasciato
  digitalWrite(ledrosso, LOW);
  delay(20);               // wait 20mS
  digitalWrite(ledverde, HIGH);  
  delay(20);               // wait 20mS
  digitalWrite(ledverde, LOW); 
  delay(20);               // wait 20mS

Serial.println(conteggio); //visualizza in monitor il conteggio dei loop dell'istruzione for

}
}
   if (pulsante == HIGH)// se il pulsante è rilasciato
  {
 digitalWrite(ledrosso, HIGH);   //Lampeggio del solo led rosso in attesa di premuta del pulsante
  delay(200);
  digitalWrite(ledrosso, LOW);   
  delay(200);  
  }
   
}

Con i delay il codice si blocca finché non è passato l’intervallo preimpostato e non puoi fare altro nel frattempo.
L’alternativa è usare millis(), una funzione che restituisce il numero di millisecondi dall’avvio del chip, e programmare i compiti in base al tempo trascorso.

Ho scritto un articolo sulla gestione dei compiti con millis: nell’esempio allegato faccio compiere 2 azioni diverse ma il concetto lo puoi estendere a quanti compiti vuoi. Usalo come base per riorganizzare il tuo codice, semplificandolo ed usando il metodo descritto, che non ti blocca nulla.

Ciao Leo: Quel utilizzo dei milis che citi nel tuo sito credo che sia proprio quello che sto cercando, in questo modo posso utilizzare i delay per semplificare le operazioni di temporizzazione e non disturbare le altre operazioni.

Non avevo ancora usato queste "unsigned long":

unsigned long previousMillis = 0; //will store last time LED was updated. unsigned long interval = 1000; //interval at which to blink (milliseconds)

Non capisco la loro funzione, l'ho gia visto in altri sketch, cercherò in rete intanto.............

Grazie

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

E' un tipo di dati, come l'int, il char, il byte ecc.. Contiene un intero senza segno a 32 bit.

Con l'applicazione dei "millis" sicuramente riesco a oviare i ritardi fatti dai "delay" ma non riesco a capire come funzionano o vengano utilizzate queste variabili:

previusMillis

currentMillis

Il millis so che conteggia i milisecondi dall'inizio dello sketch.

A me servirebbe sapere i milisecondi tra un impulso e l'altro che mi arriva da ingresso digitale ma non riesco ad applicare queste funzioni. Per esempio, ho trovato questo sketch in rete che mi accende un led alla prima pressione di pulsante e me lo accende alla seconda pressione del pulsante ma. In questo sketch vorrei misurare i millisecondi tra una pressione e l'altra:

int switchPin = 2;
int ledPin = 9;
boolean lastButton = LOW;
boolean ledOn = false;

void setup()
{
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  if (digitalRead(switchPin) == HIGH  && lastButton == LOW)
{
  ledOn = !ledOn;
  lastButton = HIGH;
}
else
{
 lastButton = digitalRead(switchPin);
}
digitalWrite(ledPin, ledOn);
}

Non è difficile. All'accensione, salvi il tempo in una variabile. Quando spengi i LED, la differenza fra il valore corrente di millis e quello precedentemente salvato ti da il tempo intercorso fra i 2 eventi.

Dal link postato precedentemente da Leo72, trovi questo sketch:

const int ledPin =  13; // the number of the LED pin
int ledState = 0; // ledState used to set the LED
unsigned long previousMillis = 0; //will store last time LED was updated
unsigned long interval = 1000; //interval at which to blink (milliseconds)
void setup() {
  pinMode(ledPin, OUTPUT); //set the digital pin as output:
}

void loop() {
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis; //save the last time you blinked the LED
    //if the LED is off turn it on and vice-versa:
    ledState ^= 1;
    digitalWrite(ledPin, ledState);
  }
}

Inizia ad adattare questo codice al tuo, dove fai lampeggiare il solo LED rosso quando pulsante è alto.

ottimo, vedrò di inserire l'ingresso del pulsante allo sketch in questione.

A presto vi farò sapere.

Di questo sketch capisco bene la sostituzione dei delay con il conteggio dei millis ma non riesco a capire le funzioni di currentMillis e previousMillis. Più che altro non capisco come e quando queste variabili acquisiscono e variano i loro valori. Ho cercato in rete anche le definizioni di queste funzioni, previousMillis e currentMillis ma ho trovato altro che sketch già compilati enza spiegazioni.

Brado: Dal link postato precedentemente da Leo72, trovi questo sketch:

const int ledPin =  13; // the number of the LED pin
int ledState = 0; // ledState used to set the LED
unsigned long previousMillis = 0; //will store last time LED was updated
unsigned long interval = 1000; //interval at which to blink (milliseconds)
void setup() {
  pinMode(ledPin, OUTPUT); //set the digital pin as output:
}

void loop() {   unsigned long currentMillis = millis();   if(currentMillis - previousMillis > interval) {     previousMillis = currentMillis; //save the last time you blinked the LED     //if the LED is off turn it on and vice-versa:     ledState ^= 1;     digitalWrite(ledPin, ledState);   } }




Inizia ad adattare questo codice al tuo, dove fai lampeggiare il solo LED rosso quando pulsante è alto.

currentMillis e previousMillis non sono funzioni ma variabili. Come tali, ad esse è assegnato il valore di millis() in determinati istanti dell’esecuzione del codice.

Nello specifico, currentMillis, contiene il valore di millis() al momento dell’esecuzione del blocco di codice che fa il controllo sul trascorrere del tempo. previousMillis contiene invece il precedente istante in cui è stata eseguita l’operazione. All’avvio del programma, ovviamente previousMillis non conterrebbe nulla perché l’operazione non è mai stata eseguita per cui gli assegno “d’ufficio” il valore di millis rilevato all’avvio dello sketch stesso: l’assegnazione è fatta dentro a setup, così che sia eseguita solo una volta. Poi, nel loop, ogni volta che la differenza fra il valore corrente di millis (currentMillis) e l’istante a cui si è eseguita precedentemente l’operazione (previousMillis) è superiore all’intervallo prefissato, si esegue il codice del blocco e poi si riassegna a previousMillis il valore corrente di millis(), per registrare il momento di quando è stato eseguito il compito.

leo72: currentMillis e previousMillis non sono funzioni ma variabili. Come tali, ad esse è assegnato il valore di millis() in determinati istanti dell'esecuzione del codice.

Nello specifico, currentMillis, contiene il valore di millis() al momento dell'esecuzione del blocco di codice che fa il controllo sul trascorrere del tempo. previousMillis contiene invece il precedente istante in cui è stata eseguita l'operazione. All'avvio del programma, ovviamente previousMillis non conterrebbe nulla perché l'operazione non è mai stata eseguita per cui gli assegno "d'ufficio" il valore di millis rilevato all'avvio dello sketch stesso: l'assegnazione è fatta dentro a setup, così che sia eseguita solo una volta. Poi, nel loop, ogni volta che la differenza fra il valore corrente di millis (currentMillis) e l'istante a cui si è eseguita precedentemente l'operazione (previousMillis) è superiore all'intervallo prefissato, si esegue il codice del blocco e poi si riassegna a previousMillis il valore corrente di millis(), per registrare il momento di quando è stato eseguito il compito.

Ho capito.....spero. currentM e previousM non sono altro che variabili con valori assegnati a seconda di dove sono state richiamate nello sketch. Ma quando si ha a che fare con queste variabili di tempo c'è l'obbligo di chiamarle sempre con "Millis" internamente alla parola o gli si può dare qualsiasi nome? Adesso ci riprovo a rifare lo sketch....... A presto

Le chiami come ti pare. Visto però che in C/C++ non c'è il limite di 2 caratteri che c'era nei vecchi BASIC Microsoft anni '80 per il nome delle variabili ;) è più d'aiuto dare alle stesse nomi significativi che aiutino a capire cosa contengono.

Esempio, potevi chiamarle anche pippo, mario e beppe, ma sicuramente vedere scritto if (pippo - beppe > mario) non ti aiuta a comprendere il programma ;) ;)

Chiarissimo, grazie! Quel che non riesco adesso è riuscire a misurare il tempo tra una pressione del pulsante e la pressione sucessiva. Ci provo ancora e casomai inserisco lo sketch se non ne vengo fuori.

Ce l’ho fatta. sono riuscito a utilizzare i millis come mi avete detto. La misurazione avviene dopo dalla seconda pressione come avevo previsto.
Ho fatto un ciclo for per annullare l’eventuale rimbalzo del pulsante causato da falsocontatto creato da un ciclo for da 50 cicli, l’unica pecca è che non posso misurare tempi più corti ma ci lavorerò.

Ho inserito due led spia, uno rosso per la situazione di standby e uno verde per l’impulso.

Se riuscite a trovare delle migliorie o semplificazioni vi ringrazierò senz’altro.

Intanto vi ringrazio tutti per avermi indicato la strada giusta!

Poi dovrei ricavarne la frequenza al minuto e inviare tutto ad un display di qualche tipo, vi farò vedere i risultati senz’altro.

A risentirci!

Ecco lo sketch:

//Contacolpi con sistema di antirimbalzo del pulsante o del contatto di misura


// dai un nome agli ingressi e definisci il tipo di variabile
int ledrosso = 9;//variabili intere
int ledverde = 10;
int pulsante ;
int conteggio;//conteggio cicli per antirimbalzo
unsigned long cc;//conteggio cicli attivi per temporizzazione
unsigned long f;//frequenza
unsigned long t;//timer dei milisecondi
unsigned long previousMillis = 0;

// setta uscite e ingressi
void setup()
{               
  pinMode(ledrosso, OUTPUT);  
  pinMode(ledverde, OUTPUT);  
  pinMode(pulsante, INPUT);
  Serial.begin(9600); //setta il monitor seriale
}

// inizio del loop
void loop() 

{

  pulsante = digitalRead(2); //definizione ingresso digitale al pin()
  
  if (pulsante == HIGH)//se il pulsante viene premuto segui le operazioni sotto
                      //altrimenti saltale fino alla prima parentesi graffa
{ 
  digitalWrite(ledrosso, LOW);    // spegni il led rosso
  for (int conteggio=0; conteggio<=50; conteggio++)//conteggio di 50 cicli per creare l'antiriblalzo del pulsante
  {
  digitalWrite(ledverde, HIGH);  // accendi il led verde
Serial.println(t); //visualizza il tempo tra una pressione e l'altra
}
unsigned long currentMillis = millis();
 t = currentMillis - previousMillis;
     previousMillis = currentMillis; 

 digitalWrite(ledverde, LOW);
}
   if (pulsante == LOW)//se il pulsante è rilasciato
  {
 digitalWrite(ledrosso, HIGH);   // accendi il led rosso, situazione di standby
}
}

Bene. son contento che tu abbia risolto. La prox volta, però, ricordati di inserire il codice fra gli appositi code.

leo72: ................però, ricordati di inserire il codice fra gli appositi code.

Dici che il codice venga in quella finestra come nel messaggio? C'è qualche comando speciale da inserire nel messaggio? Una volta l'ho fatto ma con i messaggi di errore.

Nel regolamento c'è scritto come fare. Devi usare il pulsantino "#" sopra agli smilies, dove pubblichi i post. NON usare la funzione di esportazione del codice dal menu dell'IDE di Arduino ma fai un copia e incolla: quella funzione non va bene e crea solo un testo colorato che si può solo quotare (pulsante con icona a forma di fumetto)

Adesso mi si è presentato un’altro problema.

Ho fatto iu calcolo della frequenza al minuto e poi ho visualizzato il risultato su un display nokia ma… volevo anche avere i decimali e allora ho impostato la variabile del risultato della frequenza come “float” al inizio del codice. Si visualizzano le cifre dopo la virgola ma i decimali sono sempre a zero cosa che credo che sia impossibile che dia sempre numeri interi dal calcolo della frequenza. Vi allego il codice, non so dove avrò sbagliato…

Vediamo se va l’inserimento del codice intanto.

//Contacolpi con sistema di antirimbalzo del pulsante o del contatto di misura


// dai un nome agli ingressi e definisci il tipo di variabile
int ledrosso = 9;//variabili intere
int ledverde = 10;
int pulsante ;
int conteggio;//conteggio cicli per antirimbalzo
unsigned long cc;//conteggio cicli attivi per temporizzazione
float f;//frequenza
unsigned long t;//timer dei milisecondi
unsigned long previousMillis = 0;

//Richiamo librerie e definizioni segnali su piedini del display


#include <LCD5110_Basic.h>

LCD5110 myGLCD(3,4,5,6,7);
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];

// setta uscite e ingressi
void setup()
{               
  pinMode(ledrosso, OUTPUT);  
  pinMode(ledverde, OUTPUT);  
  pinMode(pulsante, INPUT);
  Serial.begin(9600); //setta il monitor seriale
  
  //setup per display grafico
  
   myGLCD.InitLCD();
  myGLCD.setContrast(60);
  
  
}

// inizio del loop
void loop() 

{

  pulsante = digitalRead(2); //definizione ingresso digitale al pin()
  
  if (pulsante == HIGH)//se il pulsante viene premuto segui le operazioni sotto
                      //altrimenti saltale fino alla prima parentesi graffa
{ 
  digitalWrite(ledrosso, LOW);    // spegni il led rosso
  for (int conteggio=0; conteggio<=70; conteggio++)//conteggio di "x" cicli per creare l'antiriblalzo del pulsante
  {
  digitalWrite(ledverde, HIGH);  // accendi il led verde

Serial.println(f); //visualizza la frequenza al minuto

//Impostazioni numeri sul display
    
      myGLCD.setFont(BigNumbers);//numeri piccoli sulla prima riga

    myGLCD.printNumF(float(f), 1, RIGHT, 0);//definizione conteggio dei numeri piccoli a destra dello schermo,con decimale(float)
   

}
unsigned long currentMillis = millis();
 t = currentMillis - previousMillis;
     previousMillis = currentMillis; 
     
     f = 60000/t; //calcolo della frequenza al minuto
     

 digitalWrite(ledverde, LOW);
}
   if (pulsante == LOW)//se il pulsante è rilasciato
  {
 digitalWrite(ledrosso, HIGH);   // accendi il led rosso, situazione di standby
}
}