應用指南:為可程式化擷取卡設計訊號處理 Applet#
VisualApplets 中的 GPI/GPO Operators#
透過 VisualApplets,您可以設計專屬於您的應用特定觸發系統。例如,您可以決定由哪一個實體 I/O 接腳傳送或接收訊號。
在 VisualApplets 中,有兩個運算元可用於將個別接腳與您的 Applet 設計進行連線:
Operator GPI(用於觸發 IN 訊號)
Operator GPO(用於觸發 OUT 訊號)

上圖顯示了一個如何實作訊號處理的範例。您想要實作的訊號處理功能取決於您的特定需求。若要為您的應用找到合適的 operator,請造訪 Signal Library。此外,也請根據您的需求選擇 Front GPIO。
上方範例顯示了針對兩個輸入訊號的縮小功能。兩個訊號從 GPI1 和 Front GPI0 輸入至可程式化影音擷取卡。這些訊號首先會進行彈跳消除、選取上升緣或下降緣,然後以 8 或 3 的係數進行 Scaling。系統會為這兩個訊號設定訊號長度,接著將訊號轉發至 FrontGPO0、GPO1、GPO2 以及相機以控制影像擷取。
使用 GPI/GPO Operators#
您想要在 Front GPIO 或 Trigger Extension Board 上使用的每個 Trigger IN / Trigger OUT 接腳,都必須與 GPI/GPO 運算元的執行個體相互連接。
資訊
由於 Operator GPI 與 Operator GPO 具有相同的 funcionality,因此在下文中將這兩個運算元一起說明。
- 在設計中的 operator 圖示上按兩下以開啟 Module Properties 視窗。

Module Properties 視窗隨即開啟:

如您所見,該運算元具有兩個 Property:
Pin_ID:Property Pin_ID 允許您定義要定址所選連接器上的哪一個個別接腳。ConnectorType:Property ConnectorType 允許您定義要定址哪一個連接器(Front GPIO 或透過 GPIO 的 Trigger Extension Board)。
資訊
對於 CXP-12 影音擷取卡, ConnectorType Property 包含在 Pin_ID 參數的值。
Parameter Connector Type#
此 Property 允許您定義要定址哪一組觸發接腳,即 15 針 D-Sub 插座中提供的接腳(Front GPIO),或是 Trigger Extension Board 上提供的接腳(GPIO)。此 Property 的數值範圍為 {Front GPIO, GPIO}。
Value Front GPIO#
如果您選取數值 Front GPIO,即表示您定址可程式化影音擷取卡槽板上的下列連接器(觸發接腳群組):

Value GPIO#
如果您選取數值 GPIO,即表示您定址可程式化影音擷取卡上的下列觸發接腳群組:

GPIO 用於連接至 Trigger Extension Board:

Property Pin_ID#
此 Property 允許您定義要定址所選連接器(觸發接腳群組)上的哪一個個別接腳。Property 的數值範圍 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}.
Front GPIO 上的接腳組態與 VisualApplets Operator Reference#


在差動模式下,引腳 9 可用於在 Pin_ID=3 的 GPI 運算子上接收單端訊號,請參閱「Differential」模式(預設)。
注意
擷取卡觸發系統需要從 Voltage IN 引腳取得供應電壓。如果要連接沒有 PWR 引腳的裝置,則需要從外部來源為 Voltage IN 引腳提供電源。
Trigger INPUT on the Front GPIO#
如果您
- 正在使用
GPI運算子(用於定義觸發輸入訊號), - 已將參數
Connector Type設定為Front GPIO,
參數 Pin_ID 的值對應到下列引腳:

Front GPIO 的輸入 (GPI) 引腳是可以設定的。您可以使用六個輸入引腳來接收下列其中一項:
- 3 個差動訊號,或
- 2 個差動訊號與 1 個單端訊號,或
- 4 個單端訊號。
若要針對特定訊號類型(差動或單端)設定 Front GPIO 上的輸入引腳,您有兩種可用模式:
- 模式
Differential(提供選項 a 和 b) - 模式
Single-ended(提供選項 c)
Front GPIO 的預設模式為 Differential。關於如何切換模式,請參閱主題 輸入組態 於採集卡手冊中。
注意
在預設組態中,Front GPIO 的 GPIO 引腳提供:
- 上拉模式下的 3 個差動輸入訊號,或 2 個差動與 1 個單端輸入訊號
- 兩個 TTL 輸出訊號
如果您需要其他輸入訊號組態,即:
- 下拉模式,
- 4 個單端訊號(且無差動訊號),
您可以根據需求輕鬆設定 GPI。若要進行設定,請使用隨 Framegrabber SDK 一起安裝在您系統上的命令列工具。
模式 Differential (預設)#
在模式 Differential (預設)下,Front GPIO 的所有六個輸入接腳均設定為接收差動訊號:
- 接腳 8/9 -> 1 個差動訊號
- 接腳 11/12 -> 1 個差動訊號
- 接腳 13/14 -> 1 個差動訊號
或者,您可以使用接腳對 8/9(在模式 Differential中)來接收一個單端訊號:
- 接腳 9 -> 1 個單端訊號
- 接腳 11/12 -> 1 個差動訊號
- 接腳 13/14 -> 1 個差動訊號
模式中的個別接腳 Differential:

接腳 11 與 12:
- 接腳 11 與 12 上的輸入訊號會被解讀為一個差動訊號(接腳 11 為正 [+] 值,接腳 12 為負 [-] 值)。
- 若要在 VisualApplets 中接收此差動訊號,請使用 Pin_ID = 0 的 GPI 運算子執行個體。
接腳 13 與 14:
- 接腳 13 與 14 上的輸入訊號會被解讀為一個差動訊號(接腳 13 為正 [+] 值,接腳 14 為負 [-] 值)。
- 若要在 VisualApplets 中接收此差動訊號,請使用 Pin_ID = 1 的 GPI 運算子執行個體。
接腳 8 與 9:
- 接腳 8 與 9 上的輸入訊號會被解讀為一個差動訊號(接腳 8 為正 [+] 值,接腳 9 為負 [-] 值)。
- 若要在 VisualApplets 中接收此差動訊號,請使用 Pin_ID = 2 的 GPI 運算子執行個體。
或者,您可以使用接腳對 8/9 來接收一個單端訊號(儘管在模式 Differential中):在此情況下,
- 您可以將單端輸入訊號連接至實體接腳 9。
- 若要在 VisualApplets 中接收此單端信號,請使用 Pin_ID = 3 的 GPI operator 實例。
模式 Single-Ended#
在模式 Single-ended (可設定),Front GPIO 的六個輸入引腳經設定可接收 4 個單端信號:
- Pin 8 -> 1 個單端信號
- 接腳 9 -> 1 個單端訊號
- Pin 11 -> 1 個單端信號
- Pin 13 -> 1 個單端信號
模式中的個別接腳 Single-ended:

Pin 11 和 12 上的信號:
- Pin 11 上的輸入信號會被解讀為單端信號。
- 若要在 VisualApplets 中接收此單端信號,請使用 Pin_ID = 0 的 GPI operator 實例。
- 在此模式下不使用 Pin 12
Single-ended.
Pin 13 和 14 上的信号:
- Pin 13 上的輸入信號會被解讀為單端信號。
- 若要在 VisualApplets 中接收此單端信號,請使用 Pin_ID = 1 的 GPI operator 實例。
- 在此模式下不使用 Pin 14
Single-ended.
接腳 8 與 9:
- Pin 8 和 9 上的輸入信號會被解讀為兩個單端信號。
-
若要在 VisualApplets 中接收這些單端信號,請使用
- 針對 Pin 8 使用 Pin_ID = 2 的 GPI operator 實例,以及
- 針對 Pin 9 使用 Pin_ID = 3 的 GPI operator 實例。
觸發 OUTPUT TTL 位於 Front GPIO 上#
如果您
- 使用 GPO operator 來定義觸發輸出信號,
- 您已將 Connector Type 參數設定為 Front GPIO,
Pin_ID 參數的值對應至下列引腳:

這兩個引腳會發送 TTL 信號(5 V)。
Front GPIO 上的輸出 TTL 信號(5 V):

定址 Trigger Extension Boards 的觸發訊號 (透過 GPIO)#
GPIO 連接器是可程式化擷取卡的實體觸發介面,專為連接至 Trigger Extension Board 而設計:

GPIO 連接器,也就是每個 Trigger Extension Board,提供:
- 8 個數位輸入(IN 0 - 7)(8 個單端信號或 4 個差動信號)
- 8 個數位輸出(OUT 0 - 7)
這八個輸入的索引為 0 到 7。這八個輸出的索引也為 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 上的分配#
Port A#
| 接腳編號 | 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 |
Port B#
| 接腳編號 | 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 上的分配#
Port A#
| 接腳編號 | 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 |
Port B#
| 接腳編號 | 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 |
設定觸發系統#
您可以透過兩種方式存取觸發組態:
- microDisplay X:您可以在此透過 GUI 輸入觸發參數值,以檢查特定組態的結果。
- SDK:用於將擷取卡程式介面實作到特定的影像處理軟體應用程式中。
對觸發系統的要求會因您的應用而異:
- 對於面陣相機(Area Scan),只需要一種觸發類型(影格觸發)。
- 對於線陣相機(Line Scan),需要兩種觸發類型:線觸發(為每一行發送一個觸發脈衝)和影格觸發。在線陣相機應用中,影格觸發控制影像中附加了多少行。
您可以在此處找到有關如何觸發面陣和線陣相機的更多資訊。
資訊
有關採集卡觸發系統的進一步資訊,請參閱主題 GPIO Connectors。
資訊
有關哪些參數可用(以及特定設定可能產生的影響)的資訊,請參閱您正在使用的 Applet 的說明文件。
在硬體上執行您的 Applet#
先決條件:
- 您的可程式化採集卡已依照主題 Connecting Frame Grabbers 中的說明安裝在您的系統上。
- Basler Framegrabber SDK 已依照 Installing the Framegrabber SDK 中的說明安裝在您的系統上。
在您的可程式化擷取卡上執行 Applet 之前,必須先將您的 *.hap 檔案(Applet)複製到主機 PC 上的 Basler Framegrabber SDK 安裝目錄中,並将其燒錄至您的可程式化擷取卡。
資訊
只有 marathon 擷取卡才需要進行燒錄。
您可以在 Hardware Applet: From Idea to Application 下找到關於如何將 VisualApplets 設計轉換為硬體 applet 的詳細資訊。
-
將您在 VisualApplets 中建立的
*.hap檔案複製到目錄[Framegrabber SDK installation directory]/Hardware Applets/[frame grabber model]中。如果沒有對應可程式化擷取卡型號名稱的子目錄,請自行建立。如果您在 VisualApplets 中使用了預設設定,您將在 VisualApplets 安裝目錄的子目錄*.hap中找到您的Designs. -
依照 Flashing 中的說明將您的 applet 安裝到可程式化採集卡上。
完成此操作後,您可以:
- 使用作為 Framegrabber SDK 一部分的 Basler 工具 microDisplay X 來測試您的 applet,並直接檢視 applet 的影像處理結果。請參閱主題 Configuring the Applet (microDisplay X)。
範例:當您將訊號處理範例設計的硬體 Applet 載入 microDisplay X 時,您可以在參數樹中設定動態參數,例如降階縮放比例與訊號寬度,如下圖所示。

在您自己的軟體中啟動 Applet#
若要開始在您自己的軟體中使用該 Applet:
- 在 Basler 應用程式介面上,使用呼叫
Fg_Init來啟動 Applet。請指定您使用 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和Set參數 - 建立顯示畫面
- 為每個現有的連接埠啟動 Applet 與相機的擷取
- 擷取影像
- 停止擷取
- 關閉顯示
- 釋放緩衝區的 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參數區段。在此您可以看到如何設定動態參數。以下程式碼展示了如何設定縮小比例(downscale factor),以及如何選擇特定脈衝作為 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 環境中。