Tektronix Technical Forums are maintained by community involvement. Feel free to post questions or respond to questions by other members. Should you require a time-sensitive answer, please contact your local Tektronix support center here.

C# Example: using TekVISANet.dll

Questions in this forum area are community supported. Tektronix does not regularly monitor posts in this area.
Post Reply
Chris B
Tektronix Applications
Tektronix Applications
Posts: 657
Joined: December 17th, 2010, 3:17 pm

C# Example: using TekVISANet.dll

Post by Chris B » November 15th, 2012, 12:59 pm

TekVISANet.dll is installed when you install TekVISA, and can be found in the path C:\Windows\assembly (then to either GAC_32 or GAC_64, one more sub folder, then you will see the .dll).
The following example uses this DLL (note: my labtop actually run NI VISA, not TekVISA, but this still works) to do some basic functions often used in scripting:

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Collections.ArrayList instrlist;
            int j;
            float ymult, yzero, yoff, xincr, timepoint;
            string response;
            bool status;
            TekVISANet.VISA TVA = new TekVISANet.VISA();
            
            // Print list of VISA resources
            TVA.FindResources("?*", out instrlist);
            Console.WriteLine("Visa Resources");
            for (j = 0; j < instrlist.Count; j++)
            {
                Console.WriteLine(j.ToString() + " : " + instrlist[j]);
            }
            Console.WriteLine("\n");
            
            // Connect to a known instrument and print its IDN
            TVA.Open("USB0::0x0699::0x0425::CQ010017::INSTR");
            TVA.Write("*IDN?");
            status = TVA.Read(out response);
            if (status)
            {
                Console.WriteLine(response);
            }

            // Get curve data for channel 1, and scale to volts.
            byte[] rawwave;
            float[] wave;
            TVA.Write("DATA:SOU CH1");
            TVA.Write("DATA:WIDTH 1");
            TVA.Write("DATA:ENC RPB");
            TVA.Query("WFMPRE:YMULT?", out response);
            ymult = float.Parse(response);
            TVA.Query("WFMPRE:YZERO?", out response);
            yzero = float.Parse(response);
            TVA.Query("WFMPRE:YOFF?", out response);
            yoff = float.Parse(response);
            TVA.Query("WFMPRE:XINCR?", out response);
            xincr = float.Parse(response);

            TVA.Write("CURVE?");
            TVA.ReadBinary(out rawwave);
            Console.WriteLine("Number of Points " + rawwave.Count());
            Console.WriteLine(rawwave[0].ToString());
            Console.WriteLine(rawwave[1].ToString());
            wave = new float[rawwave.Count()];
            for (j = 0; j < rawwave.Count(); j++)
            {
                wave[j] = (rawwave[j] - yoff) * ymult + yzero;
            
            }

            //print the first 100 scaled waveform values to the screen 
            for (j=0; j < 100; j++)
            {
                Console.Write(wave[j].ToString() + ",");
            }

            
            //write waveform to a csv file
            System.IO.StreamWriter file = new System.IO.StreamWriter("test.csv");
            file.WriteLine("V,S");
            for (j = 0; j < wave.Count(); j++)
            {
                timepoint = j * xincr;
                file.WriteLine(wave[j].ToString() + "," + timepoint.ToString());
            }
            file.Close();


            Console.WriteLine("\nPress Enter to exit");
            Console.ReadLine();
            TVA.Close();

        }
    }
}
One issue I have run into is with trying to get a screen capture. The image data is written into a string variable, but seems to get mangled when I write it to a file.

akinola.falola
Posts: 1
Joined: January 24th, 2014, 7:06 am

Re: C# Example: using TekVISANet.dll

Post by akinola.falola » January 24th, 2014, 7:22 am

HI, thanks for this post. I was able to successfully used your code to get waveform from our DPO2012B but we recently try to deploy a second system and bought a new DPO2012B scope and everything works up excepts the lines below which times out no matter what timeout value I use:

TVA.Query("WFMPRE:YMULT?", out response);
ymult = float.Parse(response);
TVA.Query("WFMPRE:YZERO?", out response);
yzero = float.Parse(response);
TVA.Query("WFMPRE:YOFF?", out response);
yoff = float.Parse(response);
TVA.Query("WFMPRE:XINCR?", out response);
xincr = float.Parse(response);

TVA.Write("CURVE?");
TVA.ReadBinary(out rawwave);

After much troubleshooting (which included replacing TekVisa with NI VISA), I manage to replace the first 8 lines with (scope is a NI VISA session):

double xincr = double.Parse(scope.Query("WFMInpre:XINcr?"));
double ymult = double.Parse(scope.Query("WFMInpre:YMUlt?"));
double yoff = double.Parse(scope.Query("WFMInpre:YOFF?"));
double yzero = double.Parse(scope.Query("WFMInpre:YZERO?"));

But I still can't any way to make the CURVE? and ReadBinary (or ReadByteArray() for NI VISA) works. Using the WAVFRM? command only return the waveform header file. It is funny because the old oscilloscope (bought in June-2013) was working but unfortunately the system is now deployed outside the country and my code is still able to read the spectrum but this new one (bought Nov-2013) has never responded to the CURVE? query even from NI MAX. My question is why is the same model of oscilloscope not responding to the same sets of commands? and what is the "new way" to get the CURVE from DPO2012B.

Chris B
Tektronix Applications
Tektronix Applications
Posts: 657
Joined: December 17th, 2010, 3:17 pm

Re: C# Example: using TekVISANet.dll

Post by Chris B » January 29th, 2014, 6:26 am

The DPO2000 series scopes have a few things that need to be set, which no other scope has.
Make sure your Data Composition is set correctly 'DATA:COMP COMPOSITE_YT'
You may also want to check out the DATA:RESOlution command to see if it is full or reduced.
I don't know if either of these would lock up the curve query using the TekVISANet.dll, but it is possible.

dag99
Posts: 23
Joined: March 5th, 2009, 5:27 am

Re: C# Example: using TekVISANet.dll

Post by dag99 » July 8th, 2014, 3:24 am

Ive downloaded the latest TEKVISA verson from the Tektronix website.
Any known issues with using TekVISANet.dll be with the TBS1052B scope?
Also are their any limitations to this DLL as regards setting parameters and reading waveforms? TIA

dag99
Posts: 23
Joined: March 5th, 2009, 5:27 am

Re: C# Example: using TekVISANet.dll

Post by dag99 » July 8th, 2014, 4:01 am

Sorry I should have asked the following question in my previous post;

Where do I find a list of the strings for each setting ie. "WFMPRE:YMULT?"

Ive searched the TekVisa Programmers Manual and also the Reference manual but cannot find anything.

David N
Tektronix Applications
Tektronix Applications
Posts: 558
Joined: July 31st, 2008, 8:26 am

Re: C# Example: using TekVISANet.dll

Post by David N » July 8th, 2014, 2:05 pm

The programmers manual for the TBS1052B is on Tek.com under the "Downloads, Manuals & Documentation" link under the "Support" tab. A direct url is currently: http://www.tek.com/search/apachesolr_se ... tid%3A1012. Descriptions, settings, etc are listed for each commnand.

dag99
Posts: 23
Joined: March 5th, 2009, 5:27 am

Re: C# Example: using TekVISANet.dll

Post by dag99 » July 9th, 2014, 1:05 am

Great, thanks very much.

dag99
Posts: 23
Joined: March 5th, 2009, 5:27 am

Re: C# Example: using TekVISANet.dll

Post by dag99 » July 15th, 2014, 9:31 am

From the first post in this thread;

TVA.Open("USB0::0x0699::0x0425::CQ010017::INSTR");
TVA.Write("*IDN?");
status = TVA.Read(out response);


Does anyone know under what circumstances the line

TVA.Write("*IDN?");

returns false??

ie.

bool result = TVA.Write("*IDN?");

and result is false. That's what I am getting quite often.

dag99
Posts: 23
Joined: March 5th, 2009, 5:27 am

Re: C# Example: using TekVISANet.dll

Post by dag99 » July 16th, 2014, 7:16 am

To describe briefly what I am doing. I am developing a Visual C#.Net application in Visual Studio 2008. I am using the TekVISANet dll

I define the oscilloscope object thus.

TekVISANet.VISA theScope = new TekVISANet.VISA();

The application itself is quite simple. It consists of a single window that lets the user connect and disconnect to the scope.
Then the user can set the scale per division (vertical axis) and the TimeBase (horizontal axis) and click an OK button to send these settings to the scope.
Then there is a GetWaveform button that reads the waveform on the scope and display it in a new window. The user should be able to repeatedly click this button and display as many waveforms as he/she wants. This is where I am having a problem. The 1st time the user clicks the button I retrieve the data and display the waveform ok.
However when the user clicks the button again I cannot talk to the scope at all. ie. get any data out or even send any data.

The actual code that reads the waveform from the scope is very simple and shown below. (Also attached is the Connect() code which connects to the scope).
For completeness Ive also attached the code to set the scope settings. However this code works fine and is not causing any problem.

The getWaveform2() code fails at this line;

bool res = theScope.Write("CURVE?");

only when it is called a 2nd time. So the question is what do I need to reset in some way after/before "theScope.Write("CURVE?");"

One workaround I have discovered is that I call Connect() then getWaveform2(..) to get my 1st waveform then do Connect() again and getWaveform2(..) to get the 2nd waveform. This is obviously not a good solution since it is time consuming and is not really practical. The question is how do I call "theScope.Write("CURVE?")" multiple times without having to call my Connect()code every time?

Code: Select all

public bool getWaveForm2(ref double[] x, ref int[] y, string voltsUnits, string timeUnits)
{

     bool res = theScope.Write("CURVE?");           
     byte[] rawwave = null;
     if (res)
     {
              res = theScope.ReadBinary(out rawwave);
              y = new int[rawwave.Length];
              x = new double[rawwave.Length];
              for (int j = 0; j < rawwave.Length; j++)
               {
                    // convert raw data to volts
                    float t = rawwave[j];
                    t = (t - yoff) * ymult + yzero;

                    if (voltsUnits == "mV")
                        y[j] = Convert.ToInt32(t * 1000);
                    if (voltsUnits == "uV")
                        y[j] = Convert.ToInt32(t * 10000000);

                    // create x-axis
                    if (timeUnits == "S")
                         x[j] = Math.Round((j * xincr), 10);
                    if (timeUnits == "mS")
                        x[j] = Math.Round((j * xincr * 1000.0), 10);
                    if (timeUnits == "uS")
                        x[j] = Math.Round((j * xincr * 1000000.0), 10);
                }
     }
     else
         res = false;
     
     return(res);
 }

The code that connects to the scope is shown below

Code: Select all

public string Connect()
        {  
            try
            {
                if (getDetectedDeviceStrings() != null)
                {
                    theScope.Clear();
                    // Connect to a known instrument and print its IDN
                    bool res = theScope.Open(theDevices[0].ToString());

                    if(res)
                    {
                       res = theScope.Write("*RST");
                       res = theScope.Query("*IDN?", out response);
                       if (res)
                       {
                          // res = theScope.Read(out response);
                           if (res)
                           {
                               res = theScope.Write("TRIG:MAIN:EDGE:SOURCE EXT");

                               res = theScope.Write("HEADER OFF");
                               res = theScope.Write("DATA:SOU CH1");   // sets source to channel 1
                               res = theScope.Write("DATA:WIDTH 1");   // set byte width of waveform points to 1 byte
                               res = theScope.Write("DATA:ENC RPB");   // set waveform encoding method to RPB (what is RPB?). Ignored when byte width is set to 1

                               Connected = true;
                           }
                       }
                    }
                    if (!res)
                    {
                        response = "";
                        Connected = false;
                    }
                }
                else
                    Connected = false;
            }
            catch (Exception) { Connected = false; }

            return (response);
        }

Code: Select all

public string[] getDetectedDeviceStrings()
        {
            string[] theDeviceNames = null;
            string data = "";
            try
            {
                theScope.FindResources("?*", out theDevices);
            }
            catch (Exception) { }

            if (theDevices != null)
            {
                theDeviceNames = new string[theDevices.Count];

                int j = 0;
                while (j < theDevices.Count)
                {
                    data = data + " : " + theDevices[j].ToString();
                    theDeviceNames[j] = theDevices[j].ToString();
                    j++;
                }
            }
            return (theDeviceNames);
        }

For completeness the code to set the scope settings. This code also retrieves values required to convert the scope data to a voltage.

Code: Select all

public int setScopeSettings(double ScalePerDivInVolts, double TimeBasePerDivInSeconds, double DCOffsetInVolts, double VerticalOffsetInVolts, double TriggerDelayInSeconds, int NumberOfAverages )
        {
            int result = 0;

            try
            {
                bool res = true;

                if (res)
                {
                   
                    string data = "CH1:VOLTS " + ScalePerDivInVolts.ToString();
                    theScope.Write(data);

                    data = "HOR:MAIN:SCALE " + TimeBasePerDivInSeconds.ToString();
                    theScope.Write(data);

                    if (NumberOfAverages > 1)
                    {
                        theScope.Write("ACQ:MODE SAMPLE");   
                        data = "ACQ:NUMAV " + NumberOfAverages.ToString();
                        theScope.Write(data);
                    }

                    // get some data necessary for creating the plot
                    try
                    {
                        theScope.Query("WFMPRE:YMULT?", out response);   // get vertical scale factor
                        ymult = float.Parse(response);
                    }
                    catch (Exception) { ymult = 1; result = -20; }

                    try
                    {
                        theScope.Query("WFMPRE:YZERO?", out response);   // get waveform conversion factor
                        yzero = float.Parse(response);
                    }
                    catch (Exception) { yzero = 0; result = -21; }

                    try
                    {
                        theScope.Query("WFMPRE:YOFF?", out response);    // get the vertical position
                        yoff = float.Parse(response);
                    }
                    catch (Exception) { yoff = 0; result = -22; }

                    try
                    {
                        theScope.Query("WFMPRE:XINCR?", out response);   // get the horizontal sampling interval
                        xincr = float.Parse(response);
                    }
                    catch (Exception) { xincr = 1; result = -23; }
                }
                else result = -1;
            }
            catch (Exception) { result = -99; }

            return (result);
        }

dag99
Posts: 23
Joined: March 5th, 2009, 5:27 am

Re: C# Example: using TekVISANet.dll

Post by dag99 » July 17th, 2014, 3:09 am

theScope.Clear();

This solves it!

Im not sure exactly what clear() does and when you need to call it though.

deltekkie
Posts: 5
Joined: February 17th, 2015, 6:51 am

Re: C# Example: using TekVISANet.dll

Post by deltekkie » February 19th, 2015, 7:59 am

Hello,
I created a C# windows form app which is based off of your code. Thank you for posting this. It was very helpful. I do have one issue that keeps occuring though. I have set it up to read channel one and/or channel two. About 70% of the time my comms to the scope seem to die when it is trying to read the data back. It happens when it is trying to parse the data to write to a file. Sometimes it fails on channel one and sometimes it doesn't fail till it reads channel two. Is there a problem with timing that I am unaware of?

Thank you.

pmoll
Posts: 2
Joined: August 21st, 2015, 7:29 am

Re: C# Example: using TekVISANet.dll

Post by pmoll » August 21st, 2015, 7:49 am

If you run this example or a more simplified version of this example. After running and then closing program (the first run works fine), the second time you run the program gets caught up on TVA.Open(). I have messed around with the code a little and realized it is because of the TVA.ReadBinary(out rawwave); call. Without that call the program can run and close as many times as it wants without getting locked up. Any reason this would be happening. I am using MDO3012 Oscilloscope

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            float ymult, yzero, yoff, xincr;
            string response;
            TekVISANet.VISA TVA = new TekVISANet.VISA();            
            
            // Connect to a known instrument and print its IDN
            TVA.Open("USB0::0x0699::0x0425::CQ010017::INSTR");            

            // Get curve data for channel 1, and scale to volts.
            byte[] rawwave;
            TVA.Write("DATA:SOU CH1");
            TVA.Write("DATA:WIDTH 1");
            TVA.Write("DATA:ENC RPB");
            TVA.Query("WFMPRE:YMULT?", out response);
            ymult = float.Parse(response);
            TVA.Query("WFMPRE:YZERO?", out response);
            yzero = float.Parse(response);
            TVA.Query("WFMPRE:YOFF?", out response);
            yoff = float.Parse(response);
            TVA.Query("WFMPRE:XINCR?", out response);
            xincr = float.Parse(response);

            TVA.Write("CURVE?");
            TVA.ReadBinary(out rawwave); //If excluded code runs fine after second run
            
            TVA.Close();
            Console.WriteLine("\nPress Enter to exit");
            Console.ReadLine();
        }
    }
}
I read the forum post explanation and it said not to put questions in other posts. Sorry if this is not what I am supposed to do, but I thought because it was directly related to the example of the original post this is the place to put it.

flodis
Posts: 1
Joined: January 18th, 2016, 12:55 am

Re: C# Example: using TekVISANet.dll

Post by flodis » January 18th, 2016, 1:26 am

Regarding the simple example can not run multiple times.

It is like the instrument is in some state so even if you reboot your application it will still not work. If you disconnect the USB and reconnect it recovers from the "bad" state.

Calling TVA.Clear() after TVA open has no effekt.



I found a rerun works fine if you call Clear() before Close() at the end so better included it in the "try, catch, finally" or even better wrap the VISANet in an IDisposable class where it is allways handled.

This works great:

Code: Select all

            
  if (TVA!=null)
            {

                TVA.Clear();
                TVA.Close();
            }

Also there is not much said abou locating the TekVISANet.dll to be used in your code. I simply right clicked Visual Studio Project - References folder and browsed for it in folder "C:\Windows\assembly\GAC_32\TekVISANet\" or "C:\Windows\assembly\GAC_64\TekVISANet\" dependning on if you compile for 32 or 64-bit version.

Also included the library at the top of the code:

Code: Select all

using System.Globalization;
using TekVISANet;
And by the way if you use "," instead of "." for decimals you can parse to float adding "CultureInfo.InvariantCulture" (eg. US/EN):

Code: Select all

            ..
            TVA.Query("WFMPRE:YMULT?", out response);
            ymult = float.Parse(response, CultureInfo.InvariantCulture);
            ..

:)

asglay
Posts: 1
Joined: May 31st, 2017, 11:41 pm
Country: Taiwan

Re: C# Example: using TekVISANet.dll

Post by asglay » June 5th, 2017, 2:42 am

Thanks for the sharing. I found this post indeed helpful to me when I'm trying to use TekVISANet.dll to build up my c# project and control the scope remotely.

As to the screen capture got mangled, I came across the same problem.
It confused me couple days and I figured that the captured image got mangled due to the discard of TAB(0x09), \n(0x0A) and \r(0x0D).
The function VISA.Read(), provided by TekVISANet.dll,
automatically transfers the characters that reads from the buffer and discards the characters mentioned above.
Therefore, it is not possible to recover the captured images from scope once they contain these three characters.

I got this problem solved by introducing the viRead() provided by Visa32.dll.
This function returns raw characters and discards nothing.

By using this dll in an x64 platform, you have to switch your target platform to "x64" when building.

These are the namespaces need to be introduced.

Code: Select all

using System.IO;
using System.Collections;
using TekVISANet;
using System.Runtime.InteropServices;
Here I wrap it up for the convenience to use.

Code: Select all

class VISA32
        {
            [DllImport("C:\\Program Files\\IVI Foundation\\VISA\\Win64\\TekVISA\\Bin\\Visa32.dll")]
            public static extern Int32 viRead(UInt32 vi, byte[] buf, UInt32 cnt, IntPtr retCnt);
        }
        

Code: Select all

public class VISA_ext : VISA
        {
            // Read raw data from scope buffer and store in byte array
            public bool Read_raw(out byte[] OutputByteArray)
            {
                // Initialize Output byte array with zero element
                OutputByteArray = new byte[0];

                // Huge buffer size is used to read the data in the buffer of the scope
                Int32 status_Int32;
                byte[] InBuf = new byte[10000000];
                IntPtr retCnt_Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)));

                status_Int32 = VISA32.viRead(Session, InBuf, 10000000, retCnt_Ptr);

                // Exception handling for status_Int32 < 0 (ViRead gets nothing from the scope)
                if (status_Int32 >= 0)
                {
                    // Cut out the non-used part of the buffer
                    Int32 OutBuf_sz = Marshal.ReadInt32(retCnt_Ptr);
                    OutputByteArray = new byte[OutBuf_sz];

                    Buffer.BlockCopy(InBuf, 0, OutputByteArray, 0, OutBuf_sz);
                }
                Marshal.FreeHGlobal(retCnt_Ptr);

                // Convert the status from int to bool
                if (status_Int32 < 0)
                    return false;
                else
                    return true;
            }
        }
        
In your main method, you may use the following codes to apply the screen capture
These sample codes follow the example using pyVISA(python package)

Code: Select all

const string visaResourceAddr = "TCPIP::192.168.1.10::INSTR";
            const string fileSaveLocation = "C:\\Temp\\";

            VISA_ext scope = new VISA_ext();
            scope.Open(visaResourceAddr);
            
            scope.Write("*IDN?");

            bool status = false;
            string response;
            status = scope.Read_raw(out response);
            if (status)
                MessageBox.Show(string.Format("Device information: {0}", response));

            // Select the image output port and export file type
            scope.Write("HARDCopy:PORT FILE;");
            scope.Write("EXPort:FORMat PNG");

            // Set where the file will be saved on the scope's hard drive.  This is not
            // where it will be saved on your PC.
            scope.Write("HARDCopy:FILEName \"C:\\Temp1.png\"");
            scope.Write("HARDCopy STARt");
        
            // Read the image file from the scope's hard drive
            scope.Write("FILESystem:READFile \"C:\\Temp1.png\"");

            // Save the transferred image file to the hard drive of your PC
            byte[] ImgBuf;
            status = scope.Read_raw(out ImgBuf);
            if (status)
            {
                string filename = DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss");
                Directory.CreateDirectory(fileSaveLocation); // Requires System.IO
                File.WriteAllBytes(fileSaveLocation + filename + ".png", ImgBuf); // Requires System.IO
                MessageBox.Show("Save image at: " + fileSaveLocation + filename + ".png");
            }

            scope.Close();
            

Sam_SB
Posts: 4
Joined: August 13th, 2020, 1:17 pm
Country: Switzerland

Re: C# Example: using TekVISANet.dll

Post by Sam_SB » August 21st, 2020, 6:37 am

Hello,

I tried your code on VS2019 and with my scope MSO5204B. However, when I execute the code I have the following error message "string format was in a incorrect format": It appears on the following line:

ymult = float.Parse(response);

Could you please help me debugging ?

Thanks in advance
Sam

Post Reply

Return to “Other or Discontinued Oscilloscopes”

Who is online

Users browsing this forum: No registered users and 1 guest