WaveForms SDKをVCLプログラムから使う

別にFMXからでもおけです

さて、いよいよ本題です。まずフォームは、

こんな感じです。TLabelx1,TButtonx1,TMemox1を上図のように配置。忘れずにMemo1には垂直スクロールをセットしておきましょう。

さて、プロジェクトの構成は、

こんな感じですかね。32bit版なので、cbbdwf.libを組み込みます。前記事参照のこと。

Unit.cppは、

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "sample.h"

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

HDWF ghdwf;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	  int cDevice;
	int cChannel;
	double hzFreq;
	char szDeviceName[32];
	char szSN[32];
	int fIsInUse;
	//HDWF hdwf;
	char szError[512];
	AnsiString output;

	// detect connected all supported devices
	if(!FDwfEnum(enumfilterAll, &cDevice)){
		FDwfGetLastErrorMsg(szError);
		printf("FDwfEnum: %s\n", szError);
		output.sprintf("FDwfEnum: %s\n", szError);
		Memo1->Lines->Add(output);
		return;
	}
	// list information about each device
	printf("Found %d devices:\n", cDevice);
	for(int i = 0; i < cDevice; i++){
		// we use 0 based indexing
		FDwfEnumDeviceName (i, szDeviceName);
		FDwfEnumSN(i, szSN);
		printf("\nDevice: %d name: %s %s\n", i+1, szDeviceName, szSN);
		output.sprintf("\nDevice: %d name: %s %s\n", i+1, szDeviceName, szSN);
		//Memo1->Lines->Add(output);
		Label1->Caption = output;
		// before opening, check if the device isn稚 already opened by other application, like: WaveForms
		FDwfEnumDeviceIsOpened(i, &fIsInUse);
		if(!fIsInUse){
			if(!FDwfDeviceOpen(i, &ghdwf)){
				FDwfGetLastErrorMsg(szError);
				printf("FDwfDeviceOpen: %s\n", szError);
				continue;
			}
			FDwfAnalogInChannelCount(ghdwf, &cChannel);
			FDwfAnalogInFrequencyInfo(ghdwf, NULL, &hzFreq);
			printf("number of analog input channels: %d maximum freq.: %.0f Hz\n", cChannel, hzFreq);
			output.sprintf("number of analog input channels: %d maximum freq.: %.0f Hz\n", cChannel, hzFreq);
			//Memo1->Lines->Add(output);
			//FDwfDeviceClose(ghdwf);
			//ghdwf = hdwfNone;
		}
	}
	Memo1->Lines->Clear();

	// before application exit make sure to close all opened devices by this process
	//FDwfDeviceCloseAll();

}
//---------------------------------------------------------------------------
void __fastcall TForm1::DataClick(TObject *Sender)
{
	//HDWF hdwf;
	char szError[512] = {0};
	DwfState sts;
	const int nSamples = 1000;
	double* rgdSamples = new double[nSamples];
	AnsiString output;

// did in constructor
/*
	printf("Open automatically the first available device\n");
	if(!FDwfDeviceOpen(-1, &hdwf)) {
		FDwfGetLastErrorMsg(szError);
		printf("Device open failed\n\t%s", szError);
		return;
	}
*/
	printf("Configure and start first analog out channel\n");
	FDwfAnalogOutEnableSet(ghdwf, 0, true);
	// 1 = Sine wave
	FDwfAnalogOutFunctionSet(ghdwf, 0, 1);
	FDwfAnalogOutFrequencySet(ghdwf, 0, 3000);
	FDwfAnalogOutConfigure(ghdwf, 0, 1);

	printf("Configure analog in\n");
	FDwfAnalogInFrequencySet(ghdwf, 1000000);
	// set range for all channels
	FDwfAnalogInChannelRangeSet(ghdwf, -1, 4);
	FDwfAnalogInBufferSizeSet(ghdwf, nSamples);

	printf("Wait after first device opening the analog in offset to stabilize\n");
	Wait(2);

	printf("Starting acquisition\n");
	FDwfAnalogInConfigure(ghdwf, true, true);

	printf("Waiting to finish... ");
	while(true){
		FDwfAnalogInStatus(ghdwf, true, &sts);
		if(sts == DwfStateDone){
			break;
		}
		Wait(0.1);
	}
	printf("done\n");
	Memo1->Lines->Add("done");
	printf("Reading acquisition data\n");
	FDwfAnalogInStatusData(ghdwf, 0, rgdSamples, nSamples);
	// do something with the data in rgdSample
	for( int i = 0 ; i < nSamples ; i++ ){
		 output.sprintf("%d,%g",i,rgdSamples[i]);
		 Memo1->Lines->Add(output);

	}


}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
	FDwfDeviceCloseAll();
}
//---------------------------------------------------------------------------

built and run してみましょう。F9ですね。

コンストラクタ内でAD2を認識し、SNを表示しています。公開しちゃってますが、大丈夫でしょう。ここで”Data”ボタンをクリックすると、

値の最初の方がスクロールアウトしていますけど、バッファにはのこっているのでそれを書き出してみましょう。Memo1のどこかにポインタを置いて、右クリックからの

ここで”すべて選択”をクリック。テキストファイルにペーストして、*.csvとかの適当な名前でセーブして、それをExcelから開くと、

データ列を選択して、散布図を描くと、

振幅と周波数は良いですね。初期位相はランダムです。これを一定かするにはTriggerの設定をしなくてはならないです。

Memo1の内容を全て選択してコピーしてからテキストファイルにペーストしてセーブというのはいかにも回りくどいので、

TMemoの内容をファイルセーブ

とかで検索してみると。Copilot君がしゃしゃり出てくるかもしれません。不発だったので、聞き方を変えました。

TMemo ファイル 保存 C++ Builder

なにやら言ってきましたよ。

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <System.SysUtils.hpp> // ExtractFilePath など
#include <Vcl.Dialogs.hpp>     // TSaveDialog

#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}

// 「保存」ボタンのクリックイベント
void __fastcall TForm1::ButtonSaveClick(TObject *Sender)
{
    // 保存ダイアログを表示
    if (SaveDialog1->Execute())
    {
        try
        {
            // TMemo の内容をファイルに保存
            Memo1->Lines->SaveToFile(SaveDialog1->FileName, TEncoding::UTF8);
            ShowMessage(L"保存しました: " + SaveDialog1->FileName);
        }
        catch (const Exception &e)
        {
            ShowMessage(L"保存に失敗しました: " + e.Message);
        }
    }
}

ダイアログまで付いてますね。

// TMemo の内容をファイルに保存
            Memo1->Lines->SaveToFile(SaveDialog1->FileName, TEncoding::UTF8);

が肝ですね。

コメント