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

By admin at 2021-04-13 • 1人收藏 • 1158人看过

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

这里先贴出来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 & 的处理相同。

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...