Creating a simple VB.NET program for AFG3021

Post Reply
cradleinflames
Posts: 1
Joined: August 12th, 2015, 10:43 am

Creating a simple VB.NET program for AFG3021

Post by cradleinflames » August 12th, 2015, 10:52 am

Hello, everyone!

I was trying to create a very basic VB.NET program to control my AFG3021 Function Generator. I found some sample code in C# posted by buck a while back (from this location: http://www1.tek.com/forum/viewtopic.php?f=6&t=1143). I converted it to VB.NET but I'm having trouble sorting out the C# equivalent of one line, specific to the declaration of the new library. Below is the C# code in the example:

Code: Select all

namespace HelloWorld
{
      class Program
      {
          static void Main(string[] args)
          {
              TvcClass my_instrument = new TVCLib.TvcClass();
              my_instrument.Descriptor = "USB::0x0699::0x0401::C021220::INSTR";
              Console.WriteLine(my_instrument.Query("*idn?"));
              my_instrument.WriteString("*rst");
              Console.WriteLine("Instrument has been reset.");
          }
      }
  }
Below is my converted VB.NET code:

Imports System
Imports TVCLib

Code: Select all

Public Class Form1

    'Help From http://www1.tek.com/forum/viewtopic.php?f=6&t=1143

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Dim my_instrument As TvcClass = New TvcClass
        Dim my_instrument As TvcClass = New TVCLib.Tvc
        my_instrument.Descriptor = "USB::0x0699::0x0340::C020026::INSTR"
        Console.WriteLine(my_instrument.Query("*idn?"))
        my_instrument.WriteString("*rst")
        Console.WriteLine("Instrument has been reset.")
    End Sub

End Class
Normally, this would be a VB.NET question but the issue I'm having is with the TvcClass declaration specifically. When I use this line:

Code: Select all

Dim my_instrument As TvcClass = New TVCLib.Tvc
I get a number of issues along the lines of "Reference to class 'TvcClass' is not allower when it's assembly is linked using No-PIA mode"

When I use this line:

Code: Select all

Dim my_instrument As TvcClass = New TvcClass
I get the error "Interop type 'TvcClass' cannot be embedded. Use the applicable interface instead"

I know this is about as basic as it gets but I'm kind of stuck at this very basic level . . . I think once I get this working, I should be good to go (since it appears it's already setup to send commands straight from the programmers manual). Any help you guys can give me would be appreciated. Thanks!

Carl M
Tektronix Applications
Tektronix Applications
Posts: 775
Joined: July 30th, 2008, 4:45 pm

Re: Creating a simple VB.NET program for AFG3021

Post by Carl M » August 13th, 2015, 7:50 pm

did you add the reference to the TekVISA ActiveX control (COM)? This cannot be done in code but in the project setup. I forget the exact menus. Cross reference visual studio help. i don't have visual studio installed at the moment. i'm also not sure how much the interface has changed.

alternatively, you can use DLLImport to call the visa functions directly (viOpen(), viWrite(), viRead(), etc.)

here is a really bad and out of context c# example i wrote a long time ago for the DSA8300 sampling scope. i'll try to post a better more generic DLLImport example later. my intent is to provide some quick help to get you off in the right direction if you choose to ditch the activex control (which i strongly recommend). the microsoft .net documentation should help you change this c# syntax into VB.NET syntax. (.net is still .net after all).

P.S. i haven't used c# for years. i've been using python pretty much exclusively. it is very well suited for test automation and scripting.
P.P.S. i don't do GUIs. i'm terrible at them and i'd rather focus on making better test algorithms.

Code: Select all

using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace myproject
{
    public partial class Form1 : Form
    {
        // functions imported are documented in TekVISA Programmer Manual
        [DllImport("visa32.dll")]
        public static extern int viOpenDefaultRM(out int sesn);
        [DllImport("visa32.dll")]
        public static extern int viFindRsrc(int sesn, string expr, out int findList, out int retCount, StringBuilder instrDesc);
        [DllImport("visa32.dll")]
        public static extern int viFindNext(int findList, StringBuilder instrDesc);
        [DllImport("visa32.dll")]
        public static extern int viGetAttribute(int vi, int attribute, out int attrState);
        [DllImport("visa32.dll")]
        public static extern int viSetAttribute(int vi, int attribute, int attrState);
        [DllImport("visa32.dll")]
        public static extern int viOpen(int sesn, string rsrcName, int accessMode, int timeout, out int vi);
        [DllImport("visa32.dll")]
        public static extern int viClose(int vi);
        [DllImport("visa32.dll")]
        public static extern int viStatusDesc(int vi, int status, StringBuilder desc);
        [DllImport("visa32.dll")]
        public static extern int viRead(int vi, byte[] buf, int count, out int retCount);
        [DllImport("visa32.dll")]
        public static extern int viWrite(int vi, byte[] buf, int count, out int retCount);

        int visa_status;
        int visa_session;
        int retCt;
        StringBuilder videsc = new StringBuilder(1024);
        int visa_connection;
        int module_to_use;
        char d_plus;
        char d_minus;
        StringBuilder deskew_message = new StringBuilder();
        double d_plus_cross, d_minus_cross;
        double t_zero, mask_start, mask_end;
        string visa_address = "gpib8::1::instr";

        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

        public Form1()
        {
            InitializeComponent();
            visa_status = viOpenDefaultRM(out visa_session);
            txtStatusBar.Text = visa_status.ToString();
            visa_status = viOpen(visa_session, visa_address, 0, 5000, out visa_connection);
            if (visa_status == 0)
            {
                write_visa("*cls");
                write_visa("head 0");
                txtIDN.Text = query_visa("*idn?");
                listModules.Items.Clear();
                listModules.Items.Add("module 1: " + query_visa("syst:prop:ch1:mode?"));
                listModules.Items.Add("module 2: " + query_visa("syst:prop:ch3:mode?"));
                listModules.Items.Add("module 3: " + query_visa("syst:prop:ch5:mode?"));
                listModules.Items.Add("module 4: " + query_visa("syst:prop:ch7:mode?"));
                listModules.Enabled = true;
                txtStatusBar.Text = "Select module to use for testing and click Next.";
            }
            else
            {
                txtStatusBar.Text = "Cannot connect to instrument.  Relaunch to try again.";
            }
            visa_status = viClose(visa_session);
        }

        private string query_visa(string query, int timeout = 5000)
        {
            byte[] t = new byte[4];
            t = BitConverter.GetBytes(timeout);
            visa_status = viSetAttribute(visa_connection, 0x3FFF001A, timeout);
            byte[] b = new byte[1024];
            b = encoding.GetBytes(query);
            visa_status = viWrite(visa_connection, b, query.Length, out retCt);
            byte[] c = new byte[1024];
            visa_status = viRead(visa_connection, c, 1024, out retCt);
            return encoding.GetString(c);
        }

        private void write_visa(string command)
        {
            byte[] b = new byte[1024];
            b = encoding.GetBytes(command);
            visa_status = viWrite(visa_connection, b, command.Length, out retCt);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            textBox2.Enabled = false;
            listBox2.Enabled = false;
            button4.Enabled = false;
            tabControl1.Enabled = false;
            // run test
            t_zero = (d_minus_cross + d_plus_cross) / 2 - 3.941e-9;
            mask_start = t_zero + 12e-9;
            mask_end = mask_start + 42e-9;
            string z_high, z_low, z_test;

            if (listBox2.SelectedIndex == 0)
            {
                // term
                z_high = "100";
                z_low = "80";
                z_test = "-Term";
            }
            else
            {
                // thru
                z_high = "110";
                z_low = "70";
                z_test = "-Thru";
            }
            txtStatusBar.Text = "Running " + z_test.Substring(1) + " test ...";
            this.Refresh();
            
            // visa coms
            visa_status = viOpenDefaultRM(out visa_session);
            visa_status = viOpen(visa_session, visa_address, 0, 5000, out visa_connection);

            write_visa("select:ch" + d_plus + " off");
            write_visa("select:ch" + d_minus + " off");

            write_visa("math1:define 'filter(c" + d_plus + "+c" + d_minus + ")'");
            write_visa("math1:filter:risetime 400e-12");
            write_visa("select:math1 on");
            write_visa("acquire:data:clear");
            query_visa("acq:state 1;*opc?", 10000);
            write_visa("math1:scale 10");
            write_visa("math1:position -9");
            write_visa("horizontal:main:refpoint 0");
            write_visa("horizontal:main:position " + t_zero.ToString("0.0##e+00") + ";scale 5e-9");
            write_visa("mask:count:state on");
            write_visa("mask:source math1");
            write_visa("mask:mask1:points " + mask_start.ToString("0.0##e+00") + "," + z_high + "," + mask_end.ToString("0.0##e+00") + "," + z_high + "," + mask_end.ToString("0.0##e+00") + ",165," + mask_start.ToString("0.0##e+00") + ",165");
            write_visa("mask:mask2:points " + mask_start.ToString("0.0##e+00") + ",0," + mask_end.ToString("0.0##e+00") + ",0," + mask_end.ToString("0.0##e+00") + "," + z_low + "," + mask_start.ToString("0.0##e+00") + ","+z_low);
            write_visa("mask:display on");
            write_visa("horizontal:main:refpoint .07");
            write_visa("horizontal:main:scale .5e-9");
            
            write_visa("acquire:data:clear");
            query_visa("acq:state 1;*opc?", 10000);

            write_visa("measurement:meas1:type maximum;source1:wfm math1");
            write_visa("measurement:meas2:type minimum;source1:wfm math1");
            write_visa("measurement:meas1:gating:state on");
            write_visa("measurement:meas1:source1:gate1:pctpos 24");
            write_visa("measurement:meas2:gating:state on");
            write_visa("measurement:meas2:source1:gate1:pctpos 24");
        }

        private int execute_deskew()
        {
            // setup deskew
            visa_status = viOpenDefaultRM(out visa_session);
            visa_status = viOpen(visa_session, visa_address, 0, 5000, out visa_connection);
            write_visa("factory");
            write_visa("header off");
            write_visa("display:showvector on");
            write_visa("acquire:mode average;numavg 16");
            write_visa("tdr:ch" + d_plus + ":preset;units ohm");
            write_visa("tdr:ch" + d_minus + ":preset;units ohm");
            write_visa("tdr:ch" + d_minus + ":step:polarity minus");
            write_visa("ch" + d_plus + ":scale 5;position -10");
            write_visa("ch" + d_minus + ":scale 5;position -10");
            write_visa("horizontal:main:scale 5e-9");
            write_visa("horizontal:main:recordlength 16e+3");

            // setup measruments
            write_visa("measurement:meas1:source1:wfm ch" + d_plus);
            write_visa("measurement:meas1:source1:wfmdb:sigtype pulse");
            write_visa("measurement:meas1:reflevel1:method absolute;absolute:mid 70");
            write_visa("measurement:meas1:source1:hilow:track:high:enable off");
            write_visa("measurement:meas1:source1:hilow:track:low:enable off");
            write_visa("measurement:meas1:source1:edge:direction backward");
            write_visa("measurement:meas1:type pcross");

            write_visa("measurement:meas2:source1:wfm ch" + d_minus);
            write_visa("measurement:meas2:source1:wfmdb:sigtype pulse");
            write_visa("measurement:meas2:reflevel1:method absolute;absolute:mid 70");
            write_visa("measurement:meas2:source1:hilow:track:high:enable off");
            write_visa("measurement:meas2:source1:hilow:track:low:enable off");
            write_visa("measurement:meas2:source1:edge:direction backward");
            write_visa("measurement:meas2:type pcross");

            write_visa("measurement:annotations:state on");

            write_visa("acq:stopa:mod cond");
            write_visa("acq:stopa:cond avgc");
            write_visa("acquire:data:clear");
            query_visa("acq:state 1;*opc?", 10000);

            d_plus_cross = Convert.ToDouble(query_visa("measurement:meas1:value?", 10000));
            d_minus_cross = Convert.ToDouble(query_visa("measurement:meas2:value?", 10000));

            // check for reasonable measruments
            if ((d_plus_cross > 1) || (d_minus_cross > 1))
            {
                visa_status = viClose(visa_session);
                txtStatusBar.Text = "error: cannot deskew";
                MessageBox.Show("Automatic deskew failed.  Invalid measrument value.  Long cables?");
                return 1;
            }

            // tdr deskew cannot account for more than 500 ps.
            double k;
            k = Math.Abs(d_plus_cross - d_minus_cross);
            if (k > 500e-12)
            {
                visa_status = viClose(visa_session);
                txtStatusBar.Text = "error: cannot deskew";
                MessageBox.Show("Automatic deskew failed.  Larger skew then expected.  Mismatched cables?");
                return 1;
            }

            // adjust horizontal for improved accuracy
            write_visa("horizontal:main:scale 100e-12");
            if (d_plus_cross > d_minus_cross)
                write_visa("horizontal:main:position " + (d_minus_cross - 0.5e-9).ToString("0.0##e+00"));
            else
                write_visa("horizontal:main:position " + (d_plus_cross - 0.5e-9).ToString("0.0##e+00"));

            write_visa("acquire:data:clear");
            query_visa("acq:state 1;*opc?", 10000);

            // adjust deskew
            double d;
            d = Convert.ToDouble(query_visa("tdr:ch" + d_minus + ":step:deskew?"));
            k = Math.Abs(d_plus_cross - d_minus_cross);
            while (k > 0.010e-9)
            {
                if (d_plus_cross > d_minus_cross)
                    d += 5;
                else
                    d -= 5;
                write_visa("tdr:ch" + d_minus + ":step:deskew " + d.ToString("0.0000"));
                write_visa("acquire:data:clear");
                query_visa("acq:state 1;*opc?", 10000);
                d_plus_cross = Convert.ToDouble(query_visa("measurement:meas1:value?", 10000));
                d_minus_cross = Convert.ToDouble(query_visa("measurement:meas2:value?", 10000));
                k = Math.Abs(d_plus_cross - d_minus_cross);

                // check for reasonable measruments
                if ((d_plus_cross > 1) || (d_minus_cross > 1))
                {
                    visa_status = viClose(visa_session);
                    txtStatusBar.Text = "error: cannot deskew";
                    MessageBox.Show("Automatic deskew failed.  Invalid measrument value.  Long cables?");
                    return 1;
                }

                // tdr deskew cannot account for more than 500 ps.
                if (k > 500e-12)
                {
                    visa_status = viClose(visa_session);
                    txtStatusBar.Text = "error: cannot deskew";
                    MessageBox.Show("Automatic deskew failed.  Larger skew then expected.  Mismatched cables?");
                    return 1;
                }
            }
            visa_status = viClose(visa_session);
            textBox3.Text = k.ToString("0.0##e+00");
            numericUpDown1.Value = Convert.ToDecimal(d);
            return 0;
        }
    }
}
Tektronix Application Engineer

Post Reply

Return to “AFG1000/2000/3000 series”

Who is online

Users browsing this forum: No registered users and 1 guest