I am coding on Windows11 MSVS, using the PicoSDK_64_10.7.22.241. See below more info on scope/driver/etc.
I am in streaming mode, doing what's suggested;
- ps5000aSetSimpleTrigger(no trigger)
- ps5000aSetDataBuffer()
- ps5000aRunStreaming()
- looping around ps5000aGetStreamingLatestValues()
All is working nicely, but the memory footprint is going up to the gigabytes steadily...
I do NOT allocate memory during the loop, even if I take out all my code, the used memory is increasing. Looks like a a memory leak, maybe in the driver? I know supposedly the driver stores the data, but how can I tell it to release the data as I already processed it? Or should I just use ps5000aGetValuesAsync() ?
But the manual suggest to use ps5000aGetStreamingLatestValues()... Any insights?
Best if you post your stripped down code so somebody can look at it.
I have had a PS4000 series scope running for months in streaming mode without a problem in C++.
Ok, after setting up the channels, ranges, etc, this is the code that loops.
Now, the data is indeed present in the buffer and I can use it, but for some reason the memory footprint is just growing... I suspect the driver still stores the data and does not release it?
If I try calling the GetValues() function from the callback, I get an error saying I'm already collecting.
uint8_t g_running = 1;
void PREF4 callBackStreaming(int16_t handle, int32_t noOfSamples, uint32_t startIndex, int16_t overflow, uint32_t triggerAt, int16_t triggered, int16_t autoStop, void* pParameter)
{
// Can not call ps5000aGetValuesAsync() here as it gives PICO_DRIVER_FUNCTION error (A driver function has already been called and not yet finished. Only one call to the driver can be made at any one time.)
// ps5000aGetValues() is for block mode only
// pParameter points to the collection buffer and startindex is at first sample there with noOfSamples -> Data is there.
if (autoStop) g_running = 0;
}
int8_t collectStreamingImmediate(UNIT* unit)
{
int16_t* driverBuffer[1];
PICO_STATUS status;
uint32_t sampleInterval;
if (PICO_OK != ps5000aSetSimpleTrigger(unit->handle, 0, PS5000A_CHANNEL_A, 0, PS5000A_RISING, 0, 0)) return 1;
if (NULL == (driverBuffer[0] = (int16_t*)calloc(DATA_BUFFER_SIZE, sizeof(int16_t)))) return 2;
// if (PICO_OK != ps5000aSetDataBuffers(unit->handle, (PS5000A_CHANNEL)0, NULL, NULL, 0, 0, PS5000A_RATIO_MODE_NONE)) return 3;
if (PICO_OK != ps5000aSetDataBuffer(unit->handle, (PS5000A_CHANNEL)0, driverBuffer[0], DATA_BUFFER_SIZE, 0, PS5000A_RATIO_MODE_NONE)) return 4;
sampleInterval = 256; // Sample at 256ns (8 ns per sample is max resolution) -> needs to be 2^
if (PICO_OK != ps5000aRunStreaming(unit->handle, &sampleInterval, PS5000A_NS, 0, 39062500, 1, 1, PS5000A_RATIO_MODE_NONE, DATA_BUFFER_SIZE)) return 4; // 10 seconds -> at every 256 ns
g_running = 1;
while (g_running)
{
status = ps5000aGetStreamingLatestValues(unit->handle, callBackStreaming, &driverBuffer);
}
ps5000aStop(unit->handle);
if (PICO_OK != ps5000aSetDataBuffer(unit->handle, (PS5000A_CHANNEL)0, NULL, 0, 0, PS5000A_RATIO_MODE_NONE)) return 5;
return 0;
}
You shouldn't pass &driverBuffer into the call back, this parameter is used for passing a parameter to the callback function to write values to, it is not related to the actual data. In most cases this can be a null pointer.
I'm having memory leak on my MacBook Pro Early 2013 running macOS Mojave (10.14.6). I'm using PicoScope 7.0.114.13320. I suspect either libiomp5.dylib or mono:
The leak happens both with the simulated device and the actual one (2000 Series).
By the way, PicoScope, as downloaded from your site, was crashing right after start. I have managed to let it run by downloading your SDK and substituting libpicoipp.1.dylib in the PicoScope package Resources by the one contained in the SDK.
The only other available version for PicoScope (last 6) does not even start. I have tried to install mono from their website and with Homebrew.
Would be nice to have a working software - I'm even considering returning this scope.
>>ps5000aGetStreamingLatestValues(unit->handle, callBackStreaming, &driverBuffer);
>You shouldn't pass &driverBuffer into the call back, this parameter is used for passing
>a parameter to the callback function to write values to, it is not related to the actual data.
>In most cases this can be a null pointer.
I thought I have to provide the user allocated buffer (driverBuffer) to ps5000aSetDataBuffer() for the driver to put the data into, no?
If I do that, I have to know into which buffer was the data read by the driver, thus I'm passing that info over to the callback, as I'm not using a global variable.
What am I missing?
What I really do not understand is that the memory footprint of the application grows, even when my user program is not allocating extra memory. Looks like the PicoTech driver keeps allocating more and more memory as it reads from the scope. Thus, my question, how should I tell the driver NOT to keep allocating buffers, but re-use the same one. What is the right usage (sample code?) for streaming data from the scope?
I found what the issue was. I set the maxPostTriggerSamples value in the ps5000aRunStreaming() function too high (GigaBytes). I wanted to collect a few billion samples streamed, and I set the maxPostTriggerSamples to that insanely high number.
For some reason, I thought that the maxPostTriggerSamples value has to be the same as the number of samples collected. Now I understand it has nothing to do with that.
I now set both maxPreTriggerSamples and maxPostTriggerSamples to 0, and simply stream the data from the scope to my ring buffer from which an other thread writes it to file.