Re: [问题] 如何固定每个循环的执行周期?

楼主: wtchen (没有存在感的人)   2016-11-09 04:03:42
自问自答:
可以改用 TIMER_ABSTIME
Example:
#define PERIOD 4000000 // 周期为4000000ns (4ms)
void Drone_Loop()
{
struct timespec pause;
clock_gettime(CLOCK_MONOTONIC, &pause);
while(1)
{
pause.tv_nsec += PERIOD;
if(pause.tv_nsec >= 1000000000) {
pause.tv_nsec -= 1000000000;
pause.tv_sec++;
}
ReadData();
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pause, NULL);
}
}
这样干可以不需要用按两次码表或暂停期间执行其他thread的方式。
(可以做到lock-free)
不过似乎没有比较准。
这样说好了,如果普通的nanosleep(time),那latency一定>0。
使用TIMER_ABSTIME的话,latency会是 -x ~ +x 。
※ 引述《wtchen (没有存在感的人)》之铭言:
: 开发平台(Platform): (Ex: Win10, Linux, ...)
: Raspberry pi model B+ / Raspberry pi 3 model B
: 编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出)
: gcc 4.9
: 问题(Question):
: 之前希望能固定数据读取的周期,像这样:
: while(...)
: {
: ReadData();
: _usleep(3600); // 用nanosleep实作,不过单位换成us。
: }
: ReadData()是读取sensor的函式,它有可能读取1-5个sensor
: (共用一个I2C,所以要设lock),
: 因为每个sensor更新资料的周期又不一样
: void ReadData()
: {
: if (out_of_data0) readSensor0();
: if (out_of_data1) readSensor1();
: if (out_of_data2) readSensor2();
: if (out_of_data3) readSensor3();
: if (out_of_data4) readSensor4();
: }
: 其中Sensor0跟Sensor1的周期最短,到没啥问题。
: 问题是Sensor2/Sensor3/Sensor4周期比较长,读取也需要200-400us。
: 只读0/1跟5个全读的所需时间有可能会差到500-600us。
: 之前为了固定住ReadData()的周期,我是这样实作的:
: ....
: pthread_create(thread2, readSensor2); //细节不多写,会意就好
: pthread_create(thread3, readSensor3);
: pthread_create(thread4, readSensor4);
: void ReadData()
: {
: readSensor0();
: readSensor1();
: if (out_of_data2) pthread_cond_signal(&cond[thread1]); // 唤醒thread2
: if (out_of_data3) pthread_cond_signal(&cond[thread1]); // 唤醒thread3
: if (out_of_data4) pthread_cond_signal(&cond[thread1]); // 唤醒thread4
: _usleep(3600);
: }
: (这几个thread被设成读取完自动睡回去,等待下次被唤醒)
: 意思就是说,做完readSensor0/readSensor1就暂停然后开始计时,
: 计时的同时被唤醒的readSensor2/readSensor3/readSensor4可以开始工作。
: 这招让我的周期变化<1ms
: (使用Preempt RT的情况,我想用xenomai应该会更好,等我程式完成的差不多就试)。
: 不过我不太满足就是,想找个可以用lock-free的方法。
: 试过一个方法是这样:
: void ReadData()
: {
: uint64_t time1 = get_nsec(); //使用clock_gettime得到当前时间
: if (out_of_data0) readSensor0();
: if (out_of_data1) readSensor1();
: if (out_of_data2) readSensor2();
: if (out_of_data3) readSensor3();
: if (out_of_data4) readSensor4();
: uint64_t time2 = get_nsec();
: _usleep(4000-(int)(time2-time1));
: }
: 就是按两次码表,把执行的时间算出来,然后周期扣掉执行时间就是该暂停的时间。
: 结果发现clock_gettime太频繁会得到奇怪的结果(不稳定)。
: 不然还有一个办法:把整个ReadData()丢到可以被唤醒的thread去
: void ReadData()
: {
: if (out_of_data0) readSensor0();
: if (out_of_data1) readSensor1();
: if (out_of_data2) readSensor2();
: if (out_of_data3) readSensor3();
: if (out_of_data4) readSensor4();
: }
: void period()
: {
: while(....)
: {
: pthread_cond_signal(&cond[thread_of_ReadData]);
: _usleep(4000);
: }
: }
: 不过有个极小的风险是如果这个thread没有在暂停的时间内跑完就....
: 请问还有别的方法可以让周期的误差更低?
: 补充说明(Supplement):
: 四轴的程式龟速改写中,不要催....

Links booklink

Contact Us: admin [ a t ] ucptt.com