/* v0.95 2008/08/15 : 64BitOS対応(単精度実数->倍精度実数):使用環境 KaracrixBuilder v3.00Beta19 以上 */ /* v0.94 2007/12/02 */ /* v0.93 2007/11/04 */ /* v0.92 2007/10/28 */ /* v0.91 2007/07/13 */ /* 通信プログラム全体把握勉強用サンプルプログラム (TK0040A装置→1台用) */ /* 要注意:動作解説単純化させるためdi001,do001,pi001,ai001,ao001オブジェクトのみの稼働です */ /* ※各データはプログラム内に埋め込み固定させています。IPアドレスも埋め込んでいます */ #include main(argc,argv) int argc; char *argv[]; { int sockid,len,adval,pwmval; struct sockaddr_in sndaddr,rcvaddr; char sndbuff[512],rcvbuff[512]; char seq[64],ans[64]; char di_s[16],dti_s[16],do_s[8]; int pi[6],ai[4],ao[2]; int objid,di001,do001; int objid_di001,objid_do001; int objid_pi001,objid_ai001,objid_ao001; double fval,hi,low; KcxIntFlt_t udata; /* 初期設定 */ kcxinit( argc, argv ); /* ソケットの作成 */ sockid = socket( AF_INET, SOCK_DGRAM, 0 ); memset( (void *)&sndaddr, 0, sizeof(sndaddr) ); sndaddr.sin_family = AF_INET; sndaddr.sin_port = htons ( 20000 ); /*リモートIOのポート番号*/ sndaddr.sin_addr.s_addr = inet_addr( "192.168.0.200" ); /*リモートIOのIPアドレス*/ memset( (void *)&rcvaddr, 0, sizeof(rcvaddr) ); rcvaddr.sin_family = AF_INET; rcvaddr.sin_addr.s_addr = htonl( INADDR_ANY ); rcvaddr.sin_port = htons( 30000 ); /*自分(PC)のポート番号*/ bind( sockid, (struct sockaddr *)&rcvaddr, sizeof(rcvaddr) ); /* ポイント・オブジェクトID取得 */ objid_di001 = kcxobj_open( "di001" ); objid_do001 = kcxobj_open( "do001" ); objid_pi001 = kcxobj_open( "pi001" ); objid_ai001 = kcxobj_open( "ai001" ); objid_ao001 = kcxobj_open( "ao001" ); while( 1 ){ /* == TK0040A状態監視 == */ /* コマンド送信&応答受信 */ strcpy( sndbuff, "123A mix" ); len = karacrix_com( sockid, &sndaddr, &rcvaddr, sndbuff, strlen(sndbuff), rcvbuff, sizeof(rcvbuff) ); if( len <= 0 ){ sleep(1); continue; } /* 応答パケット展開&データ取得 */ rcvbuff[len] = (char)0; sscanf( rcvbuff, "%s%s%s%s%d%d%d%d%d%d%s%d%d%d%d%d%d", seq, ans, di_s, dti_s, &pi[0],&pi[1],&pi[2],&pi[3],&pi[4],&pi[5], do_s, &ai[0],&ai[1],&ai[2],&ai[3], &ao[0],&ao[1] ); /* ポイント・オブジェクト値設定 */ if( di_s[0] == (int)'1' ) di001 = 1; /* Di01→ON 判定 */ else di001 = 0; /* Di01→OFF判定 */ if( do_s[0] == (int)'1' ) do001 = 1; /* Do01→ON 判定 */ else do001 = 0; /* Do01→OFF判定 */ kcxobj_stat_iwt( objid_di001, di001 ); /* Di01値設定 */ kcxobj_stat_iwt( objid_do001, do001 ); /* Do01値設定 */ kcxobj_stat_iwt( objid_pi001, pi[0] ); /* Pi01値設定 */ kcxobj_scale_frd( objid_ai001, &hi, &low ); /* Ai01スケール取得 */ fval = ( hi - low ) * (double)ai[0] / 1024.0 + low; /* AD値→単位値変換 */ kcxobj_stat_fwt( objid_ai001, fval ); /* Ai01値設定 */ kcxobj_scale_frd( objid_ao001, &hi, &low ); /* Ao01スケール取得 */ fval = ( hi - low ) * (double)ao[0] / 256.0 + low; /* DA値→単位値変換 */ kcxobj_stat_fwt( objid_ao001, fval ); /* Ao01値設定 */ /* == TK0040A操作 == */ /* 送信データ蓄積検査と取得(オブジェクトIDとデータ(整数or実数)) */ switch( kcxobj_sndstat_fromkcx( &objid, &udata ) ){ case KcxINTEGER: /* デジタル型→Do型 */ if( objid == objid_do001 ){ /* do001のID検査パス、そしてdo001制御データのみ(他は現状維持)送信 */ if( udata.i == 1 ) sprintf( sndbuff, "123A dout 1---" ); else sprintf( sndbuff, "123A dout 0---" ); karacrix_com( sockid, &sndaddr, &rcvaddr, sndbuff, strlen(sndbuff), rcvbuff, sizeof(rcvbuff) ); } break; case KcxFLOAT: /* アナログ型→Ao型 */ if( objid == objid_ao001 ){ /* ao001のID検査パス、そしてao001制御データ(DA値)のみ(他は現状維持)送信 */ kcxobj_scale_frd( objid_ao001, &hi, &low ); adval = (int)( 256.0 * ( udata.f - low ) / ( hi - low ) ); if( adval < 0 ) adval = 0; /*制限チェック*/ if( adval > 255 ) adval = 255; /*制限チェック*/ sprintf( sndbuff, "123A aout %d -1", adval ); karacrix_com( sockid, &sndaddr, &rcvaddr, sndbuff, strlen(sndbuff), rcvbuff, sizeof(rcvbuff) ); /** 以下アナログ出力をRC/PWMにも連動出力させています **/ pwmval = (int)( 10000.0 * ( udata.f - low ) / ( hi - low ) ); if( pwmval < 0 ) pwmval = 0; /*制限チェック*/ if( pwmval > 10000 ) pwmval = 10000; /*制限チェック*/ sprintf( sndbuff, "123A pwmout %d -1 -1", pwmval ); karacrix_com( sockid, &sndaddr, &rcvaddr, sndbuff, strlen(sndbuff), rcvbuff, sizeof(rcvbuff) ); } break; default: break; } /* == ウエイト == */ kcxtim_tsleep( 100000 ); /* CPU負荷和らげるため必ず必要(100msec) */ } } /* IPデータ送信し応答受けるプログラム(以下興味有る方はBSDソケットライブラリ参照) */ karacrix_com( sockid,sndaddr,rcvaddr,sndbuff,sndlen,rcvbuff,rcvlen ) int sockid; /* ソケットID */ struct sockaddr *sndaddr; /* 送信アドレス */ struct sockaddr *rcvaddr; /* 受信アドレス */ char sndbuff[]; /* 送信データバッファ */ int sndlen; /* 送信データ長 */ char rcvbuff[]; /* 受信データバッファ */ int rcvlen; /* 受信データバッファ長 */ { int len,retry; char snd_frameidname[128]; char rcv_frameidname[128]; sscanf( sndbuff, "%s", snd_frameidname ); for( retry = 0; retry < (5); retry ++ ){ rcv_frameidname[0] = (char)0; rcvbuff [0] = (char)0; len = karacrix2_com( sockid,sndaddr,rcvaddr,sndbuff,sndlen,rcvbuff,rcvlen ); if( len <= 0 ){ sleep( 1 ); continue; } rcvbuff[len] = (char)0; sscanf( rcvbuff, "%s", rcv_frameidname ); if( strcmp( snd_frameidname, rcv_frameidname ) == 0 ){ return len; /*正常終了*/ }else{ sleep( 1 ); continue; } } return (-1); /*失敗終了*/ } karacrix2_com( sockid,sndaddr,rcvaddr,sndbuff,sndlen,rcvbuff,rcvlen ) int sockid; struct sockaddr *sndaddr; struct sockaddr *rcvaddr; char sndbuff[]; int sndlen; char rcvbuff[]; int rcvlen; { int i,len,fds,addrlen; fd_set fdset; struct timeval tm; /*受信バッファクリア*/ for(i=0;i<100;i++){ fds = 1 + sockid; FD_ZERO( &fdset ); FD_SET ( sockid, &fdset ); tm.tv_sec = tm.tv_usec = (0); if( select( fds,&fdset,(fd_set *)NULL,(fd_set *)NULL,&tm ) <= 0 ){ break; } addrlen = sizeof(struct sockaddr); (void)recvfrom( sockid,(void *)rcvbuff,rcvlen,0,rcvaddr,&addrlen ); } /* 送信チェック */ fds = 1 + sockid; FD_ZERO( &fdset ); FD_SET ( sockid, &fdset ); tm.tv_sec = (1); tm.tv_usec = (0); if( select( fds,(fd_set *)NULL,&fdset,(fd_set *)NULL,&tm ) <= 0 ){ //perror("sendto-select"); return 0; } /* データ送信 */ addrlen = sizeof(struct sockaddr); (void)sendto( sockid,(void *)sndbuff,sndlen,0,sndaddr,addrlen ); /* 受信チェック */ FD_ZERO( &fdset ); FD_SET ( sockid, &fdset ); tm.tv_sec = (10); /*要調整(ハング回避:無線LAN介入時等遅延可能性大の場合は30〜60)*/ tm.tv_usec = (0); if( select( fds,&fdset,(fd_set *)NULL,(fd_set *)NULL,&tm ) <= 0 ){ //perror("recvform-select"); return 0; } /* データ受信 */ if(( len = recvfrom( sockid,(void *)rcvbuff,rcvlen,0,rcvaddr,&addrlen )) < 0 ){ //perror("recvfrom-func"); return 0; } return len; /*受信データ長*/ } /* FILE_END */