光束分析仪BP209-IR/M的动态库TLBP2_32.dll得通信调用

By admin at 2021-04-13 • 0人收藏 • 228人看过

最近用到这个设备, 这里写下调用的时候遇到的问题和解决方法.

这里先贴出来C语言的调用示例

//==============================================================================
//
// Title:		CSample
// Purpose:		A short description of the command-line tool.
//
// Created on:	16.05.2013 at 14:01:49 by tempinstall.
// Copyright:	. All Rights Reserved.
//
//==============================================================================

//==============================================================================
// Include files

#include <ansi_c.h>
#include "TLBP2.h"

//==============================================================================
// Constants
#define  MAX_INSTRUMENTS			10    // max. 10 instruments in selection list
#define  BP2_BUFFER_SIZE			256                 // General buffer size
#define  BP2_TIMEOUT_MAX			60000
#define  BP2_MAX_SLIT_COUNT			4
//==============================================================================
// Types

//==============================================================================
// Static global variables

ViSession m_handle;

ViUInt16			m_wavelength_min;
ViUInt16			m_wavelength_max;
ViReal64			m_wavelength;
BP2_SLIT_DATA		m_slitData[7500];
BP2_CALCULATIONS	m_calculationResults[256];
ViReal64			m_power;
ViUInt8				m_slitUsed[BP2_MAX_SLIT_COUNT];
ViUInt8				m_slitLength[BP2_MAX_SLIT_COUNT];
ViUInt8				m_slitWidth[BP2_MAX_SLIT_COUNT];
ViUInt8				m_slitOrientation[BP2_MAX_SLIT_COUNT];

			BP2_SLIT_DATA slit_data[4]; ///< BP2_MAX_SLIT_COUNT = 4
			BP2_CALCULATIONS calculation_result[4];
	      //ViReal64 power;
			ViReal32 powerSaturation;
			ViReal64 power_intensities[7500];

//==============================================================================
// Static functions

// prints the error message from an error code
static void print_error_msg(ViStatus errorCode)
{
   char messageBuffer[256];

   // Get error string
   TLBP2_error_message(m_handle, errorCode, messageBuffer);

   if((errorCode & _VI_ERROR) == 0) // just a scan warning, no error
      printf("Beam Profiler Warning: %s\n", messageBuffer);

   else // errors
   {
      printf("Beam Profiler Error: %s\n", messageBuffer);

      // close instrument after an error has occured
		if (m_handle > 0)
			TLBP2_close(m_handle);
   }
}

//==============================================================================
// Global variables

//==============================================================================
// Global functions

int main (int argc, char *argv[])
{
	BP2_DEVICE* resStr = VI_NULL;
	ViUInt8 gain_buffer[5];
	ViReal64 bw_buffer[4];
	ViUInt8 loopCnt;
	ViUInt16 device_status = 0;  
	
	ViUInt16 sampleCount;
	ViReal64 resolution;
	
	ViUInt16 min_wavelength;
	ViUInt16 max_wavelength;
		
	m_handle = 0;

	// get the number of connected devices
	ViUInt32 deviceCount = 0;
	ViStatus res = TLBP2_get_connected_devices(VI_NULL, VI_NULL, &deviceCount);
	
	if (res != VI_SUCCESS)
	{
		print_error_msg(res);
		return 0;
	} 
	
	if (deviceCount == 0)
	{
		printf("No device connected\n");
		return 0;
	}

	// interrupt the program to attach to this process for debugging the driver
#ifdef _DEBUG
	printf("Press <Enter> to start the application\n");
	getchar();
#endif

	// initialize the buffer for the resource strings
	resStr = malloc(sizeof(BP2_DEVICE)*deviceCount);

	// get the reource strings of the connected devices
	res = TLBP2_get_connected_devices(VI_NULL, resStr, &deviceCount);

	if (res != VI_SUCCESS)
	{
		print_error_msg(res);
		free(resStr);
		return 0;
	}

	// connect with the first device
	res = TLBP2_init(resStr[0].resourceString, VI_TRUE, VI_FALSE, &m_handle);

	// release the buffer for the resource strings
	free(resStr);

	// abort if an error during the initialization occurred
	if ((res & _VI_ERROR) == _VI_ERROR)
	{
		print_error_msg(res);
		return 0;
	}

	// rotate with 10 hz
	res = TLBP2_set_drum_speed_ex(m_handle, 10.0, &sampleCount, &resolution);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}
	
	// set the manual gain
	gain_buffer[0] = 12;
	gain_buffer[1] = 12;
	gain_buffer[2] = 12;
	gain_buffer[3] = 12;
	gain_buffer[4] = 12;
	res = TLBP2_set_gains(m_handle, gain_buffer, gain_buffer[4]);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}
	
	// set the automatic gain
	res = TLBP2_set_auto_gain(m_handle, VI_TRUE);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}
	
	// set the bandwidth to 125 ( as the Thorlabs Beam Application)
	bw_buffer[0] = 125.0;
	bw_buffer[1] = 125.0;
	bw_buffer[2] = 125.0;
	bw_buffer[3] = 125.0;
	res = TLBP2_set_bandwidths(m_handle, bw_buffer);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}
	
	// request the wavelength range and set the wavelength
	res = TLBP2_get_wavelength_range(m_handle, &min_wavelength, &max_wavelength);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}
	res = TLBP2_set_wavelength(m_handle, min_wavelength + (max_wavelength - min_wavelength) /2);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}
	
	// set the position correction
	res = TLBP2_set_position_correction(m_handle, VI_ON);
	if ((res & _VI_ERROR) > 0)
	{
		print_error_msg(res);
		return 0;
	}

	// get a measurement
	for(loopCnt = 0; loopCnt < 10; loopCnt++)
	{
		device_status = 0;
		res = VI_SUCCESS;
		while(res == VI_SUCCESS && (device_status & BP2_STATUS_SCAN_AVAILABLE) == 0)
		{
			res = TLBP2_get_device_status(m_handle, &device_status);
		}

		if (res == VI_SUCCESS)
		{
			BP2_SLIT_DATA slit_data[4]; ///< BP2_MAX_SLIT_COUNT = 4
			BP2_CALCULATIONS calculation_result[4];
	      ViReal64 power;
			ViReal32 powerSaturation;
			ViReal64 power_intensities[7500];
			// get the calculation 
			res = TLBP2_get_slit_scan_data(m_handle, slit_data, calculation_result, &power, &powerSaturation, power_intensities);
			if (res == VI_SUCCESS)
			{
				printf("Power: %.2f\n", power);
				printf("Power Saturation: %.2f\n", powerSaturation); 
				printf("Peak Position Slit 1: %.2f\n", calculation_result[0].peakPosition);
				printf("Centroid Position Slit 1: %.2f\n", calculation_result[0].centroidPosition);
				printf("Peak Position Slit 2: %.2f\n", calculation_result[1].peakPosition);
				printf("Centroid Position Slit 2: %.2f\n", calculation_result[1].centroidPosition);
				
				// get the gains
				res = TLBP2_get_gains(m_handle, gain_buffer, &gain_buffer[4]);
				if (res == VI_SUCCESS)
				{
					printf("Gain 1: %d\n", gain_buffer[0]);
					printf("Gain 2: %d\n", gain_buffer[1]);
					printf("Gain 3: %d\n", gain_buffer[2]);
					printf("Gain 4: %d\n", gain_buffer[3]);
					printf("Gain Power: %d\n", gain_buffer[4]);
				}
			}
			else
				printf("The scan returned the error: %x\n", res);

		}
		else
			printf("The device status returned the error: %d\n", res);
	}

	// release the device
	TLBP2_close(m_handle);
	
	return 0;
}

从以上代码看出来, 里面要用到两个主要的结构体和结构体数组. 

那么翻译成aardio,应该这样描述:

import win.ui;
/*DSG{{*/
mainForm = win.form(text="aardio工程";right=694;bottom=419)
mainForm.add(
button={cls="button";text="Button";left=234;top=243;right=496;bottom=324;z=1}
)
/*}}*/

import console
console.open()

var dll = ..raw.loadDll("\res\TLBP2_32.dll","beamLib");
TLBP2_get_connected_devices = dll.api("TLBP2_get_connected_devices","int(int,pointer,int&)" );
TLBP2_init = dll.api("TLBP2_init","int(string,bool,bool,ADDR&)" );
TLBP2_close = dll.api("TLBP2_close","int(ADDR)" );
TLBP2_set_drum_speed_ex = dll.api("TLBP2_set_drum_speed_ex","int(ADDR,double,WORD&,double&)" );
TLBP2_set_auto_gain = dll.api("TLBP2_set_auto_gain","int(ADDR,bool)" )
TLBP2_set_bandwidths = dll.api("TLBP2_set_bandwidths","int(ADDR,pointer)" )
TLBP2_get_wavelength_range = dll.api("TLBP2_get_wavelength_range","int(ADDR,WORD&,WORD&)" )
TLBP2_set_wavelength = dll.api("TLBP2_set_wavelength","int(ADDR,double)" )
TLBP2_set_position_correction = dll.api("TLBP2_set_position_correction","int(ADDR,bool)" )
TLBP2_get_device_status = dll.api("TLBP2_get_device_status","int(ADDR,WORD&)" )
TLBP2_get_slit_scan_data = dll.api("TLBP2_get_slit_scan_data","int(ADDR,pointer,pointer,double&,float&,pointer)" )
TLBP2_error_message = dll.api("TLBP2_error_message","int(ADDR,int,string&)" )

var buff = raw.buffer(256*10,'\0');
var ret = TLBP2_get_connected_devices(0,buff,0);
var serialstr = raw.str(buff);
console.log("TLBP2_get_connected_devices",ret,serialstr)
ret,handle = TLBP2_init(serialstr,true,false,0);
console.log("TLBP2_init",ret,handle)
ret,sampleCount,resolution = TLBP2_set_drum_speed_ex(handle,10.0,0,0);
console.log("TLBP2_set_drum_speed_ex",ret,sampleCount,resolution)
ret = TLBP2_set_auto_gain(handle,true);
console.log("TLBP2_set_auto_gain",ret)
bandwidths = raw.buffer({double a[4]={125.0,125.0,125.0,125.0}});
ret = TLBP2_set_bandwidths(handle,bandwidths);
console.log("TLBP2_set_bandwidths",ret)
ret,min_wavelength,max_wavelength = TLBP2_get_wavelength_range(handle,0,0);
console.log("TLBP2_get_wavelength_range",ret,min_wavelength,max_wavelength)
ret = TLBP2_set_wavelength(handle,1550/*min_wavelength+(max_wavelength-min_wavelength)/2*/);
console.log("TLBP2_set_wavelength",ret)
ret = TLBP2_set_position_correction(handle,true);
console.log("TLBP2_set_position_correction",ret)


mainForm.button.oncommand = function(id,event){
	var res = 0;
	var device_status = 0;
	while( (res==0) and ((device_status&0x0001)==0) ){
		res,device_status = TLBP2_get_device_status(handle,0);
	}
	if(res==0){
		var slit_data_len = raw.sizeof({
				WORD slit_sample_count;
				float slit_dark_level;
				float slit_samples_intensities[7500];
				float slit_samples_positions[7500];
				WORD encoder_increments;	
			});
		
		var calculation_result_len = raw.sizeof({
				WORD isValid;	
				WORD peakIndex;
				float peakPosition;
				float peakIntensity;	
				WORD centroidIndex;
				float centroidPosition;
				float beamWidthClip;
				float gaussianFitAmplitude;	
				float gaussianFitCentroid;
				float gaussianFitDiameter;
				float gaussianFitPercentage;
				float gaussianFitCurve[7500];	
				float besselFitPercentage;
				float besselFitCurve[7500];
				float sigma;
				float calcAreaLeftBorder;
				float calcAreaRightBorder;	
			});
			
		var pslitData = raw.buffer(slit_data_len*4);	
		var pcalculation_result = raw.buffer(calculation_result_len*4);
		
		var ret,power,powerWindowSaturation = TLBP2_get_slit_scan_data(handle,pslitData,pcalculation_result,10,0,null);
		
		if(ret==0){
			console.log("TLBP2_get_slit_scan_data",ret,power,powerWindowSaturation);

			var retdata = raw.convertArray(pcalculation_result,4,{
				WORD isValid;	
				WORD peakIndex;
				float peakPosition;
				float peakIntensity;	
				WORD centroidIndex;
				float centroidPosition;
				float beamWidthClip;
				float gaussianFitAmplitude;	
				float gaussianFitCentroid;
				float gaussianFitDiameter;
				float gaussianFitPercentage;
				float gaussianFitCurve[7500];	
				float besselFitPercentage;
				float besselFitCurve[7500];
				float sigma;
				float calcAreaLeftBorder;
				float calcAreaRightBorder;	
			});
			
			console.log("Peak Position Slit 1:",retdata[1].peakPosition)
			console.log("Centroid Position Slit 1:",string.format("%.2f", retdata[1].centroidPosition))
			console.log("Peak Position Slit 2:",retdata[2].peakPosition)
			console.log("Centroid Position Slit 2:",string.format("%.2f", retdata[2].centroidPosition))
			//console.log("Centroid Position Slit 3:",string.format("%.2f", retdata[3].centroidPosition))
			//console.log("Centroid Position Slit 4:",string.format("%.2f", retdata[4].centroidPosition))
		}else {
			console.log(ret,string.format("%X", ret))
			console.log(TLBP2_error_message(handle,ret,raw.buffer(256)))
		}
		
	}
	
}

mainForm.onClose = function(hwnd,message,wParam,lParam){
    var ret = TLBP2_close(handle);
	console.log("TLBP2_close",ret)
}



mainForm.show();
return win.loopMessage();

image.png

以上, 主要看结构体那部分

首先C结构体第一个参数里面的viBoolean追踪过去其实是unsigned short, 在aardio中应该转换为WORD, 我之前按照字面意思转换为bool就是错误的.

这里先用sizeof()来求出此结构体的大小, 然后*4得出需要的buff大小, 然后执行了dll函数之后, 得到了数据还需要转换为结构体数组, 这里用到了raw.convertArray() , 一次转换为了定长的结构体数组.



1 个回复 | 最后更新于 2021-04-15
2021-04-15   #1

经过jacenHe老大的指点, 我上面把结构体用法复杂化了, dll声明的时候可以直接用struct , 这样会简单很多. 还有结构体数组也是可以直接赋值的. 具体可以看下面的代码.

程序修改后如下:

import console
console.open()

var dll = ..raw.loadDll("\res\TLBP2_32.dll","beamLib");
TLBP2_get_connected_devices = dll.api("TLBP2_get_connected_devices","int(int,str&,int&)" );
TLBP2_init = dll.api("TLBP2_init","int(string,bool,bool,ADDR&)" );
TLBP2_close = dll.api("TLBP2_close","int(ADDR)" );
TLBP2_set_drum_speed_ex = dll.api("TLBP2_set_drum_speed_ex","int(ADDR,double,WORD&,double&)" );
TLBP2_set_auto_gain = dll.api("TLBP2_set_auto_gain","int(ADDR,bool)" )
TLBP2_set_bandwidths = dll.api("TLBP2_set_bandwidths","int(ADDR,struct)" )
TLBP2_get_wavelength_range = dll.api("TLBP2_get_wavelength_range","int(ADDR,WORD&,WORD&)" )
TLBP2_set_wavelength = dll.api("TLBP2_set_wavelength","int(ADDR,double)" )
TLBP2_set_position_correction = dll.api("TLBP2_set_position_correction","int(ADDR,bool)" )
TLBP2_get_device_status = dll.api("TLBP2_get_device_status","int(ADDR,WORD&)" )
TLBP2_get_slit_scan_data = dll.api("TLBP2_get_slit_scan_data","int(ADDR,struct&,struct&,double&,float&,pointer)" )
TLBP2_error_message = dll.api("TLBP2_error_message","int(ADDR,int,string&)" )

var buff = raw.buffer(256*10);
var ret,serialstr = TLBP2_get_connected_devices(0,buff,0);
console.log("TLBP2_get_connected_devices",ret,serialstr)
ret,handle = TLBP2_init(serialstr,true,false,0);
console.log("TLBP2_init",ret,handle)
ret,sampleCount,resolution = TLBP2_set_drum_speed_ex(handle,10.0,0,0);
console.log("TLBP2_set_drum_speed_ex",ret,sampleCount,resolution)
ret = TLBP2_set_auto_gain(handle,true);
console.log("TLBP2_set_auto_gain",ret)
ret = TLBP2_set_bandwidths(handle,{double a[4]={125.0,125.0,125.0,125.0}});
console.log("TLBP2_set_bandwidths",ret)
ret,min_wavelength,max_wavelength = TLBP2_get_wavelength_range(handle,0,0);
console.log("TLBP2_get_wavelength_range",ret,min_wavelength,max_wavelength)
ret = TLBP2_set_wavelength(handle,1550/*min_wavelength+(max_wavelength-min_wavelength)/2*/);
console.log("TLBP2_set_wavelength",ret)
ret = TLBP2_set_position_correction(handle,true);
console.log("TLBP2_set_position_correction",ret)


mainForm.button.oncommand = function(id,event){
	var res = 0;
	var device_status = 0;
	while( (res==0) and ((device_status&0x0001)==0) ){
		res,device_status = TLBP2_get_device_status(handle,0);
	}
	if(res==0){
		var slit_data = {
				struct data[4]={
					{
						WORD slit_sample_count;
						float slit_dark_level;
						float slit_samples_intensities[7500];
						float slit_samples_positions[7500];
						WORD encoder_increments;	
					}
				}
			};
		
		var calculation_result = {
				struct data[4]={
					{
						WORD isValid;	
						WORD peakIndex;
						float peakPosition;
						float peakIntensity;	
						WORD centroidIndex;
						float centroidPosition;
						float beamWidthClip;
						float gaussianFitAmplitude;	
						float gaussianFitCentroid;
						float gaussianFitDiameter;
						float gaussianFitPercentage;
						float gaussianFitCurve[7500];	
						float besselFitPercentage;
						float besselFitCurve[7500];
						float sigma;
						float calcAreaLeftBorder;
						float calcAreaRightBorder;	
					}
				}
			};

		var ret,slit_data,calculation_result,power,powerWindowSaturation = TLBP2_get_slit_scan_data(handle,slit_data,calculation_result,10,0,null);
		
		if(ret==0){
			console.log("TLBP2_get_slit_scan_data",ret,power,powerWindowSaturation);
	
			console.log("Peak Position Slit 1:",calculation_result.data[1].peakPosition)
			console.log("Centroid Position Slit 1:",string.format("%.2f", calculation_result.data[1].centroidPosition))
			console.log("Peak Position Slit 2:",calculation_result.data[2].peakPosition)
			console.log("Centroid Position Slit 2:",string.format("%.2f", calculation_result.data[2].centroidPosition))
			//console.log("Centroid Position Slit 3:",string.format("%.2f", retdata[3].centroidPosition))
			//console.log("Centroid Position Slit 4:",string.format("%.2f", retdata[4].centroidPosition))
		}else {
			console.log(ret,string.format("%X", ret))
			console.log(TLBP2_error_message(handle,ret,raw.buffer(256)))
		}
		
	}
	
}

另外, 温习下struct的相关知识.

跟C一样,只是 aardio 里的结构体要注意以下2点
1、所有结构体转到外部API都是转换为结构体指针,传址而不是传值,实际上结构体基本都是使用指针,传值很罕见。
2、aardio 总是临时分配内存并将结构体转换为静态指针,调用完会释放临时分配的结构体内存,如果你多次把结构体传给API,他们得到的指针地址是不一样的,如果有些很特殊的情况,他们需要一个全局不变的指针,这时候就需要用 raw.buffer 将结构体转换为固定不变的内存指针,但这种情况其实非常非常少。

如果声明为 struct & ,aardio 会复制2次,先把aardio结构体复制到临时分配的结构体内存,调用完又拷贝回来。这样就得到了结构体被更新的值。

无声明调用API时总是与 struct & 的处理相同。

登录后方可回帖

登 录
信息栏
本站永久域名:HtmLayout.Cn
纯私人站,当笔记本用的,学到哪写到哪,目前在学aardio+halcon机器视觉.
Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
苏扬博客:苏扬博客
C大Aardio论坛:Aar爱好者论坛
简码教程网:简码编程
AARDIO语言QQ群:70517368
本 站 主 站:Stm32cube中文网
Htmlayout界面在线学习文档
Sciter中文在线文档Sciter在线学习文档
aardio在线手册Aardio在线手册

赞助商:才仁机械
下载站:非凡软件站
Loading...