Ajuda com função millis()

Boa tarde.

Escrevi um código com as características abaixo:

  • se condição 1 for satisfeita

  • conta um intervalo de tempo 1 pré definido

  • se condição 2 for satisfeita

  • conta um intervalo de tempo 2 pré definido

  • se condição 3 for satisfeita

  • conta um intervalo de tempo 3 pré definido e executa uma rotina

Obs: o tempo até chegar na execução dessa rotina, se satisfeita as 3 condições acima, deve ser a soma do tempo 1 + tempo 2 + tempo 3

Estou fazendo da forma abaixo:

void loop() {


if (condição1){

unsigned long previous_millis = millis();
while(millis() - previous_millis <= interval1);


if (condição2){


unsigned long previous_millis = millis();
while(millis() - previous_millis <= interval2);

if (condição3){


unsigned long previous_millis = millis();
while(millis() - previous_millis <= interval3);


if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("tempo: ");
unsigned long tempo = millis();
lcd.println(tempo);
digitalWrite(saida_1, ledState);

}

}

}
}

Para o caso de interval1 = interval2 = interval3 = 2000, o intervalo de atraso ficou em 6000 (está certinho).

Porém reparei que na primeira passada o tempo medido é de 6021, na segunda passada é de 12030 e assim por diante abaixo:

18041

24051

30061

36071

42081

48091

54102

60113

Nota-se um erro em cada passada que tem a tendência de ir aumentando e prejudicar o funcionamento da aplicação.

Acredito que isso ocorre devido a duração das operações a serem realizadas e do tempo que a própria função leva para obter o valor da função millis() e efetuar a comparação.

A dúvida é justamente sobre isso. Existe alguma correção para esse erro?

Existe uma forma de após a conclusão das ações, "resetar" o contador? Daí a próxima vez que entrar na condição o tempo começaria do zero. É possível?

Agradeço qualquer ajuda.

O teu problema é que cada passo espera pela condição do millis (estás a usar ciclos while). Isto empanca o processador e o que tu notas é o acumular do processamento das instruções.

As tuas condições são sinais externos? A condição tem de ficar sempre presente durante esse tempo ou basta que aconteça momentâneamente para iniciar a contagem?

Eu achava que usando dessa forma seria como aquele exemplo de blink without delay que não empacasse o processador.

Existe uma forma de fazer sem empacar o processador?

As condições são externas e precisam ficar sempre presentes.

A função delay é literalmente um ciclo while como o que tu programaste.
A maneira de conseguir fazer isto é através de if's em vez do while. Para tal vais precisar de ter variáveis que guardam o estado da funcionalidade que queres.

unsigned char condicao = 0;
unsigned char condicao_anterior = 0;
unsigned long condicao_tempo = 0; 

if ((condicao != condicao_anterior) && (condicao == TRUE)) { // se o sinal mudou de estado. 
    condicao_tempo = millis();
    }

if (condicao == TRUE && millis()-condicao_tempo >= interval1) {
   //faz o que pretendes...
}

A função loop é um ciclo (como um while) e como tal vai correndo todas as condições ao mesmo tempo. Se quiseres, podes criar um bit de temporização para indicares que a temporização está a correr.

Escrevi o código assim:

void loop() {

if (condition1){
                                                                               
    unsigned long current_millis = millis();
    if (current_millis - previous_millis > interval){
      previous_millis = current_millis;  
         
    if (condition2){

      unsigned long current_millis = millis();
    if (current_millis - previous_millis > interval){
      previous_millis = current_millis;
    
      if (condition3){

                               
        lcd.clear();
        lcd.setCursor(0, 1);
        lcd.print("tempo: ");
        unsigned long tempo = millis();
        lcd.println(tempo/1000);
        

      }
    }
    }
      }
  }
  
}

Escrevi o código assim:

unsigned long previous_millis = 0;
const long interval = 2000;


void loop() {

 if (condition1){
                                                                              
   unsigned long current_millis = millis();
   if (current_millis - previous_millis > interval){
     previous_millis = current_millis;  
        
   if (condition2){

     unsigned long current_millis = millis();
     if (current_millis - previous_millis > interval){
       previous_millis = current_millis;  
   
     if (condition3){

                                  
       lcd.clear();
       lcd.setCursor(0, 1);
       lcd.print("tempo: ");
       unsigned long tempo = millis();
       lcd.println(tempo/1000);
       

     }
   }
   }
     }
 }

}

Como const long interval = 2000 e após satisfeita as condições 1, 2 e 3 não deveria ter um intervalo de 4 segundos?

Ocorre que está executando as ações após a terceira condição ser satisfeita em 2 segundos (contando apenas 1 intervalo).

Preciso que os intervalos sejam cumulativos.

Agradeço a ajuda.

PS.: desculpe se não entendi direto a última sugestão do bubulindo.

Boa tarde.

Dando um feedback.

Consegui meu intento através da referência abaixo:

Obrigado a todos.