12-13-2019 03:53 PM
Thank you Rolf for educational and descriptive replies, I appreciate your patience and willing to help! Especially the analogy with glasses of water was very useful 🙂 I think I understand better now what I need to do. I guess I will create another test vi where I will be testing buffer-related functionality together with StartAcquisition, StopAcquition and WaitForAcquisitionUpdate functions from picam.h.
02-12-2020 10:50 AM
Hi Rolph.
Hope you had a great time on New Year holidays. Finally, I got back to my struggles of getting the camera functionality work. I have rereading you replies many times, and things got a bit more clear, however, I still miss some details in my understanding.
As I said before, I have created a test VI to test the asynchronous acquisition and buffer-related functionality. This VI is called TESTER_v3.vi where I initialize the camera and then acquire data by clicking "Start" button. I use "Picam_Acquire()" for this purpose. According to the manual this function automatically manages buffer memory with no user input. So I assume that after this function has acquired data, there should be already a buffer containing the data. Then, I am just trying to read this buffer and its size using "PicamAdvanced_GetAcquisitionBuffer()" function. I attach snippets of the TESTER_v3.vi and Get_AcquisitionBuffer.vi.
Could you please help me out to see what is not alright in 'Get_AcquisitionBuffer.vi'?
I also attach the unfinished SDK where you can find the source code for "TESTER_v3.vi" together with all other details.
Thank you very much.
02-12-2020 03:22 PM
One thing that is not alright I have spotted just now is that the last parameter of the first CLN should be configured as numeric (not a cluster) pointer-sized integer (inititialized as 0).
02-13-2020 11:31 AM - edited 02-13-2020 11:34 AM
@Zumbi wrote:
One thing that is not alright I have spotted just now is that the last parameter of the first CLN should be configured as numeric (not a cluster) pointer-sized integer (inititialized as 0).
I'm not sure what you try to say here? The first CLN is the one that calls the PicamAdvanced_GetAcquisitionBuffer() function, right? Because if you mean that you certainly should not just pass an integer to it but the cluster as is now. What I'm not understanding is what you are trying to do with the MoveBlock afterwards to copy 4 Bytes from the reference to the pointer into a numeric. That looks totally bogus. The way you set it up now you try to copy 4 bytes from the pointer reference into a NULL pointer and that simply doesn't work. MoveBlock in that way tries to store 4 bytes into a pointer that is invalid. What would be less wrong but still not useful is to set the first parameter to not be a pointer to value but simply by value only and the second an int32 passed as pointer to value. The third parameter is defined by LabVIEW to be a size_t which is a 32 bit integer in 32-bit LabVIEW and a 64-bit value in 64-bit LabVIEW, so you should configure that as pointer sized integer passed by value. In this way you would copy the first 4 bytes of the buffer into the int32, but that probably won't be a pointer but actual data.
More useful would be probably to initialize an array of bytes with memory_size elements and pass this as an Array Data Pointer to the second parameter of MoveBlock and the memory_size to the third parameter. But I haven't studied the Picam API. This are issues that are specific to the implementation and not described nor defined by the header file. This type of information what the memory and memory_size variables actually should mean is either contained in the API description document and/or in sample code showing how to call these APIs.
02-13-2020 03:03 PM - edited 02-13-2020 03:32 PM
Hi Rolf.
I have contacted a support team to ask what is expected as 'memory', and you were right about that it is probably an array of bytes. The following is the relevant quote that may help:
"Void* is just a pointer to a memory location. It has no data type. The AcquisitionBuffer structure is meant to be used with the PicamAdvanced_SetAcquisitionBuffer and PicamAdvanced_GetAcquisitionBuffer commands. The idea is that you initialize a byte array of some size (for example 3 * the readoutstride) and have the memory object point to the first element of that object. Please also note that you don’t need to set any buffer. If you don’t set any acquisition buffer, the API with auto-allocate memory. The manual acquisition buffer setting only comes into play when one wants to acquire thousands of frames, and the PC doesn’t have enough memory to declare a whole buffer to fit all those readouts."
I modified 'GetAcquisitionBuffer.vi' which you can see on the snippet below.
Also, I have discovered that it is possible to create a virtual demo camera using the function Picam_ConnectDemoCamera():
PICAM_API Picam_ConnectDemoCamera( PicamModel model, const pichar* serial_number, PicamCameraID* id );
where the last parameter can be null according to the manual. I thought that it would be great to work on the programming and be not dependent on the presence or absence of the actual camera.
The parameter 'PicamModel' is of an enumeration type where the element with the index 5 corresponds to the camera I am currently programming (PIXIS 100BR). Therefore I just use this number 5 instead of the enumeration type. Here is the snippet of my effort to implement 'Picam_ConnectDemoCamera(). I use 40 because there are 10 characters in the serial number multiplied by 4 bytes for each character. The error occurs in the last CLN (MoveBlock).
Finally, I wanted to use this subvi in the TESTER_v3.vi so that this virtual demo camera was connected instead of the real one. But of course, this doesn't work so far. I looked the serial number for the virtual camera in the application that I found on in the internet some time ago and which I also attach. The serial number shown within that application for PIXIS 100BR demo-camera is '00000:Demo'.
Finally, i attach the unfinished SDK. Could you please point at anything that you may find strange or weird which may probably help to get things work? Thank you for your help.
02-13-2020 03:18 PM - edited 02-13-2020 03:33 PM
That's better but not safe. You allocate a memory array of 3 * strideout but copy memory size bytes into it. What happens if memory size > 3 * strideout? Right, instant bumm!
It's not clear if that 3 * strideout was just a random example or something that is typically relevant for this API.
The safest would be to always only copy memory size bytes or less from the memory buffer into the array and of course never ever more than you allocated the array size.
And once you do that there is no need to pass out memory size as the array size is that size. And you did throw away support for 64-bit LabVIEW.
There is also no need to allocate a pointer and copy in a string, to pass it to a Call Library Node function. If you configure the according parameter as String, pass as String Data Pointer, LabVIEW will do the right thing for you. As you do it now you also create a memory leak as you absolutely have to match any DSNewPtr() with a call to DSDisposePtr().
PicamModel is an enum and the default datatype for that is an int32 not an int64. PicamCameraID is an struct, definitely wrong to pass in a u64. That is way to small and will crash when the DLL tries to copy all kind of data into that 8 byte data space.
02-14-2020 04:47 AM
Hi Rolf,
I have modified both Get_AcquisitionBuffer.vi and ConnectDemoCamera.vi.
In ConnectDemoCamera.vi, if I don't create a pointer explicitly then I am not sure what |I should use as the destination parameter in the MoveBlock CLN. Probably because of that MoveBlock gives an error.
Also, I found ready-made clusters in Ctls folder (thanks to Blokk) for PicamModel and PicamCameraID, so I just used them.
In Get_AcquisitionBuffer.vi I modified things around the MoveBlock CLN as well.
I also added back safety on different Labview bitness.
Probably I am getting close but there are still errors being shot out 😞
02-14-2020 06:01 AM
@Zumbi wrote:
In ConnectDemoCamera.vi, if I don't create a pointer explicitly then I am not sure what |I should use as the destination parameter in the MoveBlock CLN. Probably because of that MoveBlock gives an error.
Nothing! Just throw away the MoveBlock entirely and connect that string to the ConnectDemoCamera() directly. And configure it as String, pass as String Data Pointer as explained in my last message.
Also, I found ready-made clusters in Ctls folder (thanks to Blokk) for PicamModel and PicamCameraID, so I just used them.
There might be 32-bit, 64-bit alignment issues with clusters/structs.
In Get_AcquisitionBuffer.vi I modified things around the MoveBlock CLN as well.
I also added back safety on different Labview bitness.
Looks good as far as I can see. But forget that memory size in the PicamAcquisitionBuffer output. It is totally superfluous as the array size itself already contains this information. Just pass out that array and not the cluster.
02-14-2020 08:14 AM - edited 02-14-2020 08:27 AM
Rolf wrote: "Nothing! Just throw away the MoveBlock entirely and connect that string to the ConnectDemoCamera() directly. And configure it as String, pass as String Data Pointer as explained in my last message."
This seems to work or at least not to produce any error! 🙂
Now I realize that I probably cannot use the output parameter 'model' as a camera handle in order to configure this demo-camera further in the TESTER_v3.vi, but I am not sure how to get the handle for the demo-camera. I will look deeply through the manual.
Rolf wrote: "Looks good as far as I can see. But forget that memory size in the PicamAcquisitionBuffer output. It is totally superfluous as the array size itself already contains this information. Just pass out that array and not the cluster."
I am not sure if I clearly understand how I can pass out the array instead of the cluster. This seems to be going against the definition of the Picam_GetAcquisitionBuffer() function. What's the magic, Rolf? 🙂
02-14-2020 09:40 AM
I have found some C++ sample codes (ftp://ftp.princetoninstruments.com/Public/TechSupport/SL/Picam/PicamSamples.rar) which I also attach as source_code.7z. The file acquire.cpp clarified how I should deal with the demo-camera, so now this works in LabView (updated sandbox is attached).
Now when running the application TESTER_v3.vi and pressing START button, there is a InvalidHandle error at the Get_AcquisitionBuffer.vi. I am really not sure why the error is there as I checked the handles at the input and the output and they match. The only reason that comes to my mind is that something is messed up in the memory, as I pass handle as int64 while the input to the Get_AcquisitionBuffer CLN is configured as the pointer-sized integer passed by value. This doesnt give any error at the CLN itself though.
Also the error is generated by the error handler subvi as indicated on the snippet below.