是德科技
直播中

庄雪昕

7年用户 166经验值
私信 关注
[问答]

快速数据通过SCPI将ENA测量结果提取给计算机

   Hello, I'm currently involved in a project which requires frequent reading ENA measurement data to a remote PC using SCPI command.  I found a piece of code written by @ningchen, and test it on a powerful PNA N5227A, the code works perfectly and only takes a few hundred milliseconds to get the data. The code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ivi.Visa.Interop;
using System.Diagnostics;
namespace ReadSnp
{
public class FmtIoBinaryReader
{ //
// Read binary format data from IO.
// PNA return a binary stream in order: [#][byte count of count][count][data...data...data...][end]
//
protected FormattedIO488 _ioDmm;
protected ulong _lenOfDataInByte;
protected ulong _currentPos;
public ulong LenOfDataInByte
{
get { return _lenOfDataInByte; }
protected set { _lenOfDataInByte = value; }
}
public FmtIoBinaryReader(FormattedIO488 io)
{
_ioDmm = io;
_currentPos = 0;
}
public ulong BeginRead()
{
byte[] pound = _ioDmm.IO.Read(1);
byte[] count = _ioDmm.IO.Read(1);
int numToRead = int.Parse(((char)count[0]).ToString());
byte[] rawcount = _ioDmm.IO.Read(numToRead);
List al = new List(rawcount.Length);
foreach (byte b in rawcount)
al.Add((char)b);
char[] chByteCount = al.ToArray();
LenOfDataInByte = ulong.Parse(new string(chByteCount));
return LenOfDataInByte;
}
public bool Read(ulong len, out byte[] buff)
{
if (_currentPos == _lenOfDataInByte)
{
buff = null;
return false;
}
else if (_currentPos + len > _lenOfDataInByte)
len = _lenOfDataInByte - _currentPos;
buff = _ioDmm.IO.Read(Convert.ToInt32(len));
_currentPos += len;
return true;
}
public void EndRead()
{
if (_currentPos >= _lenOfDataInByte)
_ioDmm.IO.Read(1);
}
}
class Program
{
static void Main(string[] args)
{
double[][] sparaOut;
double[][,] sparaMea;
bool rst = true;
// read snp data from PNA, for a two port measurment, read freuqnecy, S11, S21 S12 and S22 all at onec
// If calibration is not performed yet, user should display all traces on the PNA. If cailibration is already done,
// then even if only S11 is displayed, user can correctly get all measured S paramerementer through the SCPI command calculate:data:snp:ports?
FormattedIO488 ioDmm = new FormattedIO488Class();
ResourceManager grm = new ResourceManager();
string visaAddress = "TCPIP0::A-N5227A-70295::inst0::INSTR";
ioDmm.IO = (IMessage)grm.Open(visaAddress, AccessMode.NO_LOCK, 0, "");
//set timeout to be 20 seconds
ioDmm.IO.Timeout = 20000;
DateTime startDate = DateTime.Now;
ioDmm.WriteString("trigger:sequence:source immediate", rst);
// set continuous scan
ioDmm.WriteString(":SENS:SWE:GRO:COUN 1", true);
ioDmm.WriteString(":SENS:SWE:MODE GRO", true); //SENS:SWE:MODE CONT
ioDmm.WriteString("SENS:SWE:MODE CONT", true);
ioDmm.WriteString("*OPC", true);
//读read number of frequency points
ioDmm.WriteString("sense:sweep:points?", rst);
string s = ioDmm.ReadString().TrimEnd('n').Trim('"');
int sweepPoints = Convert.ToInt32(s);
//set binary format
ioDmm.WriteString("format:data real,64", rst);
ioDmm.WriteString("format:border swapped", rst);
//set snp format to be real and imaginary
ioDmm.WriteString("mmemory:store:trace:format:snp RI", rst);
//get current measuremnt
ioDmm.WriteString("calculate:parameter:catalog?", rst);
s = ioDmm.ReadString().TrimEnd('n').Trim('"');
string[] meas = s.Split(',');
string command = string.Format("calculate:parameter:select '{0}'", meas[0]);
ioDmm.WriteString(command, rst);
//begin to read snp data, "3,4" designate the port number of the s2p
string setIOports = "calculate:data:snp:ports? "3,4"";
ioDmm.WriteString(setIOports, rst);
FmtIoBinaryReader reader = new FmtIoBinaryReader(ioDmm);
ulong numBytes = reader.BeginRead();
int sizeOfDouble = sizeof(double);
Debug.Assert(numBytes == Convert.ToUInt64((1 + 2 * 2 * 2) * sweepPoints * sizeOfDouble));
// read frequency
{
ulong len = Convert.ToUInt64(sweepPoints * sizeOfDouble);
byte[] byteFreq = null;
reader.Read(len, out byteFreq);
double[] freq = new double[sweepPoints];
int startIndex = 0;
for (int i = 0; i < sweepPoints; ++i)
{
freq = BitConverter.ToDouble(byteFreq, startIndex);
startIndex += sizeOfDouble;
}
//save frequencies
//..... }
// read S parameter all at onece, (including S11 S21 S12 S22), sequence is S11, S21, S12, S22
sparaOut=new double [4][];
for (int i = 0; i < 4; i++)
{ sparaOut = new double[sweepPoints * 2]; }
for (int i = 0; i < 2 * 2; ++i)
{
ulong leng = Convert.ToUInt64(sweepPoints * sizeOfDouble * 2);
byte[] byteSparameter = null;
reader.Read(leng, out byteSparameter);
int points = sweepPoints * 2;

double[] sparam = new double[points];
int startIndex2 = 0;
for (int j = 0; j < points; ++j)
{
sparaOut[j] = BitConverter.ToDouble(byteSparameter, startIndex2);
startIndex2 += sizeOfDouble;
}
//save S parameter. For each parameter Sij, first half represnet real part while the second half is the imagianry part
//...
}
Console.WriteLine("Time taken in {0} ms", DateTime.Now.Subtract(startDate).TotalMilliseconds);
sparaMea = new double[3][,];
for (int i = 0; i < 3; i++)
{
sparaMea = new double[2, sweepPoints];
if (i != 2 )
{
for (int j = 0; j < sweepPoints; j++)
{
sparaMea[0, j] = sparaOut[j];
sparaMea[1, j] = sparaOut[sweepPoints + j ];
}
}
if (i == 2)
{
for (int j = 0; j < sweepPoints; j++)
{
sparaMea[0, j] = sparaOut[i+1][j];
sparaMea[1, j] = sparaOut[i+1][sweepPoints + j ];
}
}
}
reader.EndRead();
ioDmm.IO.Close();
}
}
}
}

The reason why it is so fast I think is because all the measured S parameters are flushed to the PC all at once.  
However, above code can not be applied to the ENA model E5071C. In particular, the "calculate:parameter:catalog?" is not supported by E5071C. An alternative way to specify each trace, and then  fetch the data of each trace one by one. This significantly increase the data fetching time. I'm wondering on these ENA models, is there any SCPI commands similar  to those used on PNA that enable fetching all snp all at once?

更多回帖

发帖
×
20
完善资料,
赚取积分