C#, SCPI and Keysight (Agilent) DSO-X 2002A

And my first take on C#


            

This post is a relic. The initial draft dates back in January 19, 2013. And was left as draft ever since. Past couple of days I was busy — among other things — learning a new programming language, C#. 🙂

Ok, here’s the deal: my scope (KeysightAgilent DSO-X 2002A) is SCPI–compliant device. If you remember, the reason behind this OS X driver project was an attempt to control my KeysightAgilent DSO-X 2002A scope from my MacBook. Unfortunately, KeysightAgilent does not provide SCPI libraries for Mac, neither do they provide any OS X drivers, although they have SCPI/ VISA libraries for Windows (IO Libraries Suite) and a nice app for Windows, named Command Expert; the app can be used to control the instrument.

SCPI stands for Standard Commands for Programmable Instruments. This defines a standard for syntax and commands to use in controlling programmable test and measurement devices. Basically, it is a set of standardised command set that anyone can implement to automate control of measurement instruments like multimeters, oscilloscopes etc. SCPI is pure software standard. SCPI syntax is ASCII text, and therefore can be attached to any computer test language, such as BASIC, C, or C++. For example, this is the scope setup method I wrote in my program (C#):

/**
* Sets the scope parameters
* */
public void scopeSetup()
{
    string strResults;
    double fResult;

    // set labels
    myDSOX.myScope.Transport.Command.Invoke(":DISPlay:LABel ON");
    myDSOX.myScope.SCPI.CHANnel.LABel.Command(1, "Meas.Ch.");
    myDSOX.myScope.SCPI.CHANnel.LABel.Command(2, "Ref.Ch.");

    // set scope trigger mode
    myDSOX.myScope.SCPI.TRIGger.MODE.Command("EDGE");
    myDSOX.myScope.SCPI.TRIGger.MODE.Query(out strResults);
    Console.WriteLine("Trigger Mode: {0}", strResults);

    // set EDGE trigger source; channel 1 --> yellow; channel 2 --> green
    myDSOX.myScope.SCPI.TRIGger.EDGE.SOURce.Command("CHANnel2");
    myDSOX.myScope.SCPI.TRIGger.EDGE.SOURce.Query(out strResults);
    Console.WriteLine("Trigger edge source: {0}", strResults);

    // set EDGE trigger level
    myDSOX.myScope.SCPI.TRIGger.EDGE.LEVel.Command(1.5, "CHANnel2");
    myDSOX.myScope.SCPI.TRIGger.EDGE.LEVel.Query("CHANnel2", out fResult);
    Console.WriteLine("Trigger edge level: {0:F2}", fResult);

    // set EDGE trigger slope type
    myDSOX.myScope.SCPI.TRIGger.EDGE.SLOPe.Command("POSitive");
    myDSOX.myScope.SCPI.TRIGger.EDGE.SLOPe.Query(out strResults);
    Console.WriteLine("Trigger edge slope: {0}", strResults);

    // set acquisition type
    myDSOX.myScope.SCPI.ACQuire.TYPE.Command("AVERage");
    myDSOX.myScope.SCPI.ACQuire.COUNt.Command(8);
    myDSOX.myScope.SCPI.ACQuire.TYPE.Query(out strResults);
    Console.WriteLine("Acquire mode: {0}", strResults);

    // save scope configuration
    string[] strScopeConfigurationArray;
    myDSOX.myScope.SCPI.SYSTem.SETup.Query(out strScopeConfigurationArray);
}// end private static scopeSetup()

SCPI can also be used with Test Application Environments such as LabWindows/CVI, LabVIEW, MATLAB, Microsoft Visual Studio, or Agilent VEE. SCPI is hardware-independent. SCPI strings can be sent over any instrument interface. It works equally well over GPIB, RS-232, VXIbus or LAN networks. More informations in the links under further reading section (below).

Since the OS X driver is still on my drawing board (did not have time to complete the libraries part), I decided it is a very good opportunity to give C# a try. Yes C# as for Microsoft C# stuff. And — starting from scratch and for just / less two days of work — I dare say I have managed to impress myself:

My C# SCPI prototype application — used to control my Agilent scope. So far so good.

My C# SCPI prototype application — used to control my Agilent scope. So far so good.
Click on image for a larger and better view.

Considering the fact that is my FIRST C# attempt with a total of 12 hours of work on the project (during evenings, after my daily job chores), I think I managed pretty well. And, honestly, I understand now why so many rave about C#. It is ideal to quickly create working, simple, useful, visual apps. What this application does is to connect to the Agilent scope, set up the device (with some predefined parameters) and perform some measurements, at a touch of a software button. Results are stored in a volatile collection and displayed in a line chart. The scope setup is pictured in the image below:

My Agilent setup for SCPI tests. Unfortunately I have no 50Ω termination on the inputs so the values are not correct, but they do for programming purposes. The 10 μH inductor can be clearly seen in the middle of the image, in the small home brew adapter. My new 12" (30cm) Pomona cable can also be seen in the pic.

My Agilent setup for SCPI tests. Unfortunately I have no 50Ω termination on the inputs so the values are not correct, but they do for programming purposes. The 10 μH inductor can be clearly seen in the middle of the image, in the small home brew adapter. My new 12″ (30cm) Pomona cable can also be seen in the pic.
Click on image for a larger and better view.

Unfortunately one [major] shortcoming of the KeysightAgilent DSO-X 2002A — which, I believe, is true for the entire 2000–series — is the fact that the scope input are high–Z, which makes mandatory the use of 50Ω cable terminators. However, for programming purposes, it does not matter too much. For example, this is how a frequency sweep from 1 MHz to 20 MHz looks like for voltages measured across 10 μH inductor:

Plot of voltage drop across 10μH inductor during a frequency sweep from 1 MHz to 20 MHz, 1 V<sub>pp</sub>. Normal acquire mode. Notice the resonant value of the equivalent R-L Series circuit. The line is jagged due to high–resolution acquire.

Plot of voltage drop across 10μH inductor during a frequency sweep from 1 MHz to 20 MHz, 1 Vpp. Normal acquire mode. Notice the resonant value of the equivalent R-L Series circuit. The line is jagged due to high–resolution acquire. Click on image for a larger and better view.

The Chart class is superb. I wish Apple could do something like this. I mean, aside of all those bells and whistles and so on damn, Apple, is it so difficult to enhance XCode with a chart object ? Or possibly with a serial connection object ? Or, even sexier, with an USB connection object ? I mean, how difficult is to allow us, poor developers, to use a predefined class with a simple isLogarithmic boolean property (for example) that automatically sets a NSView–based chart as it suggests ? Yeah, yeah, I know, we can do it. You provide developers with flexibility. But stilll, sometimes I prefer a bit more rigid approach…

Plot of voltage drop across 10μH inductor during a frequency sweep from 1 MHz to 20 MHz, 1 V<sub>pp</sub>. Averaged, 8 cycles, acquire mode. Notice the line looks smoother than in the previous chart, due to average acquire mode.

Plot of voltage drop across 10μH inductor during a frequency sweep from 1 MHz to 20 MHz, 1 Vpp. Averaged, 8 cycles, acquire mode. Notice the line looks smoother than in the previous chart, due to average acquire mode.
Click on image for a larger and better view.

What I am trying to achieve is to increase my instrumentation capabilities draining the last drop of functionality from my KeysightAgilent scope. For example, I want to leverage the availability and usefulness of the embedded wave generator which is able to go up to 20 MHz and can provide AM, FM, phase and FSK modulation. Basically, the scope does not have a sweep function, but this can be easily achieved via SCPI integration and C# coding. For example, considering three variables: a frequency for sweep start (lowFrequency), a frequency for end sweep (highFrequency) and a frequency increment step (stepFrequency), the C# routine could be:

int i = 0;
while (lowFrequency <= highFrequency)
{
    Thread.Sleep(100);
    // set start sweep frequency to low freq value
    freqSweep.startSweep(lowFrequency);
    // add each measured point to the collection
    listDataSource.Add(new Record(i, lowFrequency, freqSweep.measureResults(channel)));
    // end adding data
    lowFrequency += stepFrequency;
    // report progress if needed
    //bw.ReportProgress(i);
    ++i;
}

where the freqSweep.measureResults(channel) is the method that actually does the measurement, on scope channel, channel; the method is implemented inside the class freqSweep; the actual measurement and variable assignment are performed on highlighted lines:

/**
 * Perform the measurement on specified scope channel
 */
public double measureResults(string channel)
{
    double fResult;
    myDSOX.myScope.SCPI.MEASure.SOURce.Command(channel, null);
    myDSOX.myScope.SCPI.MEASure.VAMPlitude.Query(channel, out fResult);
    Console.WriteLine("Amplitude : {0:F4}", fResult);
    if (fResult > 1000)
        return 0.0;
    else
        return fResult;
}// end public double measureResults

Ok, that’s it for today. There is a tremendous amount of improvement for this small project, from my point of view notwithstanding the results are impressive. I was able to create a fully-functional app in less than two days, starting from scratch. True, the very abrupt learning curve is probably due to my prior programming knowledge. Nevertheless. I might fall in love with this C# so more to come on the topic. Hm… Microsoft, mon amour ? 😀

Further reading

  • SCPI on Wikipedia; a good place to start. SCPI overview, some background, rationale, command syntax (high–level topics), arguments, abbreviations; not too in–depth, but enough for starters;
  • SCPI Consortium; included in the IVI Foundation website; SCPI Consortium was engulfed by IVI Foundation in 2002 and finally merged with in 2003; IVI Foundation is now the official responsible for SCPI specification.
  • National Instruments’ LabWindows/CVI;
  • LabView, MATLAB
  • MS Visual Studio
  • KeysightAgilent VEE
  • Open Source SCPI device library/ SCPI parser library — Not sure what is this useful for; nightmarish C–oriented framework; to be explored and — possibly — exploited 😉

About KeysightAgilent libraries for VISA (Virtual Instrument Software Architecture) and SCPI: Starting with IO Libraries Suite 15.5, all of the KeysightAgilent I/O Libraries are available for use in both 32-bit and 64-bit systems. You can find specific information on how to use the libraries on 64-bit systems by searching the IO Libraries Suite 15.5 Help file for the topic “64-bit”. Available information:

 

Rigol Spectrum Analyzer !

I’ve kept drooling for this for several years. Today I finally got it ! Moreover, it seems it is fully-option enabled, which is kinda weird because I haven’t ordered for such. However, here it is: the Rigol DSA 815 TG Spectrum Analyzer with tracking generator. This will enhance my lab’s capabilities in RF electronics and […]

__attribute__((packed))

The keyword __attribute__ allows you to specify special attributes of struct and union types when you define such types. This is mostly encountered when designing code with particular care on memory footprint optimisation.  I have encountered this several times in some Apple headers while digging for documentation for my kext projects, and I thought it […]

2 responses to “C#, SCPI and Keysight (Agilent) DSO-X 2002A”

  1. Mark Farver says:

    Your class interface is interesting. Do you have any code snippets to post?

    • AP says:

      Hi, Mark. Thanks for your comment and appreciation. I am not quite sure what snippets are you talking about. 🙂 Could you, please, let me know ?
      Regards,
      AP

Leave a Reply

Your email address will not be published. Required fields are marked *