Gestão de tempo

Boas,

Gostava de saber qual é a melhor maneira de gerir o tempo com o arduino sem ser com a função delay() que bloqueia o programa todo

Estou a usar neste momento a lib TIMER o que faz o trabalho mas acho muito chato cada ver ter que declarar t.every(xxxx, xxx) gostava
guardar o tempo tipo numa array e la ir testar se o testo já passou ou não mas não sei como fazer nem se é uma boa ideia ... falei numa array pois tenho muito delay a usar

Cpts

Zé tretas

Fala ai Zé tretas, eu sofro do mesmo mal. Esse é um problema que vejo nos microcontroladores, o delay para tudo e a implementação de threads ainda me parece um pouco confuso. O site Google Code Archive - Long-term storage for Google Code Project Hosting. esta nos meu favoritos para eu ver quando tiver algum tempo, o que esta difícil ultimamente rs

Eu uso algo parecido com o abaixo para que blocos/métodos sejam executados dentro de intervalos:

#define TempSensor 0
#define StepperMotorX 1

//Array de timers
int intDelay[] = {0,0,0,0};
                
//Array para armazenar a ultima execução
unsigned long longLastMillis[] = {0,0,0,0};

void setup(){
  intDelay[TempSensor] = 500;
  intDelay[StepperMotorX] = 15;
}

void loop (){  
  unsigned long currentMillis = millis();
  //verifico se o tempo já passou para executar o método
  if (currentMillis - longLastMillis[TempSensor] >= intDelay[TempSensor])
  {
    //chamada do método de leitura dos sensores 
    longLastMillis[TempSensor] = currentMillis;
  }
}

Mas, como sempre, depende da aplicação, por exemplo, subistituir um delay entre duas partes de um mesmo bloco me forcou a criar dois blocos e um outro array tipo executar[TempSensor] = true. Assim, um método é executado após x milesimos de segundo:

#define TempSensor 0
#define StepperMotorX 1

//Array de timers
int intDelay[] = {0,0,0,0};
                
//Array para armazenar a ultima execução
unsigned long longLastMillis[] = {0,0,0,0};

//Array para definir se o método será executado
boolean Execute[] = {false, false, false, false};

void setup(){
  Execute[TempSensor] = true;
  intDelay[TempSensor] = 500;
  intDelay[StepperMotorX] = 15;
}

void loop (){
  ReadSensor();
}

void ReadSensor(){
  unsigned long currentMillis = millis();
  //verifico se o tempo já passou para executar o método
  if ((Execute[TempSensor] == true) && currentMillis - longLastMillis[TempSensor] >= intDelay[TempSensor])
  {
    //códigos...
    longLastMillis[StepperMotorX] = currentMillis;
    Execute[StepperMotorX] = true; //para que seja executado após o tempo definido em intDelay[StepperMotorX]
    
    longLastMillis[TempSensor] = currentMillis;
  }
}

void StepperX() {
  unsigned long currentMillis = millis();
  //verifico se o tempo já passou para executar o método
  if (Execute[StepperMotorX] == true && (currentMillis - longLastMillis[StepperMotorX] >= intDelay[StepperMotorX]))
  {
    //chamada do método de leitura dos sensores 
    longLastMillis[StepperMotorX] = currentMillis;
    
    Execute[StepperMotorX] = false; //Evita que seja executado novamente
  }
}

no exemplo acima, o método do sensor é executado o tempo todo (a cada 500 millis por causa do execute = true), mas o método stepperMotor só é executado após 15 millis depois de ser definido o execute = true pelo método.

Vamos aguardar para ver se trazem outras soluções :wink:

O delay para tudo é perpetuado pelos senhores do Arduino que teimam em meter exemplos com delays absurdos.
O delay é uma funcão que faz parte da biblioteca de C para AVRs e, ao contrário do que muita gente pensa ao ler os problemas de usar delay(), tem imensa utilidade e não pode simplesmente ser tirada da biblioteca. O problema é que o delay deve ser usado apenas para pequenas temporizacões. Estamos a falar de dezenas de milisegundos no máximo. Mas como isso não está limitado e a malta do Arduino mete isso como um exemplo, a maior parte das pessoas acha que é perfeitamente normal fazer delays de segundos... ou pior... minutos como já vi.

A solucão do Mortis é a mais correcta no Arduino. Se tiveres um RTC também podes usar isso para temporizar, mas aí só para intervalos de minutos ou horas.

Quanto a threads... enfim... tenho de ver a performance do microcontrolador para ver se realmente é uma solucão decente. No entanto, acho que provavelmente é apenas para os programadores de alto nível se entreterem com microcontroladores. LOL

Boas,

Mortis eu também já fiz algo assim só que usei uma array de 2 dimensões (ou la como de diz em português), mas acho um método muito cansativo e quando o tamanho do programa aumenta fica tudo muito confuso ... mas como sou novato nisto (infelizmente não em tudo :cold_sweat: ) pensava que existia algo mais simples e mais compreensível para uma manutenção e desenvolvimento futuro do programa em que estou a mexer visto que uso muitas pausas.

PS: se alguém tiver algo a propor sou todos ouvidos

Cpts

Zé tretas

bubulindo:
O delay para tudo é perpetuado pelos senhores do Arduino que teimam em meter exemplos com delays absurdos.

Muito bem colocado bubulindo, delay de minutos é doído, as pessoas se esquecem que o microcontrolados para no delay. Mas pelo que vemos, muitos que usam arduino são aventureiros (o pior é que estou neste meio rs) e não possuem domínio em relação a microcontroladores e lógica de programação. E concordo que isso é o mínimo que devemos saber.

bubulindo:
A solucão do Mortis é a mais correcta no Arduino. Se tiveres um RTC também podes usar isso para temporizar, mas aí só para intervalos de minutos ou horas.

Minha solução ainda tem um problema a ser solucionado, quando millis retorna ao zero, mas como minhas aplicações ainda são de coisas que funcionam por poucas horas, não corri à procura de soluções.

bubulindo:
Quanto a threads... enfim... tenho de ver a performance do microcontrolador para ver se realmente é uma solucão decente. No entanto, acho que provavelmente é apenas para os programadores de alto nível se entreterem com microcontroladores. LOL

É, a coisa parece complexa mesmo rs... Mas é bom para distrair um pouco. Quem sabe não subimos um pouco o nível.

tretas:
mas como sou novato nisto (infelizmente não em tudo :cold_sweat: ) pensava que existia algo mais simples e mais compreensível para uma manutenção e desenvolvimento futuro do programa em que estou a mexer visto que uso muitas pausas.

Zé tretas,

Somos todos novatos em alguma área, pois estamos sempre a aprender, e quando ficamos bons em uma área no aventuramos em outra, e somos novatos novamente rs

Sim, diz-se array de 2 dimensões aqui também ;), eu fiz de uma só para facilitar o entendimento.

A lógica que coloquei pode ser encapsulada em uma lib, mas cai na solução que ja utilizas (timer lib).

Vamos ver se alguém tem alguma outra solução, pois eu não consigo pensar em nada alem dos bons e velhos IFs e variáveis ^^

Boas

Minha solução ainda tem um problema a ser solucionado, quando millis retorna ao zero, mas como minhas aplicações ainda são de coisas que funcionam por poucas horas, não corri à procura de soluções.

penso se usares algo do estilo te deves safar ...

if (abs (currentMillis - longLastMillis[TempSensor] >= intDelay[TempSensor]))
  {
    //chamada do método de leitura dos sensores 
    longLastMillis[TempSensor] = currentMillis;

Cpts

Zé tretas

tretas:
penso se usares algo do estilo te deves safar ...

if (abs (currentMillis - longLastMillis[TempSensor] >= intDelay[TempSensor]))

{
    //chamada do método de leitura dos sensores
    longLastMillis[TempSensor] = currentMillis;

Zé Tretas, obrigado pela dica! :smiley:

Mortis:
Minha solução ainda tem um problema a ser solucionado, quando millis retorna ao zero, mas como minhas aplicações ainda são de coisas que funcionam por poucas horas, não corri à procura de soluções.

Se subtraires, creio que não tens problema algum... e não precisas do abs.
Experimenta este programa:

#include <Arduino.h>
/*
what really happens with timer function at millis() rollover?
 lets test it.
 */
unsigned long fakeMillis = 4294967290;     //set fakeMillis to a number near the rollover point
unsigned long mark = fakeMillis;           // set a time marker start of timer
//long mark = fakeMillis;                   // try other type variables
//int  mark = fakeMillis;   
void setup()
{
  Serial.begin(9600);      
}
void loop() {
  do
  {
    ++fakeMillis;                          //increment faketimer          
    Serial.println(fakeMillis);            // prints "timer output" through rollover event
    Serial.println(fakeMillis-mark);      //perform typical subtraction for timer does it work through rollover?
    delay(1000);
  }
  while (fakeMillis>1);   // whatever keep looping 
}

tretas:
mas como sou novato nisto (infelizmente não em tudo :cold_sweat: ) pensava que existia algo mais simples e mais compreensível para uma manutenção e desenvolvimento futuro do programa em que estou a mexer visto que uso muitas pausas.

Usas pausas para quê?

Em português array é vector. Mas pouca gente usa essa definicão.

bubulindo:
Se subtraires, creio que não tens problema algum... e não precisas do abs.

Bubulindo, obrigado novamente! :wink:

Teu programa já esclareceu. Resultado:
4294967291
1
4294967292
2
4294967293
3
4294967294
4
4294967295
5
0
6
1
7
2
8

No passado eu guardava "currentMillis + intDelay" em uma variável, e temia que isso causaria o estouro do unsigned long (as vezes nos previnimos até para o que não precisa rs), mas deu para perceber que quando a variável passa do limite (4294967295 + 1) ela recebe o valor zero.

Excrevi o código abaixo para deixar mais claro que água rs

unsigned long currentMillis = 4294967290;  
unsigned long longLastMillis = 4294967290;

void setup()
{
  Serial.begin(9600);      
}

void loop() {
  currentMillis ++;
  
  if (currentMillis - longLastMillis >= 2)
  {
    Serial.print(currentMillis);
    Serial.print(" - ");
    Serial.print(longLastMillis);
    Serial.println(" >= 2");
    
    longLastMillis = currentMillis;
    
    delay(1000);
  }
}

e o resultado foi:

4294967292 - 4294967290 >= 2
4294967294 - 4294967292 >= 2
0 - 4294967294 >= 2
2 - 0 >= 2
4 - 2 >= 2
6 - 4 >= 2
8 - 6 >= 2
10 - 8 >= 2
12 - 10 >= 2

Agradeço novamente!

Ah, aqui no Brasil também é difícil ver algum dizendo vetor...

bubulindo:
Em português array é vector. Mas pouca gente usa essa definicão.

Discordo veementemente!

Na engenharia a gente somente dizia vetor, cálculo vetorial, etc, etc, etc.

Dizer "array" é coisa de programador que ainda não fez Cálculo!!!

AlxDroidDev:
Dizer "array" é coisa de programador que ainda não fez Cálculo!!!

kkkkk então vivo, e estou, nesse grupo!!! :wink: Nunca fiz um curso de programação ou cálculo 8)

AlxDroidDev:

bubulindo:
Em português array é vector. Mas pouca gente usa essa definicão.

Discordo veementemente!

Na engenharia a gente somente dizia vetor, cálculo vetorial, etc, etc, etc.

Dizer "array" é coisa de programador que ainda não fez Cálculo!!!

Eu já fiz todas as cadeiras de Engenharia... e não vejo o problema de usar ambos os nomes no campo da programação em C. Tu vês?

O importante é ser entendido... ouvimos coisas piores por ai rs