アプリケーションノート:プログラマブルフレームグラバー向けの信号処理アプレットの設計#
VisualAppletsにおけるGPI/GPOオペレーター#
VisualAppletsを使用すると、アプリケーション固有の独自のトリガーシステムを設計できます。たとえば、どの物理入出力ピンによってどの信号が送信または受信されるかを決定できます。
VisualAppletsでは、任意個別のピンをアプレット設計に配線するために、以下の2つのオペレーターを使用できます。
オペレーター GPI(トリガーIN信号用)
オペレーター GPO(トリガーOUT信号用)

上図は、信号処理を実装する方法の例を示しています。実装する信号処理機能は、お客様の特定の要件によって異なります。アプリケーションに適したオペレーターを見つけるには、Signal Libraryをご覧ください。また、要件に応じてFront GPIOを選択してください。
上の例は、2つの入力信号に対するダンスケーリング機能を示しています。GPI1およびFront GPI0から2つの信号がプログラマブルフレームグラバーに入力されます。信号はまずデバウンス処理され、立ち上がりエッジまたは立ち下がりエッジが選択され、その後8または3の係数でダウンスケーリングされます。両方の信号の信号長が設定された後、信号はFrontGPO0、GPO1、GPO2およびカメラに転送され、画像取得を制御します。
GPI/GPOオペレーターの使用#
Front GPIOまたはTrigger Extension Boardで使用する各トリガーIN / トリガーOUTピンは、GPI / GPOオペレーターのインスタンスに相互接続する必要があります。
情報
オペレーター GPIとオペレーター GPOは同じ機能を持つため、以下では両方のオペレーターをまとめて説明します。
- デザイン内のオペレーターアイコンをダブルクリックして、Module Propertiesウィンドウを開きます。

Module Propertiesウィンドウが開きます。

ご覧のとおり、オペレーターには2つのパラメータがあります。
Pin_ID: パラメータ Pin_IDを使用すると、選択したコネクタ上でアドレス指定する個別ピンを定義できます。ConnectorType: パラメータ ConnectorTypeを使用すると、アドレス指定するコネクタ(Front GPIOまたはGPIO経由のTrigger Extension Board)を定義できます。
情報
CXP-12フレームグラバーの場合、 ConnectorType パラメータは、 Pin_ID パラメータ。
Parameter Connector Type#
に含まれています。このパラメータを使用すると、15ピンD-Subソケット(Front GPIO)で提供されるもの、またはTrigger Extension Board(GPIO)で提供されるもののうち、アドレス指定するトリガーピングループを定義できます。パラメータの値の範囲は {Front GPIO, GPIO} です。
値 Front GPIO#
値 Front GPIOを選択すると、プログラマブルフレームグラバーのスロットブラケットにある次のコネクタ(トリガーピングループ)がアドレス指定されます。

値 GPIO#
値 GPIOを選択すると、プログラマブルフレームグラバー上の次のトリガーピングループがアドレス指定されます。

GPIOは、Trigger Extension Boardへの接続に使用されます。

パラメーター Pin_ID#
このパラメータを使用すると、選択したコネクタ(トリガーピングループ)上でアドレス指定する個別ピンを定義できます。パラメータの値の範囲 Pin_ID is {0;7} or {0;3} for connector type GPIO または Front GPIO.
情報
パラメータの値範囲 Pin_ID for marathon frame grabbers and operator GPO is {0;1}.
VisualAppletsオペレーターリファレンスによるフロントGPIOのピン構成#


差動モードでは、ピン9を使用してPin_ID=3のGPIオペレータでシングルエンド信号を1つ受信できます。モード「Differential」(デフォルト)を参照してください。
注意
フレームグラバーのトリガーシステムには、Voltage INピンへの電源供給が必要です。PWRピンを持たないデバイスを接続する場合は、外部ソースからVoltage INピンに電源を供給する必要があります。
フロントGPIOでのTrigger INPUT#
次の場合:
- 使用している
GPIオペレータ(トリガー入力信号の定義用)、 - 設定したパラメータ
Connector TypeをFront GPIO,
パラメータの値 Pin_ID 次のピンに対処します:

フロントGPIOの入力(GPI)ピンは設定可能です。6つの入力ピンを使用して、次のいずれかを受信できます:
- 3つの差動信号、または
- 2つの差動信号と1つのシングルエンド信号、または
- 4つのシングルエンド信号。
特定の信号タイプ(差動またはシングルエンド)に対してフロントGPIOの入力ピンを設定するには、2つのモードを利用できます:
- モード
Differential(オプションaおよびbを提供) - モード
Single-ended(オプションcを提供)
フロントGPIOのデフォルトモードは、次のモードです: Differentialモードの切り替え方法については、次のトピックを参照してください。 入力構成 フレームグラバーのマニュアル。
注意
デフォルト設定では、フロントGPIOのGPIOピンは以下を提供します:
- 3つの差動入力信号、またはプルアップモードでの2つの差動および1つのシングルエンド入力信号
- 2つのTTL出力信号
入力信号の別の設定が必要な場合、つまり:
- プルダウンモード、
- 4つのシングルエンド信号(差動信号なし)、
用途に合わせてGPIを簡単に設定できます。設定には、Framegrabber SDKと一緒にシステムにインストールされたコマンドラインツールを使用します。
モード Differential (デフォルト)#
モード Differential (デフォルト)では、Front GPIOの6つの入力ピンすべてが差動信号を受信するように設定されます。
- ピン8/9 -> 1差動信号
- ピン11/12 -> 1差動信号
- ピン13/14 -> 1差動信号
または、ピンペア8/9(モード Differential)を使用して1つのシングルエンド信号を受信することもできます。
- ピン9 -> 1シングルエンド信号
- ピン11/12 -> 1差動信号
- ピン13/14 -> 1差動信号
モードでの個別ピン Differential:

ピン11および12:
- ピン11および12に入力された信号は、1つの差動信号として解釈されます(ピン11が+、ピン12が-の値)。
- VisualApplets内でこの差動信号を受信するには、Pin_ID = 0のGPIオペレーターインスタンスを使用します。
ピン13および14:
- ピン13および14に入力された信号は、1つの差動信号として解釈されます(ピン13が+、ピン14が-の値)。
- VisualApplets内でこの差動信号を受信するには、Pin_ID = 1のGPIオペレーターインスタンスを使用します。
ピン8および9:
- ピン8および9に入力された信号は、1つの差動信号として解釈されます(ピン8が+、ピン9が-の値)。
- VisualApplets内でこの差動信号を受信するには、Pin_ID = 2のGPIオペレーターインスタンスを使用します。
または、ピンペア8/9を使用して1つのシングルエンド信号を受信することもできます(モード Differentialの場合でも)。この場合、
- シングルエンドの入力信号を物理ピン9に接続します。
- VisualApplets内でこのシングルエンド信号を受信するには、Pin_ID = 3のGPIオペレーターインスタンスを使用します。
モード Single-Ended#
モード Single-ended (設定可能)では、Front GPIOの6つの入力ピンが4つのシングルエンド信号を受信するように設定されます。
- Pin 8 -> 1つのシングルエンド信号
- ピン9 -> 1シングルエンド信号
- Pin 11 -> 1つのシングルエンド信号
- Pin 13 -> 1つのシングルエンド信号
モードでの個別ピン Single-ended:

Pin 11およびPin 12の信号:
- Pin 11に入力された信号は、シングルエンド信号として解釈されます。
- VisualApplets内でこのシングルエンド信号を受信するには、Pin_ID = 0を設定したGPIオペレータインスタンスを使用します。
- Pin 12は、以下のモードでは使用されません:
Single-ended.
Pin 13およびPin 14の信号:
- Pin 13に入力された信号は、シングルエンド信号として解釈されます。
- VisualApplets内でこのシングルエンド信号を受信するには、Pin_ID = 1を設定したGPIオペレータインスタンスを使用します。
- Pin 14は、以下のモードでは使用されません:
Single-ended.
ピン8および9:
- Pin 8およびPin 9に入力された信号は、2つのシングルエンド信号として解釈されます。
-
VisualApplets内でこれらのシングルエンド信号を受信するには、以下を使用します:
- Pin 8用にPin_ID = 2を設定したGPIオペレータインスタンス、および
- Pin 9用にPin_ID = 3を設定したGPIオペレータインスタンス。
トリガーOUTPUT TTL フロントGPIO#
次の場合:
- トリガー出力信号を定義するためにGPOオペレータを使用します。
- パラメータ Connector TypeをFront GPIOに設定した場合、
パラメータ Pin_IDの値は、以下のピンを指定します:

これら2つのピンは、TTL信号(5 V)を送信します。
フロントGPIO上の出力TTL信号(5 V):

Trigger Extension Boardをアドレッシングするトリガー信号(GPIO経由)#
GPIOコネクタは、Trigger Extension Boardに接続するように設計された、プログラマブルフレームグラバーの物理的なトリガーインターフェースです:

GPIOコネクタ(すなわち各Trigger Extension Board)は、
- 8つのデジタル入力(IN 0 ~ 7)(8つのシングルエンド信号または4つの差動信号)を提供します。
- 8つのデジタル出力(OUT 0 ~ 7)
8つの入力にはインデックス0 ~ 7が割り当てられています。8つの出力にも同様に0 ~ 7のインデックスが割り当てられています。
ピンレイアウトの詳細については、拡張ボードの PIN Layout on SUB-D15 - TTL Trigger Board または PIN Layout Opto-Coupled Trigger 5 - Opto-Coupled Trigger 5 Board を参照してください。
Pin_ID TTL Trigger Extension Boardsでの割り当て#
ポート A#
| PIN番号 | Pin_ID VisualApplets 内 |
|---|---|
| 1 | 0 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | 0 |
| 12 | 1 |
| 13 | 2 |
| 14 | 3 |
| 15 | 0 |
ポート B#
| PIN番号 | Pin_ID VisualApplets 内(シングルエンド信号) |
|---|---|
| 1 | 4 |
| 2 | 5 |
| 3 | 6 |
| 4 | 7 |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | 4 |
| 12 | 5 |
| 13 | 6 |
| 14 | 7 |
| 15 |
Pin_ID Opto Trigger 5 Extension Boardsでの割り当て#
ポート A#
| PIN番号 | Pin_ID VisualApplets 内(シングルエンド信号) | Pin_ID VisualApplets 内(差動信号) |
|---|---|---|
| 1 | 0 | |
| 2 | 1 | |
| 3 | 2 | |
| 4 | 3 | |
| 5 | ||
| 6 | ||
| 7 | ||
| 8 | ||
| 9 | ||
| 10 | ||
| 11 | 0 | 0 |
| 12 | 1 | 0 |
| 13 | 2 | 2 |
| 14 | 3 | 2 |
| 15 |
ポート B#
| PIN番号 | Pin_ID VisualApplets 内(シングルエンド信号) | Pin_ID VisualApplets 内(差動信号) |
|---|---|---|
| 1 | 4 | |
| 2 | 5 | |
| 3 | 6 | |
| 4 | 7 | |
| 5 | ||
| 6 | ||
| 7 | ||
| 8 | ||
| 9 | ||
| 10 | ||
| 11 | 4 | 4 |
| 12 | 5 | 4 |
| 13 | 6 | 6 |
| 14 | 7 | 6 |
| 15 |
トリガーシステムの構成#
トリガー設定には次の2つの方法でアクセスできます。
- microDisplay X:ここでは、GUIを介してトリガーパラメータ値を入力し、特定の設定の結果を確認できます。
- SDK:フレームグラバープログラミングインターフェイスを特定の画像処理ソフトウェアアプリケーションに実装するため。
トリガーシステムに対する要件は、アプリケーションによって異なります。
- エリアスキャンでは、1つのトリガータイプ(フレームトリガー)のみが必要です。
- ラインスキャンでは、ライントリガー(各ラインのトリガーパルスを送信)とフレームトリガーの2つのトリガータイプが必要です。ラインスキャンアプリケーションでは、フレームトリガーによって画像に追加されるライン数が制御されます。
エリアカメラおよびラインスキャンカメラのトリガー方法に関する詳細情報については、こちらをご覧ください。
情報
フレームグラバーのトリガーシステムの詳細については、GPIO Connectors のトピックを参照してください。
情報
利用可能なパラメータ(および特定の設定によって引き起こされる可能性のある影響)については、使用しているアプレットのマニュアルを参照してください。
ハードウェアでのアプレットの実行#
前提条件:
- プログラマブルフレームグラバーが、Connecting Frame Grabbers のトピックの説明に従ってシステムにインストールされていること。
- Basler Framegrabber SDK が、Installing the Framegrabber SDK の説明に従ってシステムにインストールされていること。
プログラマブルフレームグラバーでアプレットを実行する前に、次のファイルを *.hap ファイル(アプレット)をホストPC上のBasler Framegrabber SDKのインストール先へコピーし、プログラマブルフレームグラバーにフラッシュする必要があります。
情報
フラッシュが必要なのはmarathonフレームグラバーのみです。
VisualApplets デザインをハードウェアアプレットに変換する方法の詳細については、Hardware Applet: From Idea to Application を参照してください。
-
VisualAppletsでビルドした
*.hapファイルをディレクトリ[Framegrabber SDK installation directory]/Hardware Applets/[frame grabber model]にコピーします。プログラマブルフレームグラバーのモデル名のサブディレクトリが存在しない場合は、作成してください。VisualAppletsでデフォルト設定を使用している場合、*.hapファイルはVisualAppletsのインストールディレクトリのサブディレクトリであるDesigns. -
Flashing の説明に従って、プログラマブルフレームグラバーにアプレットをインストールします。
これが完了したら、次の操作を実行できます。
- Framegrabber SDK に付属している Basler ツール microDisplay X を使用して、アプレットをテストし、画像処理結果を直接確認できます。Configuring the Applet (microDisplay X) のトピックを参照してください。
例:信号処理サンプルデザインのハードウェアアプレットをmicroDisplay Xにロードすると、下の図に示すように、パラメータツリーでダウンスケーリングファクターや信号幅などの動的パラメータを設定できます。

独自ソフトウェアでのアプレットの起動#
独自ソフトウェアでのアプレットの使用を開始するには:
- Baslerのアプリケーションプログラミングインターフェイスで、呼び出し
Fg_Initを使用してアプレットを開始します。VisualAppletsで作成した*.hapファイルの場所へのパスを指定します。
利用可能なすべての関数呼び出しの詳細な説明とリファレンスについては、Framegrabber API Manual および Framegrabber API Function Reference を参照してください。
C++ SDK のベースとして、VisualApplets の内部 SDK コードジェネレーターを使用できます。これはアイコンメニュー内、または VisualApplets の Build および Generate SDK example から見つかります。この機能により、対応する CMake ファイルと Visual Studio プロジェクトファイルが自動的に生成されます(Hardware Applet: From Idea to Application も参照してください)。
自動生成されるSDKコードには、画像取り込みとパラメータ設定に必要な次の機能ブロックが含まれています。
- フレームグラバーの初期化
- バッファ用のMemoryの割り当て
- 定義
GetおよびSetProperty - ディスプレイの作成
- 存在する各ポートのアプレットおよびカメラでの取り込みの開始
- 画像の取り込み
- 取り込みの停止
- ディスプレイのクローズ
- バッファのMemoryの解放
- フレームグラバーの非初期化
シグナルプロセッシングのサンプルに関するC++ Framegrabber APIのサンプルコードを以下に示します。
- フレームグラバーの初期化とバッファ用のMemoryの割り当て:
int main ()
{
// ---------------------------------------------------------------------------
// Frame Grabber: Initialization
// ---------------------------------------------------------------------------
int nrOfCycles = 5000; // Acquire 5000 frames, TODO: insert the number according to your needs
unsigned int boardIndex = 0; // TODO: Use the correct board index at multi frame grabber systems
int rc = 0; // return code
Fg_Struct* fg = Fg_Init("SignalProcessingDesign.hap", boardIndex);
if(fg == NULL){
fprintf(stderr, "Error in Fg_Init(): %s\n", Fg_getLastErrorDescription(NULL));
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
return -1;
}
int nrOfParameter = Fg_getNrOfParameter(fg);
fprintf(stderr, "No. of Parameter: %d\n", nrOfParameter);
int i;
for (i = 0; i < nrOfParameter; i++) {
const char *name = Fg_getParameterName(fg,i);
fprintf(stderr," Param %d: %s,%x\n",i,name,Fg_getParameterId(fg,i));
}
/ ---------------------------------------------------------------------------
// Frame Grabber: Allocate memory for buffer(s)
// ---------------------------------------------------------------------------
// Feature Cnt 0,0
int width0 = 1024;
int height0 = 1024;
int byteWidth0 = 1;
size_t bufSize0 = width0 * height0 * (size_t)byteWidth0;
const unsigned int mem0_bufs = 4;
dma_mem *pmem0 = Fg_AllocMemEx(fg, bufSize0 * mem0_bufs, mem0_bufs);
if(pmem0 == NULL){
fprintf(stderr, "Error in Fg_AllocMemEx(): %s\n", Fg_getLastErrorDescription(fg));
Fg_FreeGrabber(fg);
fg = NULL;
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
return -1;
}
- 次の抽出
GetおよびSetパラメータセクション。ここでは、動的パラメータを設定する方法を確認できます。次のコードは、ダウンスケールファクターの設定方法と、Operatorのパラメータとして特定のパルスを選択する方法を示しています。Device1_Process0_ByFactor8:
// ---------------------------------------------------------------------------
// Frame Grabber: Get* and Set* parameters for Process0
// ---------------------------------------------------------------------------
/*============ Downscale : ByFactor8 ============== */
int Device1_Process0_ByFactor8_Downscale_Id = Fg_getParameterIdByName(fg, "Device1_Process0_ByFactor8_Downscale");
if(Device1_Process0_ByFactor8_Downscale_Id <= 0) {
fprintf(stderr, "\n");
fprintf(stderr, "Error in Fg_getParameterIdByName(Device1_Process0_ByFactor8_Downscale): %s (%d)\n", Fg_getLastErrorDescription(fg), Device1_Process0_ByFactor8_Downscale_Id);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
unsigned int Device1_Process0_ByFactor8_Downscale;
Device1_Process0_ByFactor8_Downscale = 8;
rc = Fg_setParameterWithType(fg, Device1_Process0_ByFactor8_Downscale_Id, Device1_Process0_ByFactor8_Downscale, 0);
if(rc < 0) {
fprintf(stderr, "\n");
fprintf(stderr, "Error in Fg_setParameterWithType(Device1_Process0_ByFactor8_Downscale_Id): %s (%d)\n", Fg_getLastErrorDescription(fg), rc);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
int Device1_Process0_ByFactor8_SelectedPulse_Id = Fg_getParameterIdByName(fg, "Device1_Process0_ByFactor8_SelectedPulse");
if(Device1_Process0_ByFactor8_SelectedPulse_Id <= 0) {
fprintf(stderr, "\n");
fprintf(stderr, "Error in Fg_getParameterIdByName(Device1_Process0_ByFactor8_SelectedPulse): %s (%d)\n", Fg_getLastErrorDescription(fg), Device1_Process0_ByFactor8_SelectedPulse_Id);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
unsigned int Device1_Process0_ByFactor8_SelectedPulse;
Device1_Process0_ByFactor8_SelectedPulse = 1;
rc = Fg_setParameterWithType(fg, Device1_Process0_ByFactor8_SelectedPulse_Id, Device1_Process0_ByFactor8_SelectedPulse, 0);
if(rc < 0) {
fprintf(stderr, "\n");
fprintf(stderr, "Error in Fg_setParameterWithType(Device1_Process0_ByFactor8_SelectedPulse_Id): %s (%d)\n", Fg_getLastErrorDescription(fg), rc);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
情報
自動生成されたC++ Framegrabber APIコードから、取得時のパラメータ設定に関連しないすべてのパラメータを削除しても問題ありません。取得中に設定する必要があるパラメータのみを残してください。
- ディスプレイの作成、取得の開始、および画像の取得:
// ---------------------------------------------------------------------------
// Frame Grabber: Create the display(s)
// ---------------------------------------------------------------------------
int id0 = CreateDisplay(8 * byteWidth0, width0, height0);
if(id0 < 0) {
fprintf(stderr, "Error in CreateDisplay(): %s (%d)\n", Fg_getLastErrorDescription(fg), id0);
Fg_FreeMemEx(fg, pmem0);
pmem0 = NULL;
Fg_FreeGrabber(fg);
fg = NULL;
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
return id0;
}
SetBufferWidth(id0, width0, height0);
// ---------------------------------------------------------------------------
// Frame Grabber: Start acquisition at applet and camera for each present port
// ---------------------------------------------------------------------------
rc = Fg_AcquireEx(fg, 0, nrOfCycles, ACQ_STANDARD, pmem0);
if(rc != 0) {
fprintf(stderr, "Error in Fg_AcquireEx() for channel 0: %s\n", Fg_getErrorDescription(fg, rc));
CloseDisplay(id0);
Fg_FreeMemEx(fg, pmem0);
pmem0 = NULL;
Fg_FreeGrabber(fg);
fg = NULL;
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
return rc;
}
// ---------------------------------------------------------------------------
// Frame Grabber: Grab images
// ---------------------------------------------------------------------------
frameindex_t frameNo0 = 0;
for(i = 1; i <= nrOfCycles; ++i){
frameNo0 = Fg_getLastPicNumberBlockingEx(fg, frameNo0 + 1, 0, 5, pmem0);
if(frameNo0 < 0) {
fprintf(stderr, "Error in Fg_getLastPicNumberBlockingEx(): %s (%d)\n", Fg_getLastErrorDescription(fg), frameNo0);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
break;
} else {
fprintf(stderr, "grabbed image %d\n", frameNo0 );
}
void *iPtr0 = Fg_getImagePtrEx(fg, frameNo0, 0, pmem0);
if(iPtr0 == NULL) {
fprintf(stderr, "Error in Fg_getImagePtrEx(): %s\n", Fg_getLastErrorDescription(fg));
Fg_stopAcquireEx(fg, 0, pmem0, 0);
CloseDisplay(id0);
Fg_FreeMemEx(fg, pmem0);
pmem0 = NULL;
Fg_FreeGrabber(fg);
fg = NULL;
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
return -1;
}
DrawBuffer(id0, iPtr0, frameNo0, "");
}
- 取得の停止、ディスプレイの閉鎖、バッファ用Memoryの解放:
// ---------------------------------------------------------------------------
// Frame Grabber: Stop acquisition
// ---------------------------------------------------------------------------
rc = Fg_stopAcquireEx(fg, 0, pmem0, 0);
if(rc < 0) {
fprintf(stderr, "Error in Fg_stopAcquireEx(): %s (%d)\n", Fg_getLastErrorDescription(fg), rc);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
// ---------------------------------------------------------------------------
// Frame Grabber: Close the display
// ---------------------------------------------------------------------------
CloseDisplay(id0);
// ---------------------------------------------------------------------------
// Frame Grabber: Release the memory for buffer(s)
// ---------------------------------------------------------------------------
rc = Fg_FreeMemEx(fg, pmem0);
if(rc < 0) {
fprintf(stderr, "Error in Fg_FreeMemEx(): %s (%d)\n", Fg_getLastErrorDescription(fg), rc);
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
pmem0 = NULL;
// ---------------------------------------------------------------------------
// Frame Grabber: Uninitialization
// ---------------------------------------------------------------------------
rc = Fg_FreeGrabber(fg);
if(rc < 0) {
fprintf(stderr, "Error in Fg_FreeGrabber(): %s\n", Fg_getLastErrorDescription(NULL));
fprintf(stderr, "Press <Return> to continue...\n");
getchar();
}
fg = NULL;
fprintf(stderr, "Press <Return> to exit...\n");
getchar();
return (0);
}
このサンプルコードをより大きなSDK環境に統合することができます。