• 締切済み

ADボードのデータの遅れについて

ADボードからデータを取得し、ファイルに書き出す下記のようなプログラムを作成中です。 データがNUMを境に遅れているという現象が発生しております。 #define NUM 20000 void CAdDrawGraphDlg::OnFileout() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください int nRet; int i = 0, j = 0; HANDLE hDeviceHandle; ADSMPLREQ SmplConfig; ADBOARDSPEC BoardSpec; WORD wSmplData[NUM]; FILE *fp = NULL; ULONG ulSmplNum = NUM; if((fp = fopen("DATA.csv", "w")) == NULL){ /* error */ return; } //setbuf(fp, NULL); /* デバイスのオープン */ if((hDeviceHandle = AdOpen("FBIAD1")) == INVALID_HANDLE_VALUE){ AfxMessageBox("デバイスのオープンに失敗しました",MB_OK, 0); return; } nRet = AdGetSamplingConfig(hDeviceHandle,&SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング設定情報の読み出しに失敗しました",MB_OK, 0); } nRet = AdGetDeviceInfo(hDeviceHandle, &BoardSpec); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("デバイスの情報取得にに失敗しました", MB_OK, 0); } /* config初期化 */ SmplConfig.SmplChReq[0].ulChNo = 2; SmplConfig.ulSmplNum = NUM; //SmplConfig.ulTrigMode = AD_ETERNITY; SmplConfig.fSmplFreq = 20000; SmplConfig.SmplChReq[0].ulRange = AD_5V; nRet = AdSetSamplingConfig(hDeviceHandle, &SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング条件設定に失敗しました",MB_OK, 0); } nRet = AdStartSampling(hDeviceHandle, FLAG_SYNC); //for(;;i++){ /* 無限ループ */ for(i = 0; i < 4; i++){ /* NUM回データを取得 */ for(j = 0; j < NUM; j++){ double val; AdGetSamplingData(hDeviceHandle, &wSmplData[j], &ulSmplNum); val = wSmplData[j]; val = ((val * 10) / 4096) - 5; fprintf(fp, "%d, %f\n", i * NUM + j, val); } if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSVファイル作成に失敗しました", MB_OK, 0); } } /* デバイスのクローズ */ nRet = AdClose(hDeviceHandle); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("デバイスのクローズに失敗しました"); } fclose(fp); } このロジックで出力されたcsvをグラフ化すると添付画像のようなグラフになってしまいます。 データの遅れは何が原因でしょうか?  ご教授よろしくお願いいたします。

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

AdGetSamplingDataの使い方を間違っていて、2回目の実行以降はまともに読めてないのではないか、と。 2回目以降が遅れているのではなく、1回目の値を繰り返し表示しているだけではないか、と。 まずは、ulSmplNumの値を「毎回」確認してみてください。

masasugi0518
質問者

お礼

ありがとうございました。 おかげで解決できました。 丁寧な回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ADボードでリアルタイムサンプリング

    プログラムはこちらです #define NUM 20000 void CAdDrawGraphDlg::OnFileout() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください int nRet; int i = 0, j = 0, file_count = 0; char fname[32]; HANDLE hDeviceHandle; ADSMPLREQ SmplConfig; ADBOARDSPEC BoardSpec; WORD wSmplData; FILE *fp = NULL; ULONG ulSmplNum = NUM; /* デバイスのオープン */ if((hDeviceHandle = AdOpen("FBIAD1")) == INVALID_HANDLE_VALUE){ AfxMessageBox("デバイスのオープンに失敗しました",MB_OK, 0); return; } nRet = AdGetSamplingConfig(hDeviceHandle,&SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング設定情報の読み出しに失敗しました",MB_OK, 0); } nRet = AdGetDeviceInfo(hDeviceHandle, &BoardSpec); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("デバイスの情報取得にに失敗しました", MB_OK, 0); } while(1){ /* 無限ループ */ /*時間の取得*/ int H,M,S; /* config初期化 */ SmplConfig.SmplChReq[0].ulChNo = 2; // SmplConfig.ulSmplNum = NUM * i; //SmplConfig.ulTrigMode = AD_ETERNITY; SmplConfig.fSmplFreq = 20000; SmplConfig.SmplChReq[0].ulRange = AD_5V; nRet = AdSetSamplingConfig(hDeviceHandle, &SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング条件設定に失敗しました",MB_OK, 0); } nRet = AdStartSampling(hDeviceHandle, FLAG_SYNC); /* 書き込みファイルのオープン */ sprintf(fname, "DATA.%d.csv", file_count); fp = NULL; if((fp = fopen(fname, "w")) == NULL){ /* error */ return; } setbuf(fp, NULL); /* ライブラリ内バッファリングを無効にする */ for(i = 0;; i++){ SmplConfig.ulSmplNum = NUM * i; wSmplData = 0; /* NUM回データを取得 */ for(j = 0; j < NUM; j++){ ulSmplNum = 1; double val; if(AdGetSamplingData(hDeviceHandle, &wSmplData, &ulSmplNum) != AD_ERROR_SUCCESS){ val = wSmplData; val = ((val * 10) / 4096) - 5; fprintf(fp, "%d, %f\n", i * NUM + j, val); //fprintf(fp, "[%d], %d, %d\n", ulSmplNum, i * NUM + j, wSmplData); } else{ val = wSmplData; val = ((val * 10) / 4096) - 5; CTime theTime=CTime::GetCurrentTime(); // mm=theTime.GetMonth(); // dd=theTime.GetDay(); H =theTime.GetHour(); M =theTime.GetMinute(); S =theTime.GetSecond(); fprintf(fp, "%d,%d:%d:%d, %f\n", i * NUM + j,H,M,S, val); //fprintf(fp, "%d, %d, %d\n", ulSmplNum, i * NUM + j, wSmplData); } } if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSVファイル作成に失敗しました", MB_OK, 0); } } /* end of for */ fclose(fp); file_count++; } /* end of while */ /* デバイスのクローズ */ nRet = AdClose(hDeviceHandle); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("デバイスのクローズに失敗しました"); } fclose(fp); } 問題は20000点で1秒時刻が進むはずですが2000点で1秒時計が進んでしまいます。 時刻以外は正常で、1周期1sの波形を入力したときはそのしっかり20000点存在するので1秒間に 20000点でサンプリングしています。 解決策があれば教えてください。

  • ADボードにとるCSVでの無限サンプリング

    ADボードで無限サンプリングをおこないたいのですが。 作成したCSVファイルにデータが1行しか作成されません。 何が問題でしょうか? ちなみにプログラムはこちらです。 int nRet; HANDLE hDeviceHandle; ADSMPLREQ SmplConfig; ADBOARDSPEC BoardSpec; ULONG ulSmplNum; FILE *outp; WORD wSmplData[20000][2]; hDeviceHandle = AdOpen ("FBIAD1"); if (hDeviceHandle == INVALID_HANDLE_VALUE){ AfxMessageBox("デバイスのオープンに失敗しました",MB_OK, 0); return; } else{ nRet = AdGetSamplingConfig(hDeviceHandle,&SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング設定情報の読み出しに失敗しました",MB_OK, 0); } nRet = AdGetDeviceInfo(hDeviceHandle, &BoardSpec ); if(nRet !=AD_ERROR_SUCCESS){ AfxMessageBox("デバイスの情報取得にに失敗しました", MB_OK, 0); } { SmplConfig.SmplChReq[0]. ulChNo = 2; SmplConfig.ulSmplNum = 20000; SmplConfig.ulTrigMode = AD_ETERNITY; SmplConfig.fSmplFreq = 20000; SmplConfig.SmplChReq[0]. ulRange = AD_5V; nRet = AdSetSamplingConfig(hDeviceHandle,&SmplConfig ); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング条件設定に失敗しました",MB_OK, 0); } /* nRet = AdStartSampling(hDeviceHandle, FLAG_SYNC); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSVファイル作成に失敗しました", MB_OK, 0); }*/ /* nRet = AdStartFileSampling( hDeviceHandle, "DATA.CSV", FLAG_CSV ); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSV ファイル作成に失敗しました", MB_OK, 0); }*/ AdGetSamplingData(hDeviceHandle,&wSmplData[0][0], &ulSmplNum ); AdOutputDO(hDeviceHandle,1); outp = fopen("E:\\Edata\\record.csv","a"); fprintf(outp,"%f\n",wSmplData[0][0]); fclose(outp); // 終了処理. nRet = AdClose( hDeviceHandle ); if (nRet != AD_ERROR_SUCCESS) { AfxMessageBox("デバイスのクローズに失敗しました"); } } } }

  • ADボードのプログラムでの無限サンプリング

    自分でプログラムをADsamplingData関数でやってみたのですがデータが指定の保存場所に出力されません。 CSV形式で保存するプログラムを作ったつもりです。 保存場所はEドライブのEdataの中に出力されるようにしたいです。 ちなみにプログラムはこちらです。 int nRet; HANDLE hDeviceHandle; ADSMPLREQ SmplConfig; ADBOARDSPEC BoardSpec; ULONG ulSmplNum; FILE *outp; WORD wSmplData[20000][2]; hDeviceHandle = AdOpen ("FBIAD1"); if (hDeviceHandle == INVALID_HANDLE_VALUE){ AfxMessageBox("デバイスのオープンに失敗しました",MB_OK, 0); return; } else{ nRet = AdGetSamplingConfig(hDeviceHandle,&SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング設定情報の読み出しに失敗しました",MB_OK, 0); } nRet = AdGetDeviceInfo(hDeviceHandle, &BoardSpec ); if(nRet !=AD_ERROR_SUCCESS){ AfxMessageBox("デバイスの情報取得にに失敗しました", MB_OK, 0); } { SmplConfig.SmplChReq[0]. ulChNo = 2; SmplConfig.ulSmplNum = 20000; SmplConfig.ulTrigMode = AD_ETERNITY; SmplConfig.fSmplFreq = 20000; SmplConfig.SmplChReq[0]. ulRange = AD_5V; nRet = AdSetSamplingConfig(hDeviceHandle,&SmplConfig ); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング条件設定に失敗しました",MB_OK, 0); } nRet = AdStartSampling(hDeviceHandle, FLAG_SYNC); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSVファイル作成に失敗しました", MB_OK, 0); } AdGetSamplingData(hDeviceHandle,&wSmplData[0][0], &ulSmplNum ); outp = fopen("E\\Edata\\record.csv","a"); fprintf(outp,"%f\n",wSmplData); fclose(outp); } } } 何が違うのですか? dビルドはできるのですが、プログラムを動かしてもファイルができません。

  • なんらかの原因でtxtにデータを入力できない

    こんにちは。 C言語初心者です。 まずこのようなデータを用意しました。 kus1.txt 89 65 37 44 51 30 20 10 そして、このようなプログラムをし、ビルトしました。 #include <stdio.h> #define NUM 8 int main(void) { FILE *fp; int kusa[NUM]; int max,min; int i,k; fp = fopen("kus1.txt","r"); if(fp == NULL){ printf("ファイルオープン失敗\n"); return 1; } for(i=0; i<NUM; i++){ fscanf(fp, "%d", &kusa[i]); } max = kusa[0]; min = kusa[0]; for(k=0; k<NUM; k++){ if(max < kusa[k]) max = kusa[k]; if(min > kusa[k]) min = kusa[k]; printf("NO.%-5d%d\n", k+1, kusa[k]); } printf("最高は%d。\n", max); printf("最低は%d。\n", min); fclose(fp); return 0; } その後、コマンドプロンプトでこれを実行したところ、 ファイルオープン失敗 とでてきました。つまりなんらかの原因で失敗しました。 どうしたら成功できるのでしょうか。教えてください。

  • テキストファイルからデータを読み込みモータを動かす

    理系の研究室にいます.現在VisualC++6.0でモータを動かすことにより台をある速度で動かす機械を使っています. テキストファイルに 1 1.2 1.3 と書いてあり,それを読み込んでボタンをクリックしたら モータを動かし,1秒ごとにテキストファイルに書いてる速度に 変化させていくというものです.(1秒 1mm/s 2秒 1.2mm/s) 初心者で,前研究者が作ったものを参考にしたり, 本を見て作りました. 以下がC++言語です. void CSyncStartDlg::OnDielessstart() { INT nRet; int main(void) { fstream finout; //入出力用ストリームの宣言 char ss[1000]; finout.open("data.txt", ios::in); //ファイルオープン if(finout.fail()){ cout << "入力ファイルをオープンできません\n"; exit (1); } while(!finout.eof() && !finout.fail()) //データの入力 { finout.getline( ss,1000 ); nRet=MtrChangeSpeed(hDeviceHandle1,MTR_ACCDEC_CHANGE,(ss*360*9)/(0.04394531*5)); //関数の実行結果 if(nRet != MTR_ERROR_SUCCESS) AfxMessageBox("速度変更に失敗しました"); Sleep(1000); } finout.close(); DeviceHandle1はモータの1軸ということです. エラーは:mainのローカル関数の定義がおかしい fatal errorと出ます. 初心者で何がおかしいかわかりません. もしよければ添削していただけると幸いです. よろしくお願いします.

  • C言語の配列の入れ方について質問です。

    下記のプログラムで1234という連続した数字を入れたら配列val[0]~[3]に val[0] = 1 val[1] = 2 val[2] = 3 val[3] = 4 というように入れたいのですが、どのようにして別々にすれば良いですか?宜しくお願いします。 #include<stdio.h> int main(void) { int num[10]; int val[4]; int i; printf("式:"); scanf("%d",num); for(i=0;i<4;i++){ val[i] = 0; } for(i=0; i<4; i++){ if((num[i] >= 1) && (num[i] <= 9)){ /*1から9の数値が入ったならば*/ val[i] = num[i]; } } for(i=0; i<4; i++){ printf("答え%d:%d\n",i,val[i]); } }

  • NTPサーバから時刻を取得する

    VC++にてNTPサーバから時刻を取得するためにNetRemoteTODを用いていますが、以下の方法ではコンパイルはできるのですが、プログラム実行時にサーバにつながらなくエラーとなります。サーバの指定方法がまずい気もするのですが、どのように修正すればよいのかご教授よろしくお願いします。 LPTIME_OF_DAY_INFO pBuf = NULL; NET_API_STATUS nStatus = NetRemoteTOD(L"\\\\ntp.jst.mfeed.ad.jp", (LPBYTE *)&pBuf); if(nStatus == NERR_Success){ if(pBuf != NULL){ char d[1024]; sprintf(d, "%d/%d/%d %d:%d:%d", pBuf->tod_month, pBuf->tod_day, pBuf->tod_year, pBuf->tod_hours, pBuf->tod_mins, pBuf->tod_secs); AfxMessageBox(d,MB_OK|MB_ICONSTOP); } } else{ AfxMessageBox("Error in NetRemoteTOD",MB_OK|MB_ICONSTOP); } if (pBuf != NULL) NetApiBufferFree(pBuf);

  • C言語のqsortについて

    現在、qsortのコードに取り組んでいます。 if (strcmp(ad, "ASC") == 0) { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_u); } else { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_d); } 恐らくこちらのqsortでの第二引数が書き方を間違えていると思うのですが、修正の方法が分からず、どなたか教えて頂けないでしょうか? #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> static char ad[10]; int cmp_u(const void* a, const void* d) { return strcmp((char*)a, (char*)d); } int cmp_d(const void* a, const void* d) { return strcmp((char*)d, (char*)a); } int main() { int num1, num2; char op; float answer; int r,i; FILE* fp; char c[11]; char sin[1000][1000]; char ad[8]; fp = fopen("log.txt", "a+"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (1) { r = scanf("%d%c%d", &num1, &op, &num2); if (r != 3) { puts("input error"); return 1; } if (op == '+') { answer = num1 + num2; } else if (op == '-') { answer = num1 - num2; } else if (op == '*') { answer = num1 * num2; } else if (op == '/') { answer = (float)num1 / num2; } time_t t = time(NULL); struct tm* tm = localtime(&t); printf("%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); printf("%d%c%d,%f\n", num1, op, num2, answer); fprintf(fp, "%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer); printf("計算を続けますか?"); scanf("%s\n", &c); if (strcmp(c, "no") == 0) { break ; } } fclose(fp); fp = fopen("log.txt", "r"); int cnt = 0; for (i = 0;i < 1000;i = i + 1) { if (fgets(sin[i], sizeof(sin[0]), fp)) ++cnt; else break; } fclose(fp); printf("ASC or DESC: "); scanf("%s", ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_u); } else { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_d); } for (i = 0;i < cnt;i = i + 1) { printf("%s", sin[i]); } return 0; }

  • 大規模データの処理について困っています

    掲題の通り、大規模データの処理で悩んでおります。 行ベクトル150万、列ベクトル14のCSVファイルを読み込もうとしているのですが、データ数が10万以上になるとVisual C++が勝手に動作を停止してしまいプログラムを実行することができません。 具体的には、CSVファイル上の4列目に記載されている都道府県名のデータを配列で取り、画面に表示しようと、次のようなプログラムを書いているのですが、 #include<stdio.h> #include<string.h> #include<stdlib.h> #define FNAME "data.csv" #define NUM 10000 int main(void) { FILE *fp; char buf[256]; char *p_token; char dat[14][100]; int n; int i; long int j; char *place[NUM][15]; place[NUM][15]=(char*)malloc(sizeof(char)*NUM); fp = fopen(FNAME,"r"); if (fp == NULL) { printf("ファイルをオープンできませんでした\n"); return 0; } for(j=0;j<=NUM;j++){ fgets(buf,256,fp) !=NULL; p_token = strtok(buf, ","); strcpy(dat[0],p_token); n=1; while(-1) { p_token = strtok(NULL,","); if(p_token == NULL) { break; } strcpy(dat[n],p_token); n++; } if(j!=0) { place[j-1][10]=dat[3]; printf("%s \n",place[j-1][10]); } } fclose(fp); free(place[NUM][15]); return 0; } NUMの数を10万以上にすると、実行してもプログラムが勝手に停止してしまいます。書籍もネットも大分読み漁ったのですが、処置がまったくわからず途方にくれています。 どなたかこうした処理に詳しい方、アドバイスをいただけないでしょうか。よろしくお願い申し上げます。 追記:(1)都道府県名を二次元配列で取っているのは、都道府県名が「大阪府」などと、CSVファイル上で日本語で記載されているからです。 (2)プログラムを実行する際にデータ数を10万以上にすると、CSVファイルをフォルダ内においていなくてもプログラムが停止します(ただしコンパイルエラーはでません)。つまり、メモリの確保に問題があるということになるのでしょうか?

  • C言語の、戻り値/値渡し/アドレス渡しのついて

    【実装したコードに、戻り値/値渡し/アドレス渡しを用いたサブの関数を作成せよ。】 上記の課題に取り組んでいるのですが、何となく概念は分かったのですが、ソースコードに反映させようとすると詰まってしまって… どなたか教えて頂けないでしょうか? 『ソースコード』 #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> #define CALC (3) #define FROM_YEAR (1900) #define MAX_LINE (1000) int cmp_u(const void* a, const void* d) { return strcmp((char*)a, (char*)d); } int cmp_d(const void* a, const void* d) { return strcmp((char*)d, (char*)a); } int main() { int num1, num2; char op; float answer; int r,i; FILE* fp; char e[11]; char sin[1000][1000]; char ad[8]; fp = fopen("log.txt", "a+"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (1) { r = scanf("%d%c%d", &num1,&op, &num2); if (r != CALC) { puts("input error"); return 1; } if (op == '+') { answer = num1 + num2; } else if (op == '-') { answer = num1 - num2; } else if (op == '*') { answer = num1 * num2; } else if (op == '/') { answer = (float)num1 / num2; } time_t t = time(NULL); struct tm* tm = localtime(&t); printf("%d/%02d/%02d ", tm->tm_year + FROM_YEAR, tm->tm_mon + 1, tm->tm_mday); printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); printf("%d%c%d,%f\n", num1, op, num2, answer); fprintf(fp, "%d/%02d/%02d ", tm->tm_year + FROM_YEAR, tm->tm_mon + 1, tm->tm_mday); fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer); printf("計算を続けますか?"); scanf("%s", e); if (strcmp(e, "no") == 0) { break ; } } fclose(fp); fp = fopen("log.txt", "r"); int cnt = 0; for (i = 0;i < MAX_LINE;i = i + 1) { if (fgets(sin[i], sizeof(sin[0]), fp)) ++cnt; else break; } fclose(fp); printf("ASC or DESC: "); scanf("%s", ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, cnt, sizeof(sin[0]), cmp_u); } else { qsort(sin, cnt, sizeof(sin[0]), cmp_d); } for (i = 0;i < cnt;i = i + 1) { printf("%s", sin[i]); } return 0; }