ps5000a streaming callback

Post your .Net discussions here
Post Reply
simon1407
Newbie
Posts: 0
Joined: Wed May 20, 2015 8:40 am

ps5000a streaming callback

Post by simon1407 »

Morning,

I am attempting to write a program in c# that streams data from a picoscope 5442a. I have managed to hack something together so that it works but it requires me to put in 2 second sleeps.

My code is included below and I am finding that if I call the my StreamingGetData function without sleeping the thread that it for approximately 2 seconds to manually insert a pause, the callback function is never called. I check the return value of the call to ps5000aGetStreamingLatestValues but this always returns 0, indicating that there has been no error. However, without my 2 second pause my code then hangs as the callback is never executed. This appears to be a limitation that calling the ps5000aGetStreamingLatestValues function too quickly after starting streaming or the previous call to the get streaming latest values means that the callback is not executed.

I can get around this by manually coding 2 second thread sleeps but this is not a very robust solution and seems to not be stable if I change sampling intervals etc. Can you please advise if I have done something wrong with my code?

Thanks,
Simon

Code: Select all

        /* Streaming Mode functions */
        public void StreamingRun()
        {
            /* In 16-bit mode only one channel can be enabled at a time so 
             * firstly configure the picoscope for sampling the specified 
             * channel. (To do this all other channels have to be 
             * disabled.) */
            ConfigAllChannels();

            // TODO
            // Set any triggering

            /* Need to setup all buffers at the stard so that handles can be 
             * created. The handles are required to ensure that the memory is
             * not wiped while the driver C code is operating. The handles need
             * to be created here so they can be released later and you cannot
             * have a null handle so you have to create them all. The handles
             * could be put into a list but this would be more complicated. */
            streamBufPicoChanA = new short[streamingBufferLen];
            streamBufPicoChanB = new short[streamingBufferLen];
            streamBufPicoChanC = new short[streamingBufferLen];
            streamBufPicoChanD = new short[streamingBufferLen];

            /* Create handles to prevent the buffers from being cleared while
             * the driver c code is running. */
            hStreamBufPicoChanA = GCHandle.Alloc(streamBufPicoChanA, GCHandleType.Pinned);
            hStreamBufPicoChanB = GCHandle.Alloc(streamBufPicoChanB, GCHandleType.Pinned);
            hStreamBufPicoChanC = GCHandle.Alloc(streamBufPicoChanC, GCHandleType.Pinned);
            hStreamBufPicoChanD = GCHandle.Alloc(streamBufPicoChanD, GCHandleType.Pinned);

            /* Setup the data buffers for the picoscope*/
            if (chanAEn == 1)
            {
                CheckRet(ps5000aSetDataBuffer(_handle,
                    enPS5000AChannel.PS5000A_CHANNEL_A, streamBufPicoChanA,
                    streamBufPicoChanA.Length, 0,
                    enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE));
            }
            if (chanBEn == 1)
            {
                CheckRet(ps5000aSetDataBuffer(_handle,
                    enPS5000AChannel.PS5000A_CHANNEL_B, streamBufPicoChanB,
                    streamBufPicoChanB.Length, 0,
                    enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE));
            }
            if (chanCEn == 1)
            {
                CheckRet(ps5000aSetDataBuffer(_handle,
                    enPS5000AChannel.PS5000A_CHANNEL_C, streamBufPicoChanC,
                    streamBufPicoChanC.Length, 0,
                    enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE));
            }
            if (chanDEn == 1)
            {
                CheckRet(ps5000aSetDataBuffer(_handle,
                    enPS5000AChannel.PS5000A_CHANNEL_D, streamBufPicoChanD,
                    streamBufPicoChanD.Length, 0,
                    enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE));
            }

            /* Run Streaming mode */
            CheckRet(ps5000aRunStreaming(_handle, ref streamSampleInt, enPS5000ATimeUnits.PS5000A_MS, 1000, 1000, false, 1, enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE, (uint)(streamingBufferLen)));
        }
        // IMPORTANT NOTE: CALLING FUNCTION MUST WAIT ~2S BETWEEN CALLING THIS TO GUARANTEE IT RETURNS DATA
        public ScopeMeasurements StreamingGetData()
        {
            ScopeMeasurements data = new ScopeMeasurements();

            Debug.WriteLine("Requesting Streaming Samples", "Picoscope");

            _streamingCallbackDelegate = StreamingDataReadyCallback;
            
            /* Set the data available flag */
            _streamDataAvail = false;

            /* Command a picoscope data read */
            CheckRet(ps5000aGetStreamingLatestValues(_handle, _streamingCallbackDelegate, IntPtr.Zero));

            /* Wait for the data available flag to be set */
            while (!_streamDataAvail)
            {
                Thread.Sleep(100);
            }

            /* Use thread lock before accessing data */
            lock(streamBufLock)
            {
                if (chanAEn == 1)
                {
                    data.chanA = new short[streamBufNoSamp];
                    Array.Copy(streamBufPicoChanA, steamBufStartIdx, data.chanA, 0, streamBufNoSamp);
                }
                if (chanBEn == 1)
                {
                    data.chanB = new short[streamBufNoSamp];
                    Array.Copy(streamBufPicoChanB, steamBufStartIdx, data.chanB, 0, streamBufNoSamp);
                }
                if (chanCEn == 1)
                {
                    data.chanC = new short[streamBufNoSamp];
                    Array.Copy(streamBufPicoChanC, steamBufStartIdx, data.chanC, 0, streamBufNoSamp);
                }
                if (chanDEn == 1)
                {
                    data.chanD = new short[streamBufNoSamp];
                    Array.Copy(streamBufPicoChanD, steamBufStartIdx, data.chanD, 0, streamBufNoSamp);
                }
            }

            return data;
        }
        private void StreamingDataReadyCallback(short handle, int noOfSamples, uint startIndex, short overflow, uint triggeredAt, short triggered, short autoStop, IntPtr pVoid)
        {
            Debug.WriteLine("Streaming Data Ready Callback", "Picoscope");
            
            /* Use thread lock before accessing buffers */
            lock (streamBufLock)
            {
                /* Copy the start index and number of samples to return */
                streamBufNoSamp = noOfSamples;
                steamBufStartIdx = Convert.ToInt32(startIndex);
            }

            /* Set the data available flag */
            _streamDataAvail = true;
        }
        public void StreamingStop()
        {
            /* Command picoscope to stop streaming */
            ps5000aStop(_handle);

            /* Clear up memory buffers */        
            /* Release all of the handles now that the data has been read */
            hStreamBufPicoChanA.Free();
            hStreamBufPicoChanB.Free();
            hStreamBufPicoChanC.Free();
            hStreamBufPicoChanD.Free(); 
        }

Hitesh

Re: ps5000a streaming callback

Post by Hitesh »

Hi Simon,

Your streaming callback should copy the data from the driver buffers to application buffers.

Trying to access the driver buffers while the driver is busy collecting data could be causing the lock-up.

Please take a look at the solution in the attached zip file for reference - this should be available via the next SDK release.
PS5000AStreamingConsole.zip
C# streaming example for the ps5000a driver
(12.13 KiB) Downloaded 405 times
Regards,

Post Reply