Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

EARG (4) error when using ibrd() in Visual Basic 6.0

Hello,
 
I have a question about the ibrd() call in Visual Basic 6.0.  I am using a fixed length string for the buffer.  The buffer is quite large, 20,000 bytes, because I am getting a large amount of ASCII data off of a device.  I call ibwrt() to make the appropriate query (the device allows the contents of its output buffer to be viewed on its display, so I know its all set to transmit data...) and when I call ibrd() the buffer is empty and there is an error in ibsta.  The number in iberr is 4, which the manual refers to as "invalid argument".  The device descriptor is the same on from the ibwrt() call, so I know that isn't the "invalid argument".  I was wondering if anyone knew any reason why the buffer would be considered an "invalid argument"
 
The other odd thing is that I can communicate with the instrument using GPIB explorer and eventually, the function described above will work properly.  Once it starts working, it works every time, no error #4.  But as soon as Visual Basic is restarted, I have the same problem all over again.
 
Thank you very much in advance for any help anoyone can offer, I've been all over the web and forums looking for a solution.
 
0 Kudos
Message 1 of 13
(5,946 Views)

Hello,

The only reason that this could be happening (since your UD is good) is that there's something wrong with your buffer or your count.  Make sure your buffer isn't NULL and that your count is > 0 (I think this is >-1, actually, but a read of 0 doesn't make much sense).  What version of the driver are you using?  And on what OS?  Also, if you could take an NI-Spy capture of the failure and post it here, that would help immensely.

Thanks,
Scott B.
GPIB Software
National Instruments

0 Kudos
Message 2 of 13
(5,928 Views)
If you are not familiar with NI-SPY, you can find a tutorial here.

Logan S.
0 Kudos
Message 3 of 13
(5,922 Views)
Thanks for the help everyone.  First off, additional information:
 
OS: Windows 2000, 5.0.2195, Service Pack 4
 
Visual Basic 6.0: SP6 ver. 9782
 
National Instruments: Comments in VIB32.bas say "Version 1.81", Comments in NIGLOBAL.bas say "version 1.8",  the Readme.txt in the NI488.2 directory says "Version 2.3"
 
In VB I initialized the buffer with a line like:
 
Dim buf As String * DATA_BUFFER_SIZE
 
where DATA_BUFFER_SIZE = 10000.  This makes a string 20000 bytes long, as reported by LenB().  At first I was just using this string "as is".  Then I tried to "initialize" it (though I think VB already inits fixed-length strings with \0's) with a line like:
 
buf = ""
 
Now I see from ScottieB's reply that the buffer shouldn't be NULL.  I'm guessing you mean the pointer, which I don't think I have any control over in VB, but just to be on the safe side I tried "initializing" buf with a line like:
 
buf = space(DATA_BUFFER_SIZE)
 
to get a string filled with ASCII 32 instead of ASCII 0.  This acutally produced a change in behavior.  I open VB, run the program, and get the same EARG error, but now if I stop the program and run it again, it seems like the error goes away.  However, after several runs of the program, I will occasionally get VB crashing with one of those "Instruction could not be read" errors.  Is something writing or reading past the end of the buffer?  Maybe I need to leave a /0 at the end of the string? 
 
I'll post the NI Spy results in another reply, since I've hit a character limit...
0 Kudos
Message 4 of 13
(5,918 Views)
... and here are the NI-Spy results from the last run:
 
469.  ibwrt(UD0, "TRCA?1,0,321.", 13 (0xD))
Process ID: 0x000004F8         Thread ID: 0x0000007C
Start Time: 12:50:42.891       Call Duration: 00:00:00.010
ibsta: 0x100       iberr: 0             ibcntl: 13(0xd)
470.  ThreadIbsta()
Process ID: 0x000004F8         Thread ID: 0x0000007C
Start Time: 12:50:42.901       Call Duration: 00:00:00.010
ibsta: 0x100       iberr: 0             ibcntl: 13(0xd)
> 471.  ibrd(UD0, "", 20000 (0x4E20))
> Process ID: 0x000004F8         Thread ID: 0x0000007C
> Start Time: 12:50:42.921       Call Duration: 00:00:00.010
> ibsta: 0x8100       iberr: 4             ibcntl: 0(0x0)
> 472.  ThreadIbsta()
> Process ID: 0x000004F8         Thread ID: 0x0000007C
> Start Time: 12:50:42.931       Call Duration: 00:00:00.011
> ibsta: 0x8100       iberr: 4             ibcntl: 0(0x0)
> 473.  ThreadIberr()
> Process ID: 0x000004F8         Thread ID: 0x0000007C
> Start Time: 12:50:42.942       Call Duration: 00:00:00.010
> ibsta: 0x8100       iberr: 4             ibcntl: 0(0x0)
Line (469) is the query (to a Standford Research Systems SR850 Lock-in Amplifier).  After the ibwrt() I check for errors (none) and then call ibrd() on (471).    After that, my application checks ibsta for an error, finds it, and checks iberr to report it.  Here are the details for the ibrd() on line (471):
 
_INPUT_
UD = 31256
&buffer = 0x030E0CEC
count = 20000 (0x4e20)
 
_OUTPUT_
ibsta = 0x8100
iberr = EARG (4)
ibcntl = 0 (0x0)
 
_BUFFER_
(this tab was blank)
 
I hope some of this can help. The VB app works really well except for this one bit 🙂
 
Thanks again.
0 Kudos
Message 5 of 13
(5,917 Views)
could you actually post the .spy files? They're a little easier to read. Also, could you post two captures? One where it doesn't work and one where it does? Just make sure that you start SPY before you run your program, so we get a good look at the whole setup, and stop NI-SPY after you stop your program.

Logan S.
0 Kudos
Message 6 of 13
(5,904 Views)
Thanks for the help, LoganS.  Is there a special trick to attaching .spy files to these posts?  Since .zip files are allowed I zipped up two .spy files and attached that.  I'm on a PC at work and I don't have easy access to other file compression programs, so I hope that works OK for you.  The first file is called EARG.spy and documents the EARG error.
 
After starting NI-Spy, I
1) Start VB and open my project
2) Run the project
3) Get the error
4) Close the the project, stopping program execution
5) Re-run the project
6) Successfully collect the data
7) Close the project
😎 Exit VB
 
In this project there are two instruments.
ud0: SR850 Lock-in amplifier
ud1: Diode laser
 
Here is what is going on at the different lines in the spy file:
 
1-59: Set up both instruments for a scan
 
60-61: Set up lock-in to start the scan with a Trigger()
 
62: Send Trigger() to all instruments.  Previously, I had two lock-in amplifiers collecting data simultaneously so I started them both with a GPIB trigger.  To simplify debugging of this problem, I completely removed all code relating to the second lock-in.
 
63-586: Wait around for the scan to complete.  During this time, I send "STB?" to the lock-in to query its status byte to see if the scan is done.  I am also monitoring the temperature of the diode laser with ":SENS:TEMP..." queries.
 
587-590: The status byte changes to "1". The scan is complete.
 
591-598: Some "clean-up" stuff and allocation of arrays to hold the trans from the lock-in.
 
599-609: ERROR.  Here is where I ask the lock-in how many points it has and attempt to read those points with the "TRCA?" query.
 
610-621: Recovery from error, graceful exit from scan subroutine.
 
622-623: Close connections to instruments on exit from application  with ionl().
 
624-1287: Do the whole thing again, this time without an error.  The "TRCA?" query is on line 1236.
 
The second file is called vbcrash.spy and documents the steps necessary to crash VB6.  Basically I run everything as before and, as before, get an EARG (4) error on line 567.  This time I DO NOT shut down the program after error recovery.  Lines 570-599 show a bunch of commands sent to the laser and lock-in for recovery and a re-run of the scan.  Note that nothing is a query and there are no ibrd() calls.  The first query is on line 602 and it is a request for a status byte, i.e. "STB?".  The buffer for this query is set with:
 
Dim buf As String * 255
 
so the buffer size should be 512 bytes.  Line 604 shows the ibrd() operation reading 510 bytes.  The buffer fills with the data from the "TRCA?" query which exited with EARG (4).  I don't know whether this is data that was in the output buffer of the lock-in or if this was data that was read off of the lock-in, was sitting around in the ni dll's, and got copied into buf on the next ibrd() call.  After that, the scan exits because the value read is not a boolean.  When I end the program, I get a "vb6.exe Application Error" with the message:
 
The instruction at "0x77aa48e4" referenced memory at "0x37363952".  The memory could not be "read".
and VB then exits upon closing the dialog.
 
This really looks to me like the ni drivers are writing past the end of the buffer, but I don't have a debugger installed on this machine so I can't check that. Or maybe I just want to believe that there is a problem with someone else's code instead of mine 😉
 
Thanks agian for all the help,
-Forrest
 
0 Kudos
Message 7 of 13
(5,775 Views)
Your .zip file didn't post, can you repost with it?  Thanks!

Scott B.
GPIB Software
National Instruments
0 Kudos
Message 8 of 13
(5,887 Views)

If you are declaring your buffer with 10,000 characters and telling a C function that it can write 20,000 characters to that buffer you have a problem happening.

When you call ibrd VB does not pass a pointer to the actual memory location of your string.  It declares a new memory location, with the same number of characters!   and passes a pointer to that location.  If you change your string declaration to match the buffer size that you tell ibrd then you should not have any trouble.  You don't have to initialize the string, but I personally usually fill it with chr(0).

 

Message 9 of 13
(5,882 Views)
Hi Saikey,

The NI drivers actually come with VB routines which actually make the call to the DLLs.  These VB routines actually don't take a count argument, instead they determine the count from the size of the string passed to them.  I think what is happening is that VB uses unicode (2 bytes/char) encoding for its strings.  There is a function, LenB(), which will return the length of a string in bytes.  The VB code that comes with the NI drivers checks the length of a string with LenB() and passes this argument to the count of the C function.  I double-checked all of this, and the 10,000 character string is indeed 20,000 bytes, according to LenB(), and 20,000 is the count sent to ibrd().  I assumed that the NI DLLs use 8-bit ASCII characters... is this true?  If it's not then this could be the problem, in which case NI should change its VB functions to use Len() instead of LenB().  I am using the 32-bit versions of the visual basic .bas files, if that makes a difference.

Actually, I just realized that if the DLLs where NOT using the same character encoding that VB uses, then the returned values would always be a mess of random unicode characters, which they are not.  Unless VB has some way of guessing the encoding of the characters in a string!?  I will try and figure out a way to test what's going on...

Thanks!
0 Kudos
Message 10 of 13
(5,877 Views)