Reputation: 2279
I am playing around with monitoring stuff. For that I like to monitor pins etc. on a regular base. The monitoring app should run in user space and be written in C/C++. I am looking for a good practice how to approach this field of problems generally.
There is a good answer about using timers already here. My question is more general nature. Are timers the best solutions or maybe a wait for a semaphore with a timeout? etc.
I put some pseudo code as a base for the discussion:
// sample with 1kHz
#define fs 1000
// sample time
#define Ts 1.0/fs
// sample data structure
typedef struct sampleStruct {
struct timespec ts;
int sampleData[10];
} sampleType;
void monitorCallback(sampleType * pS) {
}
void sampleThread() {
sampleType s;
struct timespec workingtime;
for (;;) {
// get a timestamp
timespec_get(&(s.ts), TIME_UTC);
// sample data
monitorCallback(s);
// try to measure the time we spent for obtaining the sample
timespec_get(&workingtime, TIME_UTC);
// try to minimize the jitter by correcting the sleeping time
sleep(Ts - (workingtime - s.ts));
}
}
I am looking for solutions, to sample signals etc. periodically, like to detect/measure the jitter in between two samples and use a function for obtaining the sample signal data.
Any ideas are welcome!
Upvotes: 2
Views: 7351
Reputation: 16540
use the function: setitimer()
here is simple example:
struct itimerval tv;
tv.it_interval.tv_sec = 0;
tv.it_interval.tv_usec = 100000; // when timer expires, reset to 100ms
tv.it_value.tv_sec = 0;
tv.it_value.tv_usec = 100000; // 100 ms == 100000 us
setitimer(ITIMER_REAL, &tv, NULL);
And catch the timer on a regular interval by using struct sigaction
.
Here is a simple example of using: struct sigaction
:
struct sigaction psa;
psa.sa_handler = pSigHandler; // << use the name of your signal hander
sigaction(SIGTSTP, &psa, NULL);
and here is a simple implementation of the function: pSigHandler()
static void pSigHandler(int signo)
{
switch (signo)
{
case SIGTSTP:
printf("TSTP");
fflush(stdout);
break;
}
}
Of course, for all the above to work, need the two following statements:
#include <stdio.h>
#include <signal.h>
There is a problem with the above code, There is a long list of functions that 'should' not be used in a signal handler. printf()
is one of the problematic functions. My suggest is just have the signal handler function set a flag and the main function watching that flag and when found 'set', reset it and perform the necessary activities.
Upvotes: 3
Reputation: 1150
I won't impose how you should use threads, since this depends on your other code.
From C++11 there is a time manipulation module (std::chrono
) in the standard library. Use it with std::this_thread::sleep_until
:
#include <chrono>
#include <thread>
// ... in your code ...
namespace chr = std::chrono;
// steady_clock is better than system_clock in this case.
// You should also consider high_resolution_clock.
auto currentTime = chr::steady_clock::now();
auto targetTime = currentTime + chr::seconds{30};
// sleep until the targetTime
std::this_thread::sleep_until(targetTime);
Upvotes: 1
Reputation: 62553
No. This is will not work for your purposes. Linux is no RTOS, and there is absolutely no guarantee what your process will be awaken at a requested time. It is not even a C++ question, it is an OS question.
The best way to achieve what you are doing on Linux I know of is to have a real-time process bound to isolated CPU, doing busy wait and waiting for a certain number of CPU cycles to pass before next sample.
Upvotes: 2
Reputation: 5131
You have to assume that the sleep()
and also the "measuring of the monitoring time" is very imprecise.
If you would like to monitor things at regular intervals you have to change your code to wait until the next interesting point in time e.g.:
void sampleThread() {
sampleType s;
for (;;) {
// get a timestamp
timespec_get(&(s.ts), TIME_UTC);
// sample data
monitorCallback(s);
// Wait until the next sampling time.
struct timespec now;
timespec_get(&now, TIME_UTC);
sleep(now - s.ts);
}
}
The most important point is to sleep/wait until the next absolute point in time, and to calculate this next absolute point in time solely based on your target interval, not based on any measured time or anything. This way any inaccuracies in sleep()
and in execution time do not matter at all. In the code above you can replace the sleep()
call with sleep((now - s.ts) / 2)
and it will still hit the target frequency in the long run (just as an extreme example for a sleep implementation which only ever sleeps half as long as requested).
Upvotes: 1