Jump to content

As of July 17, 2015, the LabJack forums here at forums.labjack.com are shut down. New registrations, topics, and replies are disabled. All forums are in a read-only state for archive purposes.

Please visit our current forums at labjack.com/forums to view and make new posts. To post on the current forums, use your labjack.com login account. Your old LabJack forums login credentials have been retired. There are no longer separate logins for labjack.com and LabJack forums.


Photo

Raw Input/Output Fails in C++


  • Please log in to reply
4 replies to this topic

#1 JeffW

JeffW
  • Members
  • 3 posts

Posted 22 June 2013 - 10:56 PM

This is my first time programming the LabJack (really cool device) so this problem may simply be my lack of experience.

I can successfully communicate with my U3 Labjack using the LJUD_DynamicLinking.h and library. (C++ Visual Studio 2008)
But when I try a raw communication to a single DS18B20 connected to EI06 (through a DB15 connector) it fails.

LJ_HANDLE ljHandle;
LJ_ERROR ljError;
double dblVoltage;
double commandArray[8];
unsigned char* bytePtr;
double numBytesToWrite=64;


ljError = m_pOpenLabJack (LJ_dtU3, LJ_ctUSB, "1", TRUE, &ljHandle);
(Return No Error)

ljError = m_peAIN(ljHandle, 3, 31, &dblVoltage, 0, 0, 0, 0, 0, 0);
(Return No Error)

printf("AIN3 value = %.3f\n",dblVoltage);
(prints 1.388 and shows that communication has been established to the device)

(Command array is filled in according to the DS18B20 spec sheet)
bytePtr=(unsigned char *) commandArray;

bytePtr[1]=0xF8;
bytePtr[2]=0x1D;
bytePtr[3]=0x3C;
bytePtr[4]=0x00;
bytePtr[5]=0x00;
bytePtr[6]=0x00;
bytePtr[7]=0x00;
bytePtr[8]=0x0E;//EI06
bytePtr[9]=0x00;
bytePtr[10]=0x00;
bytePtr[11]=0x33;//Specify Read ROM Command
for(i=12;i<64;i++) bytePtr[i]=0x00;//Zero out the rest to guarantee checksum does not get messed up.
//
(compute the checksum for the bytes 1-63)
bytePtr[0]=eightBitCheckSum(64,
bytePtr);


ljError=m_peGet(ljHandle, LJ_ioRAW_OUT, 0, commandArray,numBytesToWrite);

This causes the error "Invalid Raw In/Out Parameter" error no matter what commandArray contains.

When I change the second argument to 0 (not correct), this gets rid of the error, leading me to believe it has something to do with the second argument.

The pseudocode in the documentation (4.3.8) gives an Example for doing this but the function calls don't match the documentation API.
In addition the array in the example appears to be incorrect.

Any Ideas?

Thanks

#2 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 24 June 2013 - 02:45 PM

This is my first time programming the LabJack (really cool device) so this problem may simply be my lack of experience.

I can successfully communicate with my U3 Labjack using the LJUD_DynamicLinking.h and library. (C++ Visual Studio 2008)
But when I try a raw communication to a single DS18B20 connected to EI06 (through a DB15 connector) it fails.

LJ_HANDLE ljHandle;
LJ_ERROR ljError;
double dblVoltage;
double commandArray[8];
unsigned char* bytePtr;
double numBytesToWrite=64;


ljError = m_pOpenLabJack (LJ_dtU3, LJ_ctUSB, "1", TRUE, &ljHandle);
(Return No Error)

ljError = m_peAIN(ljHandle, 3, 31, &dblVoltage, 0, 0, 0, 0, 0, 0);
(Return No Error)

printf("AIN3 value = %.3f\n",dblVoltage);
(prints 1.388 and shows that communication has been established to the device)

(Command array is filled in according to the DS18B20 spec sheet)
bytePtr=(unsigned char *) commandArray;

bytePtr[1]=0xF8;
bytePtr[2]=0x1D;
bytePtr[3]=0x3C;
bytePtr[4]=0x00;
bytePtr[5]=0x00;
bytePtr[6]=0x00;
bytePtr[7]=0x00;
bytePtr[8]=0x0E;//EI06
bytePtr[9]=0x00;
bytePtr[10]=0x00;
bytePtr[11]=0x33;//Specify Read ROM Command
for(i=12;i<64;i++) bytePtr[i]=0x00;//Zero out the rest to guarantee checksum does not get messed up.
//
(compute the checksum for the bytes 1-63)
bytePtr[0]=eightBitCheckSum(64,
bytePtr);


ljError=m_peGet(ljHandle, LJ_ioRAW_OUT, 0, commandArray,numBytesToWrite);

This causes the error "Invalid Raw In/Out Parameter" error no matter what commandArray contains.

When I change the second argument to 0 (not correct), this gets rid of the error, leading me to believe it has something to do with the second argument.

The pseudocode in the documentation (4.3.8) gives an Example for doing this but the function calls don't match the documentation API.
In addition the array in the example appears to be incorrect.

Any Ideas?

Thanks


The main issue is that the commandArray and the numByteToWrite values in the m_peGet() call should be swapped. The 4th parameter (the Value) in this case is the number of bytes to write or read. The 5th parameter (x1) is the pointer to the array. I know that is a little confusing because of the eGet() function (because the Value in it is a pointer, and x1 is a constant) but its set that way mainly because eGet() is actually a wrapper to AddRequest(). See here for more info.

Also, looking at your code there are a few other things to take note of. First, is when you put numBytesToWrite into the value slot, you'll need to pass the pointer to that value (so &numBytesToWrite). You could also use the ePut() function and just pass it as is. Again, this is sub-optimal because of how Arrays are done. I usually stick with AddRequest/Go/GetResult when working with arrays.

So your call should look something like this:

ljError=m_peGet(ljHandle, LJ_ioRAW_OUT, 0, &numBytesToWrite, (int)commandArray);

In AddRequest() the value parameter is a double passed by value, and x1 is an int passed by value. At the time of the driver's creation (when 64-bit wasn't an issue) it made more sense to pass the pointer to the array into the x1 parameter, since that is an easy conversion since they are the same number of bytes. The value parameter is often read & updated in the GetResult() function as well, and passed by reference into that function. Thus, for cases where the driver reports how many bytes of the array were changed/written/etc it made sense to pass it that way. eGet() has the value parameter passed by reference (a pointer) so that it can be updated.

Also, I see you are using dynamic linking to our .dll directly. We have C/C++ examples for Visual Studio 2008 (and other versions) here. We know that is a little confusing since they are marked as VC6, but they port over to newer versions of Visual Studio just fine. We are actually in the process of revamping them for VS2005 (and later versions) with other changes to make them easier to find & use. I believe there is a Raw I/O example included in them.

If you have any other questions or run into anything else please let us know.

#3 JeffW

JeffW
  • Members
  • 3 posts

Posted 04 July 2013 - 07:57 PM

Thanks, your response helped clarify some important points. I recompiled my code in 32-bit using the .lib directly (static) as you suggested (to make sure there weren't any problems with my 64-bit build and using a mismatched DLL) I am able to run the RAW IO example provided in the code that you pointed me to. When I execute the command in my original post (with appropriate fixes), I don't get an error but nothing seems to happen. double numBytesToWrite=64; double numBytesToRead=64; long commandArray[16]; //set up as before long responseArray[16]; ljError=eGet(ljHandle, LJ_ioRAW_OUT, 0, &numBytesToWrite,(int)commandArray); printLabJackErrorMessage(ljError);//No error is reported //CommandArray is unchanged I then try to query the device for the result by setting responseArray to be equivelent to commandArray (since the 1-wire command needs to know the pin being used) and calling ljError=eGet(ljHandle, LJ_ioRAW_IN, 0, &numBytesToRead,(int)responseArray); printLabJackErrorMessage(ljError); //No error The response array has byte 1 altered to a different value. According to the documentation bytes 16 to 23 should contain the 64-bit chip code but they don't. What happens in the case that the chip is not hooked up properly? Am I using the checksums correctly and are they required? I feel like I don't have a good understanding of how eGet works. You said you prefer to perform IO of arrays using AddRequest() and maybe that's a more intuitive method. Can you illustrate how it is done with this example? Thanks for being so helpful. JeffW

#4 LabJack Support

LabJack Support
  • Admin
  • 8677 posts

Posted 08 July 2013 - 03:56 PM

Thanks, your response helped clarify some important points.

I recompiled my code in 32-bit using the .lib directly (static) as you suggested (to make sure there weren't any problems with my 64-bit build and using a mismatched DLL)
I am able to run the RAW IO example provided in the code that you pointed me to.

When I execute the command in my original post (with appropriate fixes), I don't get an error but nothing seems to happen.

double numBytesToWrite=64;
double numBytesToRead=64;
long commandArray[16]; //set up as before
long responseArray[16];

ljError=eGet(ljHandle, LJ_ioRAW_OUT, 0, &numBytesToWrite,(int)commandArray);
printLabJackErrorMessage(ljError);//No error is reported
//CommandArray is unchanged

I then try to query the device for the result by setting responseArray to be equivelent to commandArray (since the 1-wire command needs to know the pin being used) and calling

ljError=eGet(ljHandle, LJ_ioRAW_IN, 0, &numBytesToRead,(int)responseArray);
printLabJackErrorMessage(ljError); //No error

The response array has byte 1 altered to a different value.

According to the documentation bytes 16 to 23 should contain the 64-bit chip code but they don't.
What happens in the case that the chip is not hooked up properly?

Am I using the checksums correctly and are they required?

I feel like I don't have a good understanding of how eGet works.
You said you prefer to perform IO of arrays using AddRequest() and maybe that's a more intuitive method.

Can you illustrate how it is done with this example?

Thanks for being so helpful.
JeffW


There are a few things that stick out. First, your arrays are declared to be only 16 bytes, but are being treated as 64. This could create some potential memory issues.

Also, there is a checksum that should be put into bytes 4 and 5, as documented here. The easiest thing to do would be if you could send us your code (or just the parts related to the U3 if it's a large project) to [email protected] We can check the code and make sure it's set up as it should be which you can then use to test with your hardware.

#5 JeffW

JeffW
  • Members
  • 3 posts

Posted 12 July 2013 - 11:37 PM

Thanks for all of you help through this topic and Email support.

 

Your LabJack Technical support has been outstanding making me even happier than I already was with the product.

 

I am now able to successfully read the temperature from my DS18B20 after getting the commands and checksum correct.

The device was hooked up according to the example on EI06 through a DB15 connector.

 

(I'm still not 100% sure if I am sending the correct number and format of the match ROM code 0x55 for reading temperature since the temperature periodically doesn't seem to update)

 

Since this might be useful to other C++ programmers I have attached the complete source code. (Also the compiled executable)

 

This code also contains utility routines for computing the checksums necessary to build commands.

 

The code was compiled in C++ using Visual Studio 2008 on Windows 7 (32-bit, haven't tried to build the 64-bit yet).

I included a cmake file in an attempt to make it easier to compile.

 

If you are not familiar with Cmake.

Copy the attached files into a source directory.

Change the directories in CMakeLists.txt to match your system.

Download Cmake

Make a directory for the solution to be created in.

Run  Cmake

Choose the source directory containing the attached files.

Choose the output directory that you created.

Push configure and choose your compiler (must have one installed)

Push generate

You will now have a solution in the folder you created.

Double click it to open.

It should compile without any problems.

 

Jeff

Attached Files




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users