0

I'm testing out the vanilla viWrite() function and have realised that it does not return an error code when I pass in an invalid command string. I find this a little strange... surely the implementation ought to detect this event.

Here is a small test case I used to demonstrate this... (it's just test code so it won't be perfect :))

#include <visa.h>
#include <cstring>
#include <iostream>

#define VIBUF_LEN 255

static ViChar viBuf[VIBUF_LEN];

void MyWrite(ViSession sess, char const *cmd)
{
    ViStatus status;
    ViUInt32 rcount;

    strncpy_s(viBuf, cmd, VIBUF_LEN);
    status = viWrite(sess, (ViBuf)viBuf, strlen(viBuf), &rcount);
    if (status < VI_SUCCESS)
    {
        std::cout << "Failed to write!\n";
        exit(-1);
    }
}

std::string MyRead(ViSession sess)
{
    ViStatus status;
    ViUInt32 rcount;

    status = viRead(sess, (ViBuf)viBuf, VIBUF_LEN, &rcount);
    if (status < VI_SUCCESS)
    {
        std::cout << "Failed to read 1!\n";
        exit(-1);
    }
    else if (rcount >= VIBUF_LEN)
    {
        std::cout << "Failed to read 2!\n";
        exit(-1);
    }
    else if (!rcount)
    {
        std::cout << "Failed to read 3!\n";
        exit(-1);
    }

    viBuf[rcount] = NULL;
    return std::string(viBuf);
}

int _tmain(int argc, _TCHAR* argv[])
{
    ViStatus status;
    ViSession mVisaDefaultRM;
    ViSession mVisaInst;

    status = viOpenDefaultRM(&mVisaDefaultRM);
    if (status == VI_SUCCESS)
    {
        strncpy_s(viBuf, "GPIB0::1::INSTR", VIBUF_LEN);
        status = viOpen(mVisaDefaultRM, viBuf, VI_NULL, VI_NULL, &mVisaInst);
    }

    if (status < VI_SUCCESS)
    {
        std::cout << "Failed to initialise!\n";
        exit(-1);
    }

    viClear(mVisaInst);
    MyWrite(mVisaInst, "*CLS;");
    MyWrite(mVisaInst, "*RST;");
    MyWrite(mVisaInst, "*SRE 0;");
    MyWrite(mVisaInst, "*ESE 0;");
    MyWrite(mVisaInst, "CRAP;");   /* Wow really!? */
    MyWrite(mVisaInst, "*ESR?;");
    std::string str = MyRead(mVisaInst);
    std::cout << "ESR is " << str.c_str() << "\n";

    std::cout << "END\n";
    getchar();

    return 0;
}

The program outputs the following:

ESR is +32
END

So, the write of the SCPI command "CRAP;" is definitely being flagged up as an error by the device.

This made me think, ah... I haven't enabled the ESE bit to enable this bit to get flagged in the STB. So I do this:

MyWrite(mVisaInst, "*ESE 255;");
//                       ^^^
//                       A bit of a sledge hammer but should do the job

The bad command is still not detected.

Okay, so maybe need to enable SRQs... perhaps the VISA library needs both these enabled to handle this...

So I do this:

MyWrite(mVisaInst, "*SRE 255;");
//                       ^^^
//                       A bit of a sledge hammer but should do the job

Nope, no difference. It still does not detect the bad command.

Is this standard VISA? Should it be working like this? Does this mean that if I want to detect these errors I always have to enable the event VI_EVENT_SERVICE_REQ and so a viWaitOnEvent() after a write? I would have thought the vanilla viWrite() would detect this for me??

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jimbo
  • 4,352
  • 3
  • 27
  • 44
  • 2
    isn't it possible that viWrite just takes care of _writing_? I mean, it's not because the command doesn't make sense, that writing it failed. Or to put it another way: suppose I enter a typo in this comment, posting it still succeeds. – stijn Jul 16 '13 at 10:25
  • yes could be! +1. I'm a new to visa and I've been assuming it does some work "behind the scenes" to check for errors but what you say makes more sense because it has to be device independent even though the ESR is somewhat standardised. Hmm... hastle... I want to be able to detect such errors without interrupt any commands I send etc but without having to rely on a timeout if no error events occur... how well do you know the visa library? – Jimbo Jul 16 '13 at 10:48
  • I think you're correct. The error return code must just be a client side error or if the device isn't responding at all or correctly to handshaking but nothing more. If you want to post it as an answer I'll upvote and accept. Thanks for pointing this out! – Jimbo Jul 16 '13 at 10:53

1 Answers1

2

viWrite just takes care of writing (see Ni Visa Programmers Reference), meaning it only returns an error when there's a true communication failure (like a timeout, or someone unplugging the cable, etc.). This is standard for low-level I/O functions (sockets, serial ports, ... all work this way).

Which means in order to figure out if there is a remote device error you'll have to query that somehow. I'm not familiar with VISA, so I'm not sure what the best way is too achieve this. It's either something in the style you talk about (events) or maybe you can query the device directly? (maybe you can viWrite a command that says "give me your status" and then viRead the response?)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
stijn
  • 34,664
  • 13
  • 111
  • 163
  • Thanks stijn. Not sure what the best way to solve it is as it appears some commands don't generate a "success" signal that I can use as a SRQ. I'm thinking maybe SPOLL, not sure. Cheers for help – Jimbo Jul 16 '13 at 11:17