Gestione Timer in C++

di il
5 risposte

Gestione Timer in C++

Ciao,
ho un dubbio che definire da principianti è poco, ma che mi sta proprio incasinando la testa...succede...

per esigenze di un mio progetto personale sto studiando un po i PID e quant'altro concerne la sviluppo di un sistema di controllo di un quadcopter.
per mia sfortuna mi sono imbattuto in esempi di codice su internet, ed uno in particolare dove viene gestito un timer come da codice seguente.
/*********TIMER.H****************************/
#ifndef TIMER_H
#define TIMER_H

#include <signal.h>
#include <iostream>
#include <stdint.h>
#include <time.h>

#include "SPIClass.h"
#include "pid.h"
#include "dmp.h"

class TimerClass
{
 public:
  TimerClass();
  TimerClass(const TimerClass& orig);
  virtual ~TimerClass();

  void start();
  void stop();

  float dt;
  timer_t timerId; //id  for the posix timer
  struct sigaction signalAction; //signal action handler struct
  bool started;

 private:
  static void sig_handler_(int signum);
  struct itimerspec timeToSet_;  //time to be set
  struct timespec timeValue_;    //timer expiration value
  struct timespec timeInterval_; //timer period

  timespec oldtime_;
  timespec time_;
  timespec iterationtime_;

  void calcdt_();
  void compensate_();

};

extern TimerClass Timer;
#endif        /* TIMER_H */

/********TIMER.CPP***************************/

#include "timer.h"
#include <fstream>
using namespace std;

#define PERIOD 500000

#define N_RC_CHAN 4
#define N_SERVO 4

#define K_YAW 260
#define K_PITCH 120
#define K_ROLL 120

#define RC_MIN 1000
#define RC_MAX 2000
#define THR_MIN 890
#define THR_MAX 1900

#define YAW 0
#define PITCH 1
#define ROLL 2
#define DIM 3

/*Defines which PID control to use*/
#define PID_STAB
//#define PID_RATE
#define XMODE


TimerClass Timer;
pthread_mutex_t TimerMutex_;

TimerClass::TimerClass()
{
  /* Intialize sigaction struct */
   signalAction.sa_handler = &sig_handler_;

   /* Connect a signal handler routine to the SIGALRM signal */
   sigaction(SIGALRM, &signalAction, NULL);

   /* Allocate a timer */
   timer_create(CLOCK_REALTIME, NULL, &timerId);

   started = false;

 }

 TimerClass::TimerClass(const TimerClass& orig)
 {
 }

 TimerClass::~TimerClass()
 {
 }

void TimerClass::start()
{
  timeValue_.tv_sec = 0;
  timeValue_.tv_nsec = PERIOD;
  timeToSet_.it_value = timeValue_;
  timer_settime(timerId, 0, &timeToSet_, NULL);
  started = true;
}

void TimerClass::stop()
{
  timeValue_.tv_sec = 0;
  timeValue_.tv_nsec = 0;
  timeToSet_.it_value = timeValue_;
  timer_settime(timerId, 0, &timeToSet_, NULL);
  started = false;
}

inline void TimerClass::calcdt_()
{
  oldtime_ = time_;
  clock_gettime(CLOCK_MONOTONIC, &time_);
  Timer.dt = ((static_cast <int64_t>(time_.tv_sec) * 1000000000 +
	       static_cast <int64_t>(time_.tv_nsec)) -
	      (static_cast <int64_t>(oldtime_.tv_sec) * 1000000000 +
	       static_cast <int64_t>(oldtime_.tv_nsec))) / 1000000000.0;
}

inline void TimerClass::compensate_()
{
  //Timer aims to get as close to 400Hz as possible, mostly limited by the I2C
  //bandwidth
  clock_gettime(CLOCK_MONOTONIC, &iterationtime_);
  long inttime = PERIOD - ((iterationtime_.tv_sec * 1000000000 +
			    iterationtime_.tv_nsec) - (time_.tv_sec * 1000000000
						       + time_.tv_nsec));
  if (inttime < 0)
    Timer.timeValue_.tv_nsec = 1;
  else
    Timer.timeValue_.tv_nsec = inttime;
  Timer.timeToSet_.it_value = Timer.timeValue_;
  timer_settime(timerId, 0, &timeToSet_, NULL);
}

template <class T, void(T::*member_function)()>
void* thunk(void* p)
{
  (static_cast<T*> (p)->*member_function)();
  return 0;
}

void TimerClass::sig_handler_(int signum)
{
  pthread_mutex_lock(&TimerMutex_);
  
  //TODO 

  //------------------------------------------------------
  //3- Timer dt
  Timer.calcdt_();
  //printf("dt : %f \n",Timer.dt);

  //------------------------------------------------------

  //TODO
  
  //------------------------------------------------------
  //6-compensate dt
  Timer.compensate_();

  pthread_mutex_unlock(&TimerMutex_);
  //end of interrupt

}

/****************MAIN.H******************************/
#ifndef MAIN_H
#define MAIN_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <fstream>
#include <sstream>

// these have to be put before the
// other local .h files
// otherwise compiling errors show up
#include <sys/socket.h>
#include <fcntl.h>
#include <time.h>

#include "timer.h"


#endif

/****************MAIN.C******************************/
#include "main.h"

int main(int argc, char *argv[])
{
  //Starting Timer
  Timer.start();

  /* Sleeping everything is done via
     software interrupts  */
  while (true){

    usleep(20000);

  }//end
}
ara le parti che mi hanno confuso sono in particolare quelle contenute nel metodo inline void TimerClass::compensate_() ed in particolar modo
 if (inttime < 0)
    Timer.timeValue_.tv_nsec = 1;
  else
    Timer.timeValue_.tv_nsec = inttime;
  Timer.timeToSet_.it_value = Timer.timeValue_;
  timer_settime(timerId, 0, &timeToSet_, NULL);
spero di aver reso l'idea di quale sia la mia confusione.

grazie

5 Risposte

  • Re: Gestione Timer in C++

    Io credo che tu debba darci qualche indicazione in più: compilatore che usi, eventuali librerie, e scheda che usi, se usi una evaluation board, con i componenti che usi (vedo che leggi qualcosa dall'I2C bus...)
  • Re: Gestione Timer in C++

    Allora si.
    il codice è preso da un esempio per Raspberry pi 2, il compilatore usato per questo codice non lo so (credo comunque un gcc per sistemi embedded), anche perché sono in fase di studio per capire le logiche.
    comunque io sto sviluppando su Udoo Neo (basato su ubuntu) con compilatore gcc, per essere sicuri queste sono le procedure che ho seguito per l'installazione della toolchain (http://www.acmesystems.it/arm9_toolchai). la versione attualmente non la ricordo ma entro questa sera la posso recupero.

    comunque in entrambi i casi le periferiche I2C e quant'altro sono gestite da un sistema operativo basato su LINUX.
  • Re: Gestione Timer in C++

    Ho dato un occhiata alla scheda Udoo Neo in tuo possesso: mi sembra che possa montare a bordo non solo un ambiente Linux completo (come Raspberry) ma anche parallelamente un "ambiente" Arduino con relativo firmware (SAM3x Arduino compatible controller).
    Ora, i sorgenti che hai scaricato sono per Raspberry Pi, sul quale gira Linux (abitualmente) e la gestione del timer non può essere precisa (quello che ci vorrebbe per un PID): ma tu hai un Arduino e molto probabilmente devi lavorare su questo.
    Purtroppo ho trovato solo questo http://www.udoo.org/tutorial/interaction-between-linux-and-arduino-on-udoo/ che spiega come eventualmente far dialogare i due "mondi"; non ho trovato niente che spieghi come compilare e caricare il firmware sulla parte Arduino.
    Probabilmente ho detto un sacco di baggianate (so già che mi fucileranno ); magari qualcuno con più esperienza di me può guidarti meglio.
  • Re: Gestione Timer in C++

    M in realtà il mio dubbio era su come veniva gestito il timer. ed in particolare mi confonde l'utilizzo della parte che ho evidenziato.

    per i lresto sono ben conscio su come far funzionare i due ambienti
  • Re: Gestione Timer in C++

    in realtà il mio dubbio era su come veniva gestito il timer. ed in particolare mi confonde l'utilizzo della parte che ho evidenziato.
    Se utilizzi Arduino avrai un timer apposito che programmerai opportunamente con eventuale gestione ad interrupt.
    Il codice che hai riportato è per Linux e quindi non ti è di nessun aiuto!
Devi accedere o registrarti per scrivere nel forum
5 risposte