2019年02月09日
XML
カテゴリ: Linux
通常、アプリの中でターミナルを使ってキーボードから入力するには、
標準入力として、fgets()なんかを使うのだけど、
エコーもあって使いやすいのだけど、enterを押すまでスレッドが止まってしまう・・・。
もちろん、止まっててもよいように、キー入力用スレッドを別に作ってもいいのだけど、
あまりスレッドをポイポイ作らない方が、実時間実効性を確保できそうで、
ちょろっと調べて、入力待ちしない設定にできることが判明。

参考にしたのは​ ここ ​。

コードはこんな感じ。

#include <stdio.h> // printf
#include <stdlib.h> // exit,strtol
//#include <sys/time.h> // gettimeofday
#include <time.h> // clock
#include <pthread.h> // pthread
#include <termios.h> // termios
#include <unistd.h> // read & write
#include <sys/types.h> // open
#include <sys/stat.h> // open
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <string.h> // memcpy
#define hz 200 // 5msec
#define N_servo 23
pthread_mutex_t mutex_servo;
pthread_cond_t  cond_servo;
int POS[N_servo];
int TCH[N_servo];
int timer_servo;
int stop_request;
/**********************/
/*   サーボスレッド   */
/**********************/
void *servo_thread(void *arg)
{
 struct timespec tsb,tsrq;
 int sPOS[N_servo];
 int sTCH[N_servo];
 int i;
 /* タイマ初期化 */
 clock_gettime(CLOCK_REALTIME,&tsb);
 tsb.tv_sec++;
 tsb.tv_sec++;
 tsb.tv_nsec = 0;
 clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,&tsb,NULL);
 timer_servo = 0;
pthread_mutex_lock(&mutex_servo);
 /* 繰り返し処理 */
while(!stop_request)
{
 /* POS読み込み */
 memcpy(sPOS,POS,sizeof(int)*N_servo);

pthread_mutex_unlock(&mutex_servo);
 /* 処 理 */
 for(i = 0; i < N_servo; i++) {
  sTCH[i] = 0;
 }
 /* 時刻指定スリープ */
 tsrq.tv_sec = tsb.tv_sec + (timer_servo + 1) / hz;
 tsrq.tv_nsec = ((timer_servo + 1) % hz) * (1000000000 / hz);
 if(clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,&tsrq,NULL) != 0)
 {
  printf("Error: on clock_nanosleep.\n");
  exit(1);
 }
pthread_mutex_lock(&mutex_servo);
 /* タイマ処理 */
 timer_servo++;
 /* TCH書き込み */
 memcpy(TCH,sTCH,sizeof(int)*N_servo);
 /* メインスレッドに通知 */
 pthread_cond_signal(&cond_servo);
}
pthread_mutex_unlock(&mutex_servo);
 return NULL;
}
/**********************/
/*   メインスレッド   */
/**********************/
int main(int argc, char **argv)
{
 pthread_t thread_servo;
 int mPOS[N_servo];
 int mTCH[N_servo];
 int timer_main;
 int old_sec;
 int i;
 char c;
 struct termios term_attr,term_backup;
 struct timespec tsm;
 /* 標準入力設定(入力待ちなし) */
 tcgetattr(0,&term_attr);
 term_backup = term_attr;
 term_attr.c_lflag &= ~(ICANON|ECHO);
 term_attr.c_cc[VMIN] = 0;
 term_attr.c_cc[VTIME] = 0;
 tcsetattr(0,TCSANOW,&term_attr);
 fcntl(0,F_SETFL,O_NONBLOCK);
 stop_request = 0;
 old_sec = 0;
 /* POS初期化 */
 for(i = 0; i < N_servo; i++) {
  POS[i] = 0;
 }
 /* サーボスレッド作成 */
 pthread_mutex_init(&mutex_servo,NULL);
 pthread_cond_init(&cond_servo,NULL);
 if(pthread_create(&thread_servo,NULL,servo_thread,NULL) != 0)
 {
  printf("Error: Failed to create servo thread.\n");
  exit(1);
 }
pthread_mutex_lock(&mutex_servo);
 /* 繰り返し処理 */
while(1)
{
 /* サーボスレッドの通知待ち */
 if(pthread_cond_wait(&cond_servo,&mutex_servo) != 0)
 {
  printf("Error: on pthread_cond_wait.\n");
  exit(1);
 }
 /* タイマ処理 */
 timer_main = timer_servo;
 /* TCH読み込み */
 memcpy(mTCH,TCH,sizeof(int)*N_servo);

pthread_mutex_unlock(&mutex_servo);
 /* 入力処理 */
 if ( read(0, &c, 1) == 1 ) {
  if ( c == 's' ) break;
 }
 /* 処 理 */
 clock_gettime(CLOCK_REALTIME,&tsm);
 printf("%d %ld\n",timer_main,tsm.tv_nsec);
 if ( timer_main / hz > old_sec ) {
  old_sec++;
  printf("%d sec\n",old_sec);
 }
 for(i = 0; i < N_servo; i++) {
  mPOS[i] = 0;
 }
pthread_mutex_lock(&mutex_servo);
 /* POS書き込み */
 memcpy(POS,mPOS,sizeof(int)*N_servo);
}
 /* ストップ処理 */
 stop_request = 1;
 if(pthread_join(thread_servo,NULL) != 0)
 {
  printf("Error: Failed to wait for servo thread termination.\n");
  exit(1);
 }
 pthread_mutex_destroy(&mutex_servo);
 pthread_cond_destroy(&cond_servo);
 /* 標準入力復帰 */
 tcsetattr(0,TCSANOW,&term_backup);
 return 0;
}





お気に入りの記事を「いいね!」で応援しよう

最終更新日  2019年02月09日 23時10分13秒
[Linux] カテゴリの最新記事


【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! -- / --
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x
X

PR

キーワードサーチ

▼キーワード検索

プロフィール

nisiken2002

nisiken2002

お気に入りブログ

まだ登録されていません

© Rakuten Group, Inc.
Mobilize your Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: