Excel through learning

Excel through learning
Your source of knowledge

Monday, July 7, 2008

Use PowerShell to send scpi command to instrument

I start to 'seriously' learn PowerShell this Monday as I'm doing some investigation. I was not too impressed with it previously as most of the PoSh books I read discuss about it from the Shell's perspective. Then I'm lucky enough to read "Pro Windows PowerShell" by Hristo Deshev which teach from programmer's perspective. And now, I like to use PoSh so much!

I used to be using VBScript a lot in my projects. This is because I can easily apply it to many applications: ASP, Windows Scripting Host, Office's VBA and so on. There are few limitations with VBScript though, such as no User Interface (UI), can only use the COM object that have IDispatch interface and so on.

In the past, it was a pain if I want to use VBScript to send scpi command to the instrument. This is because the IMessage interface functions like "WriteString", "ReadString" are not exposed in IDispatch interface. That means I cannot use the "WriteString" and "ReadString" as I wish. I have to wrap the Visa IO into another COM object which expose these functions.

With PoSh, I'm able to do so. The implementation is not very direct though. The magic is done by using reflection. At the beginning, I tried to use "Type.InvokeMethod" to access the Ivi.Visa.Interop.IMessage's functions. But this interface does not implement IDispatch. Therefore, I get expection: "The COM target does not implement IDispatch". After some study, I found that I can use MemberInfo.Invoke in this case. Read The Essentials for Using COM in Managed Code for detail.

I have written part of the PoSh implementation as an object and share it here. Do let me know if you extend it.


function New-Instrument([string]$RscStr = $(throw "Resource string cannot be null"))
{
$Instance = New-Object PSObject
#Instancing local Variable
$_RM = New-Object -ComObject VISA.GlobalRM
$_Sess = $_RM.Open($RscStr)
$_WriteString = ([Ivi.Visa.Interop.IMessage]).GetMember("WriteString")[0]
$_ReadString = ([Ivi.Visa.Interop.IMessage]).GetMember("ReadString")[0]
$_Close =([Ivi.Visa.Interop.IMessage]).GetMember("Close")[0]

#class Field/Property
$Instance | Add-Member NoteProperty Sess $_Sess
$Instance | Add-Member NoteProperty _WriteString $_WriteString
$Instance | Add-Member NoteProperty _ReadString $_ReadString
$Instance | Add-Member NoteProperty _Close $_Close
#Methods
$Instance | Add-Member -MemberType ScriptMethod WriteString{
param([string]$Command)
#param matching due to PoSh 1.0 Bug
$Command = $args[0]
if ($Command -eq $null)
{
throw "Command cannot be null"
}
$this._WriteString.Invoke($this.Sess,$Command) >$null
}

$Instance | Add-Member ScriptMethod ReadString{
param([int]$Length=1024)
#Param matching
$Length = $args[0]
if ($Length -eq $null)
{
$Length = 1024
}
return $this._ReadString.Invoke($this.Sess,$Length)
}

$Instance | Add-Member ScriptMethod Query{
param([string]$Command)
$Command = $args[0]
if ($Command -eq $null)
{
throw "Command cannot be null"
}
$this.WriteString($Command)
return $this.ReadString()
}
$Instance | Add-Member ScriptMethod Close{
$this._Close.Invoke($this.Sess,$null)
}


return $Instance
}
$Inst = New-Instrument("GPIB0::6::INSTR")
$Inst.WriteString("*IDN?")
$Inst.ReadString()
$Inst.Query("*IDN?")
$Inst.Close()



PoSh Output


Download source code

0 comments: