lundi 13 juin 2011

FOX Board : Timer

J'ai eu besoin d'une classe gérant un timer sur la FOXBoard pour faire des lectures périodiques d'un gyroscope.
J'ai utilisé la fonction gettimeofday() de /sys/time.h qui a une precision supérieure à clock().
On peut définir une fonction à appeler périodiquement. Elle doit être du type : void fonction(void* data)

Cette classe utilise la bibliothèque pthread qui est normalement déjà installé sur la Fox. Il faut juste signaler à Eclipse qu'on l'utilise : Project->Properties->C/C++ General->Path and Symbols->Librairies->Add "pthread"

Timer.h :
/*
 * Timer.h
 *
 *  Created on: 12 juin 2011
 *      Author: Eliott
 */

#ifndef TIMER_H_
#define TIMER_H_

#include <sys/time.h>
#include <iostream>
#include "pthread.h"

class Timer {
public:

    Timer(int wait); // wait en ms

    void setCall(void(*fonction)(void*),void* arg); // fonction à appeler périodiquement
    void start();
    void stop();

private :
    static void* callRun(void* data);
    void run();

    int wait;
    void(*fonction)(void*);
    void* arg;
    struct timeval start_t, end_t;
    pthread_t thread;
};

#endif /* TIMER_H_ */


Timer.cpp :
#include "Timer.h"


Timer::Timer(int wait) {
    this->wait=wait;
    thread=0;
}
//****************************************************************************
void Timer::setCall(void(*fonction)(void*),void* arg){
    this->fonction = fonction;
    this->arg =arg;
}
//****************************************************************************
void Timer::start(){
    if(thread==0)
        pthread_create(&thread,NULL,callRun,this);
}
//****************************************************************************
void* Timer::callRun(void* data){
    Timer *t = reinterpret_cast<Timer*>(data);
    t->run();
    return NULL;
}
//****************************************************************************
void Timer::stop(){
    if(thread!=0){
        pthread_cancel(thread);
        thread=0;
    }
}
//****************************************************************************
void Timer::run(){
    double temps;
    while(1){
        gettimeofday(&start_t, NULL); // Récupération temps début
        if(fonction!=NULL) fonction(arg); // appel de la fonction définie par setCall
        temps=0;
        while(temps<wait){
            gettimeofday(&end_t, NULL); // Récupération temps fin
            temps = (end_t.tv_usec-start_t.tv_usec+2)/1000;
            temps += (end_t.tv_sec-start_t.tv_sec)*1000;
        }
    }
}


Voici un main d'exemple qui affiche un compteur toute les 10 ms pendant 30 secondes.
On doit donc avoir 3000 affichages à la fin.
main.cpp :
#include "Timer.h"
#include <iostream>
using namespace std;

// afficher le compteur et l'incrementer
void afficher(void *data){
 cout<<(*(int*)data)++<<endl;
}


int main(void) {
 int compteur = 0;
 Timer timer(10);
 timer.setCall(afficher,&compteur);

 timer.start();
 sleep(30);
 timer.stop();

 return 0;
}

Aucun commentaire:

Enregistrer un commentaire