dubbi sulla funzione millis()

sto provando la funzione millis perchè ho dei sensori che hanno dei tempi di recupero di 50ms, e adesso sto provando con 4 led e un arduino 2009 per poi applicarlo anche ai sensori ma ho dei dubbi.... questo è il codice:

void setup()
{
 pinMode(2,OUTPUT);
 pinMode(3,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);
}

void loop()
{
 byte y;
 unsigned long time[4];
 
 for(y=0;y<4;y++) time[y]=millis();
 
 y=0;
 
 while(3)
 { 
  time[y]=millis()-time[y];
  if(time[y]<6000)delay(time[y]);
  time[y]=millis();
   
  switch(y)
  {
   case 0:
     {
      digitalWrite(2,HIGH);
      delay(random(1000,2000));
      digitalWrite(2,LOW);
      y=1;
     }break;
     
   case 1:
     {
      digitalWrite(3,HIGH);
      delay(random(1000,2000));
      digitalWrite(3,LOW);
      y=2;
     }break;
   
   case 2:
     {
      digitalWrite(4,HIGH);
      delay(random(1000,2000));
      digitalWrite(4,LOW);
      y=3;
     }break;
   
   case 3:
    {
     digitalWrite(5,HIGH);
     delay(random(1000,2000));
     digitalWrite(5,LOW);
     y=0;
    }break;
  } 
 } 
}

volevo provare ad accendere un led alla volta per un tempo random da 1 a 2 secondi e fare in modo che il led stia spento per almeno 6 secondi, il codice è giusto no?
il programma sembra che funzioni ma non capisco perchè ogni tanto si blocchi e aspetti altri 6 secondi per niente, a parte all'inizio dove aspettare ovviamente deve settare i tempi sul primo giro, succede anche dopo ma non capisco perchè... ho sbagliato qualcosa nel programma? :~
ci sono problemi nell'usare la funzione millis con gli ATtiny?
grazie :slight_smile:

macheccasini stai combinando?

non usare il while.

fai una digitalWrite high, un delay random tra 1 e 2 secondi, una write low, delay di random + delay 6 secondi

edit: per sostituire la delay con una millis, ti basta un semplice if

ma a me interessa capire la funzione millis... Dopo in questo codice devo mettere dei sotto-programmi per i sensori all posto dei accendi e spegni i led, questo è solo per capire se e come funziona

la millis ti dice il numero di millisecondi trascorsi a partire dall'accensione dell'arduino.
Il valore è un unsigned long, quindi si resetta più o meno ogni 70 giorni se non erro.

Se vuoi aspettare un tot, per esempio 1000 millis, allora fai così: leggi la millis attuale, sommi 1000, e poi controlli ogni loop se la millis da un valore >= del valore calcolato, se è vero esegui la funzione e ricalcoli il prossimo tempo. mi raccomando anche il maggiore, metti che qualche parte di codice usi più tempo del previsto, rimastesti "intrapolato"

Va in overflow ca ogni 49 giorni e mezzo;
Il micros() va in overflow ca dopo 70 ore.
Ciao UWE

Premesso che non riesco a capire la logica del tuo programma, la definizione di time[] messa nel loop significa che ogni volta che il programma riparte, viene reinizializzato l'array, con conseguente attesa dei 6 secondi.
Devi spostare quella dichiarazione prima del setup, in modo da farla diventare globale, oppure usare static affinché conservi il valore ad ogni iterazione di loop().

Poi mi pare che la struttura che hai usato è un inutile spreco di risorse dato che se devi accendere 1 solo led per volta ed ogni volta che lo accendi attendere un tempo casuale, puoi benissimo usare una variabile singola per gestire solo il led da accendere. Poi non so cosa devi fare esattamente nella versione finale dello sketch per cui questa indicazione prendila con le molle.

ok ok grazie ho capito abbastanza, comunque dopo nel programma finale devo mettere delle funzioni dove leggo ed elaboro i dati dei sensori al posto dei led, questo è solo per provare se la base funziona, dopo metto assieme tutti i pezzi :wink:
non ho capito quello che dici sulle variabili... Se sono dentro il while il programma non riparte mai o sbaglio?
Se uso la funzione pulseIn durante il programma crea qualche problema a millis?
E con i tiny non cio dovrebbero essere problemi no?

A me pare che ad ogni ciclo dopo l'accensione del 4° led, il tuo codice si fermi 6 secondi.
Comunque è molto ingarbugliato, sinceramente non ho capito la logica che dovrebbe rispettare. :sweat_smile:

eh non è da escludere :blush: comunque dopo lo sistemo e lo riprovo e vi so dire...
Se uso la funzione pulseIn durante il programma crea qualche problema a millis?
E con i tiny cio sono problemi con millis?

PulseIn blocca il codice per un determinato lasso di tempo in attesa di un segnale sul pin, quindi tieni conto di questa cosa.

Delay e millis funzionano sui Tiny come sull'Arduino.

ok ma non impedisce il correto funzionamento di millis?
Grazie

Che intendi per "corretto funzionamento"?

bo non so, magari pulseIn crea qualche "interferenza", non so come funzionano realmente le funzioni :blush: anche pulseIn si basa sul tempo...
ma non dovrebbe dare problemi, è solo per essere sicuro :sweat_smile:

ok ho modificato il codice, così pare che funzioni molto meglio :slight_smile: ma non so se va bene la parte dove metto un ciclo while senza operazioni...
avete qualche altro consiglio da darmi a rigurardo?

byte y;
unsigned long time[4];

void setup()
{
 pinMode(2,OUTPUT);
 pinMode(3,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);
 
 for(y=0;y<4;y++) time[y]=0;
 y=0;
}

void loop()
{ 
  while(millis()<=time[y]){}
  time[y]=millis()+6000;
   
  switch(y)
  {
   case 0:
     {
      digitalWrite(2,HIGH);
      delay(random(1000,2000));
      digitalWrite(2,LOW);
      y=1;
     }break;
     
   case 1:
     {
      digitalWrite(3,HIGH);
      delay(random(1000,2000));
      digitalWrite(3,LOW);
      y=2;
     }break;
   
   case 2:
     {
      digitalWrite(4,HIGH);
      delay(random(1000,2000));
      digitalWrite(4,LOW);
      y=3;
     }break;
   
   case 3:
    {
     digitalWrite(5,HIGH);
     delay(random(1000,2000));
     digitalWrite(5,LOW);
     y=0;
    }break;
  } 
}

grazie a tutti :wink:

(ripeto questo è solo un codice di prova, dopo al posto di accedi-spegni un led ci devo mettere delle funzioni per leggere e calcolare i dati dei sensori)

Mi limito a risponderti per la parte tecnica: va bene.

mi associo al consiglio di togliere il while. Dal while non puoi uscire, tutto il resto del programma sara' intrappolato li' dentro. il loop stesso di arduinop e' un while.
Sostituiscilo con il "blink without delay"

Testato:
Dal while non puoi uscire,

Per dirla tutta da una "while", ma anche da una "for", puoi uscire quando ti pare usando la "break" indipendentemente dal fatto che la condizione determinante del ciclo sia vera o falsa.

il while non serve a nulla

while(millis()<=time[y]){}

l'assegnamento non ha significato visto che viene fatto ogni loop, come anche lo switch.

cioè? a me questo serve per provare il programma finale che dovrebbe essere una roba tipo così:

void loop()
{
 if((PINA>=B01000000)&&(er==0))
 {
  output:
  x=(PINA & B11000000)/64;
  TinySerial.print(value[x-1]);
  er=1;
 }
 else
 {
  while(millis()<=time[y])
  {
   if(PINA<B01000000)er=0;
   else if((PINA>=B01000000)&&(er==0))goto output;
  }
  time[y]=millis()+50;
  
  switch(y)
  {
   case 0:{BallUS();                y=1;}break;
   case 1:{value[2]=LRUS(value[2]); y=2;}break;
   case 2:{value[1]=FUS();          y=3;}break;
   case 3:{value[0]=BUS();          y=0;}break;
  } 
   
  if(PINA<B01000000)er=0; 
 }
}

ci sto lavorando per sistemarlo...

La domanda posta è: a che dovrebbe servire questo?

while(millis()<=time[y])