Go Down

Topic: Ajuda com função millis() (Read 267 times) previous topic - next topic

rocborges

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:

Code: [Select]

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.
Rodrigo Borges
Vitória-ES-Brasil

bubulindo

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?
This... is a hobby.

rocborges

#2
Apr 11, 2019, 08:46 pm Last Edit: Apr 11, 2019, 08:47 pm by rocborges
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.
Rodrigo Borges
Vitória-ES-Brasil

bubulindo

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.

Code: [Select]


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.
This... is a hobby.

rocborges

Escrevi o código assim:

Code: [Select]
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);
       

      }
    }
    }
      }
  }
 
}


Rodrigo Borges
Vitória-ES-Brasil

rocborges

Escrevi o código assim:

Code: [Select]
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.
Rodrigo Borges
Vitória-ES-Brasil

rocborges

#6
Apr 15, 2019, 06:16 pm Last Edit: Apr 15, 2019, 06:17 pm by rocborges
Boa tarde.

Dando um feedback.

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

https://youtu.be/9gG_Vc2g6X8

Obrigado a todos.
Rodrigo Borges
Vitória-ES-Brasil

Go Up