Author Topic: 3458A GPIB-Readout nonblocking  (Read 2963 times)

0 Members and 1 Guest are viewing this topic.

Offline Echo88Topic starter

  • Frequent Contributor
  • **
  • Posts: 826
  • Country: de
3458A GPIB-Readout nonblocking
« on: August 26, 2018, 07:12:54 pm »
Hi,

maybe someone here has a working code snippet for Python which does the data readout, but allows other code execution without waiting (4s for 1 sample at 100NPLC) by using maybe STB or SPOLL? As far as ive tried i never get the data ready-bit set. 

Thanks.
 

Offline TiN

  • Super Contributor
  • ***
  • Posts: 4543
  • Country: ua
    • xDevs.com
Re: 3458A GPIB-Readout nonblocking
« Reply #1 on: August 26, 2018, 08:30:01 pm »
Hi,

I have STB checking for calibration procedures on K2002, but didn't do for readings (don't mind the wait).
Maybe this little piece can help:

Code: [Select]
def k2002_calsts():
    srq = 0x0
    cnts = 0
    while (srq != 0x20):
        sre = intf.ibstat()
if isinstance(sre, (int, long)):
    srq = sre
else:
        srq = ord(intf.ibstat())   
        sys.stdout.write ("%d sec, SRQ = %X\r" % (cnts, srq))
time.sleep(1)
        cnts = cnts + 1
        sys.stdout.flush()
        if (srq != 0x0):
            intf.write("*CLS")
            sys.stdout.write("\r\n")
            sys.stdout.flush()
            print ("%d seconds, SRQ = %X" % (cnts, srq))
            return srq
    time.sleep(1)
    return srq
YouTube | Metrology IRC Chat room | Let's share T&M documentation? Upload! No upload limits for firmwares, photos, files.
 
The following users thanked this post: Echo88

Offline Echo88Topic starter

  • Frequent Contributor
  • **
  • Posts: 826
  • Country: de
Re: 3458A GPIB-Readout nonblocking
« Reply #2 on: August 26, 2018, 10:52:41 pm »
Since "STB?" isnt recommended in the 3458A-Manual and SPOLL just gave out the normal measured data instead of the status register (surely my own stupidity in not using it correctly in Python), i searched in the PyVISA-documents and found the Instrument.read_stb() command.
With the following code snippet one can then look if the Bit 7 is set (Data Available) and if it is, gather the data, if not then one can just doing other stuff in the code. In my case i read out the Serial-Port with about 5 Samples/s from an ADC and cant wait for the 3458A with its 100NPLC-sample-time.

Code Snippet:

dataready =  HP3458A.read_stb()
if dataready >= 128:
       DMM_Value = float(HP3458A.read())
else:
       do the usual other timecritical stuff
 
The following users thanked this post: TiN, ManateeMafia, Mickle T., e61_phil

Offline dl1640

  • Regular Contributor
  • *
  • Posts: 222
  • Country: cn
Re: 3458A GPIB-Readout nonblocking
« Reply #3 on: August 27, 2018, 10:15:51 am »
Please read user manual, page 306.
Serial poll and *STB? are different in 3458
 

Online Tony_G

  • Frequent Contributor
  • **
  • Posts: 909
  • Country: us
  • Checkout my old test gear channel (link in sig)
    • TGSoapbox
Re: 3458A GPIB-Readout nonblocking
« Reply #4 on: August 27, 2018, 05:23:32 pm »
Since "STB?" isnt recommended in the 3458A-Manual and SPOLL just gave out the normal measured data instead of the status register (surely my own stupidity in not using it correctly in Python), i searched in the PyVISA-documents and found the Instrument.read_stb() command.
With the following code snippet one can then look if the Bit 7 is set (Data Available) and if it is, gather the data, if not then one can just doing other stuff in the code. In my case i read out the Serial-Port with about 5 Samples/s from an ADC and cant wait for the 3458A with its 100NPLC-sample-time.

Code Snippet:

dataready =  HP3458A.read_stb()
if dataready >= 128:
       DMM_Value = float(HP3458A.read())
else:
       do the usual other timecritical stuff

+1 for Echo88's solution - Here is the relevant C# code from the current Keysight sample:

Code: [Select]
public void ReturnReadings()
//"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
// This function triggers the instrument and takes readings.
//"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
{
short rdcnt = 0,
i;
double[] rdgs = new double[5200]; // Returns reading from memory

// Check for exceptions
try
{
            // Trigger the 3458A
Dmm.WriteString("TARM SGL", true);

// Read status byte to determine when measurements are complete
do
rdcnt = Dmm.IO.ReadSTB();
while ((rdcnt & 128) != 128);

// Get number of readings taken
Dmm.WriteString("MCOUNT?", true);
rdcnt = (Convert.ToInt16((double)Dmm.ReadNumber(IEEEASCIIType.ASCIIType_R8, true)));

listBox1.Items.Clear();
listBox1.Items.Add("Number readings taken: " + rdcnt.ToString());
listBox1.Items.Add("Returning readings; takes some time.");
listBox1.Items.Add("");
listBox1.Items.Add("Rdg#\tValue");
listBox1.Items.Add("---------\t------------------------------");
listBox1.Refresh();

// Remove the readings
Dmm.WriteString("RMEM 1," + rdcnt.ToString() + "\n", true);
rdgs = (double[])Dmm.ReadList(IEEEASCIIType.ASCIIType_R8, ",");

// Enter readings into list box
for (i=0; i<rdcnt; i++)
listBox1.Items.Add((i+1).ToString() + "\t" + (rdgs[i].ToString()));

//Check for errors
Check_Error("ReturnReadings");
}
catch(Exception e)
{
MessageBox.Show(e.Message + "\nin function: ReturnReadings", "VISAComExample");
End_Prog();
}
}


You can see exactly how they're following the model that Echo88 showed. If you want to get all eventy on it then you use SPOLL and setup an event handler (I'm sorry I'm not a Python guy so you'll have to see how to do that yourself).

Here is some code showing how I did this for a HP438A:

Code: [Select]
using Ivi.Visa.Interop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace HP438A
{
    enum Mode { CHA, CHB, ZER, CAL, ADJ, SWR };

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IEventHandler
    {
        public static RoutedCommand SetModeCommand = new RoutedCommand();

        private string PWRMeterAddress = @"GPIB1::13::INSTR";
        private ResourceManager ResMgr;
        private FormattedIO488 PWRMeter;
        private DispatcherTimer ReadTimer;
        private Mode CurrentMode;
        private string CurrentCommand;
        private Mode CurrentChannel;
        private IEventManager Srq;
        private List<RadioButton> radioButtons;

        public MainWindow()
        {
            InitializeComponent();

            // Get the radiobuttons for the mode group
            radioButtons = ModeButtons.Children.OfType<RadioButton>().ToList<RadioButton>();

            CommandBinding SetModeCommandBinding = new CommandBinding(SetModeCommand, ExecutedSetModeCommand, CanExecuteSetModeCommand);
            this.CommandBindings.Add(SetModeCommandBinding);

            try
            {
                ResMgr = new ResourceManager();
                PWRMeter = new FormattedIO488();

                Initialize438();
                SetMode("CHA");
                CurrentChannel = Mode.CHA;

                // Setup the event handler for SRQ (primarily for CAL & ZERO)
                Srq = (IEventManager)PWRMeter.IO;
                Srq.InstallHandler(EventType.EVENT_SERVICE_REQ, this);

                InitializeTimer();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Please ensure that the Keysight IO Libraries are installed\nand configured correctly\n\n" + ex.Message, "438A Power Meter Application Error");
                System.Windows.Application.Current.Shutdown();
            }
        }

        private void Initialize438()
        {
            PWRMeter.IO = (IMessage)ResMgr.Open(PWRMeterAddress, AccessMode.NO_LOCK, 2000, null);
            PWRMeter.IO.TerminationCharacterEnabled = true;
            PWRMeter.IO.Timeout = 20000;
            PWRMeter.IO.Clear();

            // PReset, CaL100, ENter, LoG, TRigger2
            SendCommand("PRCSLGTR0 ");
        }

        private void InitializeTimer()
        {
            ReadTimer = new DispatcherTimer();
            ReadTimer.Interval = TimeSpan.FromSeconds(1);
            ReadTimer.Tick += Timer_Tick;
        }

        private void btnRun_Checked(object sender, RoutedEventArgs e)
        {
            btnRun.Content = "Stop";
            ReadTimer.Start();
        }

        private void btnRun_Unchecked(object sender, RoutedEventArgs e)
        {
            btnRun.Content = "Run";
            ReadTimer.Stop();
        }

        private void ExecutedSetModeCommand(object sender, ExecutedRoutedEventArgs e)
        {
            RadioButton btnClicked = e.Source as RadioButton;

            SetMode(btnClicked.CommandParameter.ToString());
        }

        private void SetMode(Mode targetMode)
        {
            switch (targetMode)
            {
                case Mode.CHA:
                    SetMode("CHA");
                    break;
                case Mode.CHB:
                    SetMode("CHB");
                    break;
                case Mode.ZER:
                    SetMode("ZER");
                    break;
                case Mode.CAL:
                    SetMode("CAL");
                    break;
                case Mode.ADJ:
                    SetMode("ADJ");
                    break;
                case Mode.SWR:
                    SetMode("SWR");
                    break;
                default:
                    break;
            }
        }

        private void SetMode(string mode)
        {
            switch (mode)
            {
                case "CHA":
                    CurrentMode = Mode.CHA;
                    CurrentCommand = "APTR2";
                    CurrentChannel = Mode.CHA;
                    break;
                case "CHB":
                    CurrentMode = Mode.CHB;
                    CurrentCommand = "BPTR2";
                    CurrentChannel = Mode.CHB;
                    break;
                case "ZER":
                    CurrentMode = Mode.ZER;
                    //Set the SRQ Mask
                    // The Cal/Zero mask is bit 2 (bit 1 if zero referencing)
                    // so that resolves to a 0x02 byte which can be put in a
                    // string using the unicode escape
                    SendCommand("@1\u0002");

                    // Enable the handler to respond to the SRQ
                    Srq.EnableEvent(EventType.EVENT_SERVICE_REQ, EventMechanism.EVENT_HNDLR);

                    // Zero the meter
                    CurrentCommand = "ZE";
                    break;
                case "CAL":
                    CurrentMode = Mode.CAL;
                    CurrentCommand = "";
                    break;
                case "ADJ":
                    CurrentMode = Mode.ADJ;
                    CurrentCommand = "";
                    break;
                case "SWR":
                    CurrentMode = Mode.SWR;
                    CurrentCommand = "";
                    break;
            }

            SendCommand(CurrentCommand);
        }

        private void SendCommand(string Command)
        {
            //TODO: Fix condition when read returns an error string
            PWRMeter.WriteString(Command, true);
        }

        private string ReadCommand(string Command)
        {
            PWRMeter.WriteString(Command, true);
            return PWRMeter.ReadString();
        }

        private void CanExecuteSetModeCommand(object sender, CanExecuteRoutedEventArgs e)
        {

            if (e.Source is Control target)
            {
                e.CanExecute = true;
            }
            else
            {
                e.CanExecute = false;
            }
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            string Symbol = "";

            switch (CurrentMode)
            {
                case Mode.CHA:
                case Mode.CHB:
                    //TODO: Add support for Log/Lin
                    //TODO: Watch for Log/Lin setting to determine whether to use engineering notation
                    //txtReading.Text = ToEngineeringFormat.Convert(Convert.ToDouble(ReadCommand(CurrentCommand)), 6, Symbol);
                    var reading = Convert.ToDouble(ReadCommand(CurrentCommand));

                    // If there is a reading Log/Lin error the the returned value is
                    // very large (9E+40). Skip updating the UI if that is the case.
                    if (reading > 8E+40)
                        break;

                    // Setup the appended symbol
                    Symbol = " dBm";
                    txtReading.Text = reading.ToString("F") + Symbol;
                    break;
                case Mode.ZER:
                    txtReading.Text = "Zeroing";
                    break;
                case Mode.CAL:
                case Mode.ADJ:
                    Symbol = "";
                    break;
                case Mode.SWR:
                    Symbol = " SWR";
                    break;
            }
        }

        void IEventHandler.HandleEvent(IEventManager vi, IEvent @event, int userHandle)
        {
            switch (CurrentMode)
            {
                case Mode.ZER:
                case Mode.CAL:
                    // Clear the status byte
                    SendCommand("CS");

                    // Update the UI and mode
                    System.Windows.Application.Current.Dispatcher.Invoke(delegate
                    {
                        txtReading.Text = "Complete";
                        radioButtons.Find(x => x.Content.ToString() == "CHA").IsChecked = true;
                        SetMode(CurrentChannel);
                    });
                    break;
                default:
                    break;
            }
        }
    }
}


Please note that this code isn't finished nor is it intended to be a canonical example of how to do it - I'm trying to write an app to help my dad make SWR/Ratio measurements with his 438A.

TonyG



Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf