イマダ製フォースゲージ用シリアル通信プログラム
大昔に書いたプログラムを公開しておく
どこかの誰かに刺さればいいな。
GUIはめんどいのでコンソールで動作します。C言語。コンパイル必須なのでわかる人向けです。
OS依存はないはず。COMポートやらボーレートは各自の環境に合わせてカスタマイズしてください。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>//kbhit(),getch()関数のためのヘッダ
#include <windows.h>
//イマダ製フォースゲージ通信ソフト
//コンソール専用
//シリアルケーブル自作すること
#define TIMEOUT 1 //通信タイムアウト設定する=1 しない=0
//シリアル通信設定 対象とあわせること
#define COM_PORT_NAME "COM1"//通信ポートdefault=COM1 test=COM4,5
#define BAUD_RATE 2400
#define BYTE_SIZE 8 // 7 or 8
#define PARITY NOPARITY //NOPARITY, EVENPARITY, ODDPARITY
#define STOP_BIT ONESTOPBIT //ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS
#define F_PARITY TRUE //FALSE
#define WAITTIME 100//msecでウェイトを記入。ボーレートが速ければもっと短く出来そう。
HANDLE hComm; // シリアルポートとの通信ハンドル
int ComInit(void)
{
COMMTIMEOUTS CommTimeOuts;/*通信タイムアウト構造体*/
DCB dcb;
// シリアルポートを開ける
hComm = CreateFile(
COM_PORT_NAME, /* シリアルポートの文字列 */
GENERIC_READ | GENERIC_WRITE, /* アクセスモード:読み書き */
0, /* 共有モード:他からはアクセス不可 */
NULL, /* セキュリティ属性:ハンドル継承せず */
OPEN_EXISTING, /* 作成フラグ: */
FILE_ATTRIBUTE_NORMAL, /* 属性: */
NULL /* テンプレートのハンドル: */
);
if (hComm == INVALID_HANDLE_VALUE) {
printf("シリアルポートを開くことが出来ませんでした。\n");
exit( -1 );
} else {
printf("シリアルポートオーポン、設定中\n");
}
/*イベントなし*/
if(!SetCommMask(hComm,0)) {
CloseHandle(hComm);
return(-2); /*通信マスク設定失敗*/
}
//バッファの設定は無視してデフォルトを使う
#if 0
/*バッファ数*/
if(!SetupComm(hComm,0x1000L,0x1000L)) {
CloseHandle(hComm);
return(-3); /*設定失敗*/
}
#endif
#if TIMEOUT
CommTimeOuts.ReadIntervalTimeout=MAXDWORD;//でふぉ0xffffffff;
CommTimeOuts.ReadTotalTimeoutMultiplier=100;
CommTimeOuts.ReadTotalTimeoutConstant=100;
/*ReadFileの動作すぐに終了する*/
CommTimeOuts.WriteTotalTimeoutMultiplier=20;
CommTimeOuts.WriteTotalTimeoutConstant=10;
/*1バイト書き込みタイムアウトms*/
/*タイムアウト設定*/
if(!SetCommTimeouts(hComm,&CommTimeOuts)) {
CloseHandle(hComm);
return(-4); /*設定失敗*/
}
#endif
// 通信属性を設定する
GetCommState(hComm, &dcb); /* DCB を取得 */
dcb.BaudRate = BAUD_RATE;
dcb.ByteSize = BYTE_SIZE;
dcb.Parity = PARITY;
dcb.fParity = F_PARITY;
dcb.StopBits = STOP_BIT ;
SetCommState(hComm, &dcb); /* DCB を設定 */
return 0;
}
void ComEnd(void)
{
// ハンドルを閉じる
CloseHandle(hComm);
}
int WriteData(char *buff, unsigned int data_size)
{
DWORD dwWritten=0; /* ポートへ書き込んだバイト数 */
WriteFile(hComm, buff, data_size, &dwWritten, NULL);
if (dwWritten != data_size) {
printf("データの送信に失敗しました。\n");
return -1;
}
Sleep(WAITTIME);
return 0;
}
/*=======================================
受信バイト数のチェック
=======================================*/
DWORD rs_check(void)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
/*エラーがあったらクリア*/
ClearCommError(hComm,&dwErrorFlags,&ComStat);
/*受信バイト数を返す*/
return(ComStat.cbInQue);
}
int ReadData(char *buff, unsigned int max_size)
{
DWORD dwRead;
DWORD dwCount;
dwCount = rs_check();
if (dwCount > max_size) {
printf("バッファサイズが足りません dwCount=%d, max=%d\n", dwCount, max_size);
return -1;
}
ReadFile(hComm, buff, dwCount, &dwRead, NULL);
if (dwCount != dwRead) {
printf("データの受け取りに失敗しました。\n");
return -1;
}
//読んだデータの最後にふたする
buff[dwRead] = '\0';
return 0;
}
int SendData(char *buff, int maxlen)
{
char *com;
com = (char *)malloc(maxlen);
sprintf(com, "%s", buff);
WriteData(buff,strlen(buff));
ReadData(buff,maxlen);
//printf("%s\n",buff);
if (strcmp(buff,"R\r")){
fprintf(stderr, "Com=%s\nRes=%s\n", com, buff);
return -1;
}
free(com);
return 0;
}
void FGInit()
{
char buff[16];
sprintf(buff, "N\r");//単位をNに設定
SendData(buff,16);
Sleep(WAITTIME);
sprintf(buff, "T\r");//トラックモード(ピークホールドモードにしない)
SendData(buff,16);
Sleep(WAITTIME);
sprintf(buff, "I\r");//メモリクリア
SendData(buff,16);
Sleep(WAITTIME);
sprintf(buff, "Z\r");//ゼロリセット
SendData(buff,16);
Sleep(WAITTIME);
fprintf(stderr, "Force Gauge Init finish\n");
}
void ReadMemoryData(char *data)
{
char buff[1024];
//メモリデータ全読み出し
fprintf(stderr, "\nデータ吸出し中...");
sprintf(buff, "R\r");
WriteData(buff,strlen(buff));
//dataの中身をフォーマットする
ReadData(buff,1024);
sprintf(data, "%s", buff);
//データがある限り読み出しまくる。通信が間に合わないので、たくさんスリープしてます。
while (1) {
//Sleep(WAITTIME);
ReadData(buff,1024);
sprintf(data, "%s%s", data, buff);
//Sleep(WAITTIME);
if(!rs_check()) break;
}
/*
sprintf(buff, "I\r");
SendData(buff,16);
fprintf(stderr, "バッファクリアしました\n");
*/
}
int Measure(DWORD *time)
{
char buff[128];//送受信バッファ 使いまわし
int n=0;
DWORD start, end;
fprintf(stderr, "Press any key to exit:\n");
start = GetTickCount();
while (!kbhit()){ //無限ループ キーボード叩いたら抜ける
if( n > 256 ) break; //FGのメモリを超えたら強制break 256件しか記録できない仕様
sprintf(buff, "W\r");
if ( SendData(buff,128) ) break;
end = GetTickCount();
fprintf(stderr, "%d %d\t %s", n, end - start, buff);
time[n] = end - start;
n++;
}
return (n-1);
}
void savedata(char *data, DWORD *time, int num)
{
FILE *fp;
double force[256];
int i, j;
char tmp[16], *e;
fprintf(stderr, "セーブします\n");
//+000.8NM\r+002.8NM\r こんなフォーマットでdataに入ってる
for (i=0; i < num; i++){
for (j=0; j<8; j++){
tmp[j] = data[9*i+j];
}
tmp[7] = '\0';
force[i] = strtod(tmp, &e);
//printf("%d, %s, %f, %d, %s\n", i, tmp, force[i], time[i+1], e);
}
//このへんでセーブする
if ( (fp = fopen("forcegauge.log","w") ) == NULL ){
fprintf(stderr, "file open error, forcegauge.log \n");
exit(-1);
}
for (i=0; i<num; i++){ //最大値まで行ったら終了
fprintf(fp, "%d,%f\n", time[i], force[i]);
}
fclose(fp);
}
int main(int argc, char* argv[])
{
char data[1024*9];//9文字1024行までOK 実際は256行なんで余裕あり
DWORD time[256];
int num;
ComInit();
//FGInit();
num = Measure(time);
ReadMemoryData(data);
ComEnd();
savedata(data, time, num);
fprintf(stderr, "press 'q' to exit\r");
while (1){
if( kbhit() ){
if( getch()=='q' ) break;
}
}
return 0;
}
/*
以下マニュアルより抜粋
=============
コマンド、ステイタスはすべて大文字
CRコードが最後につく
フォースゲージはLF無視する
コマンド成功=R[CR]
エラー=E[CR]
返答を確認してから再送信
ステイタスが返ってくる前にコマンドを送るとどうなるかわからん
W メモリへの測定値の取り込み
R メモリ内容の読み出し
I メモリクリア
D 表示データの送信
Z ゼロリセット
N 単位をニュートンに
K 単位をキログラムに
L 単位をポンドに
T トラックモード(対義語:ピークホールドモード)
P ピークホールドモード:最大値のみを常に表示
返答はcharで返ってくる
必要ならばatoiなどで変換
*/