Estouro da função Millis()

Boa Noite a Todos,

Desculpem resgatar esse topico tão antigo mas fiz varias pesquisas e não encontrei claramente como "dar a volta" na função millis.

Gostaria da ajuda de voces! Estou em um projeto de estufa de hortaliças estou usando a função millis() para medição de umidade do solo e ao mesmo tempo habilitar uma solenoide para liberara agua.

Sendo assim não consigo usar o delay() pois "travaria" a medição de umidade e não ia desabilitar a solenide ou vice e versa.

A função millis() estoura em ~48 dias com isso pode ser que meu programa trave na solenoide com a agua aberta e cause um desastre, se alguem necessitar do codigo inteiro ou somente a parte do millis é só falar que eu posto aqui.

Obrigado e Agradeço a todos desde já!!!! :grinning:

Pode usar um RTC.

a funcao millis() como vc falou reseta a cada 47dias +-.
desta forma, o valor comeca do zero novamente.
o que eu faco aqui é criar um timer, que a cada 4294967200 millisegundos avisa o programa que o millis vai resetar.

timer.setInterval(4294967200L, FuncaoResetMillis);
esse valor 4294967200 é um pouco antes do millis estourar.
no meu caso eu uso essa funcao para saber quanto tempo a placa ta ligada...

nao sei se no seu caso seria possivel, mas vc poderia fazer uma funcao para reiniciar o arduino a cada X dias, por exemplo quando millis for mair q X, reinicia a placa...

Segue o trecho do codigo pois esta muito grande,

Tenho um sensor DHT e preciso fazer a leitura sem que o resto do programa trave, pois é uma estufa de plantas, então logo imaginei na pior sutuação que seria a solenoide de abetura de agua ficar travada aberta.... :o

void leitura_temp()
   {
   if ((millis() - delayIntervalo) > intervalo) {       //delayIntervalo => ARMAZENA O TEMPO DE COMPARAÇÃO COM MILLIS 
        unsigned long start = micros();                 //intervalo=> INTERVALO DE LEITURA DO SENSOR DTH - esta setado para 2000ms
        int chk = DHT.read11(DHT11_PIN);       
        unsigned long stop = micros();
        delayIntervalo = millis();
    };
}                                                         //FINAL DA FUNÇÃO LEITURA TEMPERATURA

Tenho um RTC no circuito mas não faço ideia de como utilizar o tempo dele (imagino que dos segundos) para fazer a leitura do sensor.

Gostei dessa ideia de dar um reset no programa antes do millis estourar... porem achei somente esse codigo que nao entendi nada>

void setup(){
}

void(*resetFunc) (void) = 0; 

void loop() {
  resetFunc();
  delay(1000); 
}

Acredito que a cada 1 segundo o arduino da o reset....

Quais são os intervalos que estás a tentar temporizar? O que passa com a função millis() é apenas um problema se a temporização é superior ao valor do que estás a tentar medir (ou seja, 47 dias).

Se quiseres medir uma hora ou um dia, dependendo do tipo de variáveis que usas a função continua a funcionar sem problema algum no código.

Para perceberes melhor o que se passa no código e não andares à caça de gambuzinos vê o link em baixo e os cálculos bem como o código para evitar problemas:

https://www.gammon.com.au/millis

Estou fazendo uma estufa de plantas, e a temporização é para atualizar o sensor de Temperatura, Umidade e Higrômetro, estava utilizando o Millis().

Porem me deram uma luz, como eu tenho no circuito um RTC , eu peguei no pino SQW a frequência de 1Hz, e com essa frequência eu gerei uma interrupção, ficando assim>>>>

Dentro do void setup

RTC.writeSqwPinMode(DS1307_SquareWave1HZ);    //para gerar 1Hz no pino SQW

attachInterrupt(0,leitura_temp,RISING);     // Para a interrupção fazer a função da temperatura

E dentro da função da leitura da temperatura

void leitura_temp()
   {
       DHT1.read11(DHT11_PIN);
     
       digitalWrite(10, !digitalRead(10));  //LED para ter um visual que o programa esta passando por aqui
    }

Coloquei o LED para ter um visual que o codigo esta pasando pela linha interrupção. O led pisca normal mas a temperatura nao é atualizada..... :frowning:

Estou fazendo algo errado?

Como posso fazer se quiser a cada 5s por exemplo?

Com o que tens actualmente podes fazer isto:

//coloca esta variável fora de todas as fnuções para ser global. 
unsigned int segundos = 0; 

//modifica a tua função de leitura da temperatura
void leitura_temp()
   {
       segundos++;
     
       digitalWrite(10, !digitalRead(10));  //LED para ter um visual que o programa esta passando por aqui
    }

//dentro da loop()
//de 5 em 5 segundos, o código lê a humidade. 
if (segundos % 5 == 0) {
   DHT1.read11(DHT11_PIN);
   }

Nunca deves colocar funções que demorem muito dentro de interrupções.

No entanto, com o millis o código ficaria:

//fora de todas as funções...
unsigned long update_time = 0; 
const unsigned long intervalo = 5000; //5 segundos * 1000 milisegundos

//dentro da função loop()
if (millis() - update_time >= intervalo) {
   DHT1.read11(DHT11_PIN);
}

Para temporizações de segundos o millis() serve perfeitamente bem e é mais simples que usar o RTC. Dito isto, também podes fazer exactamente a mesma lógica com os segundos do RTC em vez do resultado do millis()...

Experimenta e diz como resultou.

Nunca deves colocar funções que demorem muito dentro de interrupções.

Eu percebi isso quando coloquei para fazer a leitura toda da temperatura dentro da interrupção, o programa trava....

/
/dentro da loop()
//de 5 em 5 segundos, o código lê a humidade.
if (segundos % 5 == 0)-------------------------------- este comando que nao compreendi % 5==0
{
DHT1.read11(DHT11_PIN);
}

Funcionou perfeitamente mas nao sei oque "%" significa?
ela compara se é igual a 5, e zera?

Eu escrevi assim, me falem se esta correto:

unsigned int temp_leitura=5;



Dentro do setup
            attachInterrupt(0,leitura_temp,RISING); 


Dentro do looping
         if (segundos >= temp_leitura) {
            DHT1.read11(DHT11_PIN);
            digitalWrite(10, !digitalRead(10));
            segundos = 0;


Fora do lopping
        void leitura_temp()
            {
              segundos++;
            }

Eu testei basendo no millis, mas colocando os segundos no lugar

Obrigado
@bubulindo @damyanhansen @luisilva

O operador % é o operador de resto. Se meteres no google dá para perceber o que ele faz, basicamente retorna zero quando o número que é dividido por, no teu caso 5, é um múltiplo.

Como está parece-me confuso, mas funciona.