Enviar respuesta 
[Arduino] tasks / timers (delay sin bloquear)
Autor Mensaje
LuKks Sin conexión
Miembro Sr.


Mensajes: 435
Registro en: Jul 2014
Reputación: 17
Mensaje: #1
[Arduino] tasks / timers (delay sin bloquear)
Alguien en desvirtúe me hizo recordar sobre una librería que hice hace mucho.

La busqué y hasta la había documentado con ejemplos, jajaj Gran sonrisa (bien hecho LuKks del pasado).

Timer.h
Código PHP:
#ifndef Timer_h
#define Timer_h

class Timer
{
    public:
        
Timer();

        
bool second(int iunsigned long secs);
        
bool milli(int iunsigned long ms);
        
bool micro(int iunsigned long ms);

        
bool is(int i);
        
bool check(int i);
        
bool exists(int i);
        
bool remove(int i);

        
float leftSeconds(int i);
        
float leftMillis(int i);
        
long leftMicros(int i);
        
    private:
        
unsigned long _tasks[16][2];
};

#endif 

Timer.cpp
Código PHP:
#include "Timer.h"
#include "Arduino.h"

Timer::Timer() {

}

bool Timer::second(int iunsigned long secs) {
    return 
micro(isecs 1000000);
}

bool Timer::milli(int iunsigned long ms) {
    return 
micro(ims 1000);
}

bool Timer::micro(int iunsigned long ms) {
    
check(i); //check expired

    
if(_tasks[i][1] > 2) {
        return 
false//if there is time yet, false
    
}

    
_tasks[i][0] = micros(); //start
    
_tasks[i][1] = ms 2//ms + state
    
return true;
}

bool Timer::is(int i) {
    
check(i); //check expired

    
if(_tasks[i][1] != 1) {
        return 
false//if not expired, false
    
}

    
_tasks[i][1] = 0//set used
    
return true;
}

bool Timer::check(int i) {
    
//(not used && micros() - start >= ms)
    
if(_tasks[i][1] >= && micros() - _tasks[i][0] >= _tasks[i][1] - 2) {
        
_tasks[i][1] = 1//set expired
        
return true;
    }
    
    return 
false;
}

bool Timer::exists(int i) {
    return 
_tasks[i][1] >= 2;
}

bool Timer::remove(int i) {
    
_tasks[i][1] = 0;
    return 
true;
}

float Timer::leftSeconds(int i) {
    return 
leftMicros(i) / 1000000;
}

float Timer::leftMillis(int i) {
    return 
leftMicros(i) / 1000;
}

long Timer::leftMicros(int i) {
    return 
_tasks[i][1] <= micros() - _tasks[i][0];


keywords.txt
Código PHP:
timer    KEYWORD1
Timer    KEYWORD1
second    KEYWORD2
milli    KEYWORD2
micro    KEYWORD2
is    KEYWORD2
check    KEYWORD2
exists    KEYWORD2
remove    KEYWORD2
getMicros    KEYWORD2
leftSeconds    KEYWORD2
leftMillis    KEYWORD2
getSeconds    KEYWORD2
getMillis    KEYWORD2 

example.ino
Código PHP:
#include <Timer.h>
Timer timer;

enum //task ids
  
tMessages 0,
  
tLed,
  
tAlerts,
  
tInfo
}

void setup() {
    
timer.second(tLed15); //part of example three
}

void loop() {
    
//example one
    
if(timer.milli(tMessages1000)) { //also exists timer.micro
        //executed every second
    
}
    
    
//example two
    //you can create timers inside loop but you have to create the timer below timer.is, otherwise timer.is never executed
    //because the functions to create timers works like timer.is too (showed above with tMessages), check out:
    
if(timer.is(tAlerts)) {
        
//executed every second too
    
}

    
timer.second(tAlerts1);

    
//note: in the first check of the example one will be executed and after every second (test for more understand)

    //example three
    
if(timer.exists(tLed) && digitalRead(6)) { //imagine that pin six it's a button
        
timer.remove(tLed); //also you can remove without check exists, just to show more functions
    
}

    if(
timer.is(tLed)) { //executed one time after 15 seconds (if you didn't press the button)
        
digitalWrite(13HIGH);
    }

    return; 
//the code below will not executed but it's just for show it

    //example four (utility)
    //these functions not check if the task expired, only calculate the time left. Just use for informative purposes:
    
timer.leftSeconds(tLed); //int
    
timer.leftMillis(tLed); //int

    
timer.fLeftSeconds(tLed); //float
    
timer.fLeftMillis(tLed); //float

    
timer.leftMicros(tLed); //int

    //important difference on use, check this out:

    /*on setup:*/ 
timer.second(tLed15);
    
/*on loop:*/ if(timer.leftSeconds(tLed) == 10) { }

    
/*seems the if will be execute after 5 seconds but not, will do after 4 seconds.
    on another words: seems the if will be executed when the seconds left are 10 but not, will do when are 11.

    because when the seconds left are 10.999 (and later 10.998) this always return 10 (always return an integer, not rounded)
    to solve that, we can use fLeftSeconds:*/
    /*on loop:*/ 
if(timer.fLeftSeconds(tLed) == 10.0) { }

    
//you should read this before use floats: https://www.arduino.cc/reference/en/language/variables/data-types/float/*/


Lo publico así tal cual sin cambiar nada, así que si hay algo incorrecto o no se entiende pueden preguntar.

Lo único que no comenté fue que en Timer.h en la parte donde se asignan las variables privadas _tasks[16][2] el 16 indica el número máximo de tasks, seguramente no se puede hacer dinámico por eso está así.
Entonces, si necesitan más task ids simplemente aumentan ese número.

edit: si alguien quiere publicarlo en algún foro de Arduino sería genial, mejor si enlazan hacía esta publicación.

(Este mensaje fue modificado por última vez en: 19/08/2018 12:52 AM por LuKks.)
19/08/2018 12:33 AM
Encuentra todos sus mensajes Cita este mensaje en tu respuesta
Enviar respuesta 


Salto de foro:


Usuario(s) navegando en este tema: 1 invitado(s)

Contáctanos | Allied Modders en español | Volver arriba | Volver al contenido | Archivo (Modo simple) | Sindicación RSS