Test and Measurement Forum

Working with multiple picoscopes

Post your .Net discussions here

Working with multiple picoscopes

Postby mzeeshan » Mon Nov 06, 2017 5:20 am

Hello,

I have been working on an application with multiple picoscopes. I started with a single channel first. Previously, I had posted a question regarding my requirements of acquisition in block mode at 10Hz rate (https://www.picotech.com/support/topic30981.html). At that time when I tried to run everything within a 10Hz timer, the random delay in RunBlock and GetValues caused problems after several packets. So to solve that I came up with the following solution (which is the current structure I'm following):

The program works in two parts:

A) In data capturing part, commands to RunBlock and GetValues are sent much faster than 10Hz and the results are copied to another buffer.
B) At every 10Hz timer tick, the data processing part copies the value in the buffer to its own buffer for processing.

This makes sure that data processing part does not have to wait for the delay in RunBlock and GetValues and gets the latest packet from the input signal.

Now all this works well for a single picoscope which is actually a Windows form running on a separate thread. However, when I run multiple picoscopes (four at a time), each running on a separate thread, I observe some random stalling in a random picoscope. All picoscopes work well for a short period of time and then randomly some picoscope seems to be unable to get a new value. I have been trying to trace the problem for long time (its difficult since everything happens in realtime and with four picoscopes) but finally I found that the problem occurs because of random high delay in GetValues command. Once the command is sent before that problem occurs, the program gets stuck at GetValues for as long as a few seconds sometimes and then a new value is copied to the buffer. Now I check the buffer is not occupied during that time.

So, I came to the conclusion that the picoscope cannot get the access to the USB sometimes and once it loses access its hard to get it since all other picoscopes are always trying to access the USB at a rate higher than 10Hz. This of course forced me to check my USB connections. The four picoscopes all connect with a 4 port, USB 3.0 hub which then connects to a USB 3.0 port on the PC. I quickly checked with individually connecting each picoscope with a single USB 3.0 port (fortunately they were available on the PC) but the problem did happen again.

I connected the 4 picoscopes back to the hub as I quickly thought about testing your PicosScope 6 software. I opened 4 instances and as I watched the waveforms, even though I could see very very short jerks (almost not perceivable) but I did not see that problem. Now that could mean that may be you guys of course do not have the requirement of fixed 10 Hz so probably you can work with the random delay sometimes.

But now here is the question that popped in my head after all this, does the picoscope driver or the USB controlling driver treats simultaneous USB access requests from the same process differently as compared to the requests from separate applications? Since all picoscopes even though running on separate thread, still belong to the same process in a single application. So may be if I try to run each picoscope in a separate application, it might work? Also do you think that the four picoscopes to a single USB 3.0 at rate higher than 10Hz can take up all the data rate bandwidth of USB 3.0?

Need your help regarding all this please.

Thank you for reading this long post.

Best regards,

Shan
mzeeshan
Newbie
 
Posts: 0
Joined: Wed Jun 28, 2017 7:26 am

Re: Working with multiple picoscopes

Postby Martyn » Mon Nov 06, 2017 8:49 am

It would help to know some more detail about your data collection :-

1. How many samples you are collecting in each block ?
2. How many channels are enabled on each device ?
3. What is the sample interval ?
4. Is this the same for all of the scopes ?
Martyn
Technical Support Manager
Martyn
Site Admin
Site Admin
 
Posts: 2816
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: Working with multiple picoscopes

Postby mzeeshan » Tue Nov 07, 2017 5:27 am

Sure here are the details

1) Sample count = 47, Timebase = 3, Signal frequency ~13MHz
2) Both channels enabled on 5242A
3) Timebase = 3 --> Sample interval = 8ns
4) All four picoscopes have the same configuration

Here's how Im getting the block in a loop. (The loop only has a small 25ms sleep time, other than that it keeps running so that it can get at least a single value every 0.1s duration, and the data processing module running at 10Hz, can copy this latest value for processing.)

Code: Select all
while (!stopPicoscope) //is set to true if user stops the processing
            {
                do
                {
                    retry = false;
                    status = Imports.RunBlock(_handle, 0, (int)sampleCount, _timebase, out timeIndisposed, 0, _callbackDelegate, IntPtr.Zero);

                    if (status == (short)StatusCodes.PICO_POWER_SUPPLY_CONNECTED || status == (short)StatusCodes.PICO_POWER_SUPPLY_NOT_CONNECTED || status == (short)StatusCodes.PICO_POWER_SUPPLY_UNDERVOLTAGE)
                    {
                        status = Imports.ChangePowerSource(_handle, status);
                        retry = true;
                    }
                    else
                    {
                        //textMessage.AppendText("Run Block Called\n");
                    }
                }
                while (retry);

                while (!_ready)
                {
                    //Thread.Sleep();
                }

                Imports.Stop(_handle);

                if (_ready)
                {
                    short overflow;
                    status = Imports.GetValues(_handle, 0, ref sampleCount, 1, Imports.DownSamplingMode.None, 0, out overflow);

                   
                        if (copyNewValues) // is set to true in data processing module after data has been copied from receivedDataTmpChA/B buffer to dataprocessing module's own buffer
                        {
                            Array.Copy(maxBuffersChA, receivedDataTmpChA, maxBuffersChA.Length);
                            Array.Copy(maxBuffersChB, receivedDataTmpChB, maxBuffersChB.Length);
                            copyNewValues = false;
                        }                 

                    if (status == (short)StatusCodes.PICO_OK)
                    {
                        //textMessage.AppendText("Have Data\n");                       
                    }
                    else
                    {
                        //textMessage.AppendText("No Data\n");
                    }
                }
                else
                {
                    //textMessage.AppendText("data collection aborted\n");
                }

                Imports.Stop(_handle);
                Thread.Sleep(25);
            }
mzeeshan
Newbie
 
Posts: 0
Joined: Wed Jun 28, 2017 7:26 am

Re: Working with multiple picoscopes

Postby Martyn » Tue Nov 07, 2017 11:04 am

I am not sure I fully understand what you are trying to achieve, so a couple more questions.

Every time you RunBlock are you expecting to collect the block of 47 samples per channel and pass it up to the processing application, or does the processing application only need a block of 47 samples per channel every 0.1 seconds ?

Are you making use of any trigger functionality ?
Martyn
Technical Support Manager
Martyn
Site Admin
Site Admin
 
Posts: 2816
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: Working with multiple picoscopes

Postby mzeeshan » Tue Nov 07, 2017 1:48 pm

Thanks for the reply. I'm trying to get a data block every 10Hz with a little time to spare for processing but because of some randomly high delay in getting a block of data sometimes there is not enough time for processing the received block. Hence I'm trying to solve the issue by requesting the data block not every 10Hz but at a faster rate and then at every 10Hz timer tick event I capture the last saved data block.

So with every RunBlock command I just receive the data block and copy it into a buffer. That means it the buffer gets updated value always at a rate faster than 10Hz. Data processing module runs every 10Hz in the timer's tick event, where it copies the latest value from buffer and exactly after finishing copying and before starting to process that block, it sets the copyNewValues to true so that the data acquisition part can save the updated value to the buffer at the very next time RunBlock command runs.

Ideally if there had been a fixed, small delay for receiving a block of data, I could have easily requested for a new block in the tick event of the timer and then processed it.

BTW, 47 samples is an estimate to get at least 3 to 5 sine waves of the input signal.

Yes I tried to use SetSimpleTrigger but it does not really work well for a small number of samples in a few sine waves at this timebase. Also, since the delay I'm detecting is on GetValues so I think that's after the trigger has been found.

I just checked with multiple instances of the application, each getting data from a picoscope but I'm still getting the stalling and delays randomly.

Do you think I'm keeping the USB too busy?

Regards,

Shan
mzeeshan
Newbie
 
Posts: 0
Joined: Wed Jun 28, 2017 7:26 am

Re: Working with multiple picoscopes

Postby Martyn » Tue Nov 07, 2017 10:04 pm

I would look to setup a 10Hz square wave output on the sig gen and feed this into the external trigger input on the scope. Then you can trigger data collection of just one block at exactly 10Hz, even using the same signal to trigger all scopes. Trigger rearming takes between 1 and 60 msecs due to USB latency which falls well within the 100msec capture rate.
Martyn
Technical Support Manager
Martyn
Site Admin
Site Admin
 
Posts: 2816
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: Working with multiple picoscopes

Postby mzeeshan » Thu Nov 09, 2017 5:42 am

Thanks Martyn. That's a good idea because I can see that even though using accurate Multimedia timers in .NET they still get strongly affected by some other tasks on the PC. So a single channel is working perfectly until a second channel is started. The timer also gets disturbed.

I can setup the signal generator at 10 Hz square wave not problem. Could you please let me know how to setup block mode to trigger with EXT input? What are good values for square wave amplitude and trigger?
mzeeshan
Newbie
 
Posts: 0
Joined: Wed Jun 28, 2017 7:26 am

Re: Working with multiple picoscopes

Postby mzeeshan » Thu Nov 09, 2017 7:42 am

So, I tried to setup signal generator and connected the output to EXT. I then setup the signal generator to generate 1 Hz square wave (for testing). It works in PicoScope 6, but I could not get proper triggering in my .Net app with the same configuration. If I make the threshold 0, the RunBlock just captures the packet without waiting 1 second for the triggers rising edge. If I increase the threshold, it just does not trigger at all.

Could you please check whats wrong with this code:

Code: Select all
public void getBlockDataTmp()
        {
            uint status;

            //---------------------------------------------------------------------------------------------------------------------------------
            //*********************************               Initialize signal gen           *************************************************
            //---------------------------------------------------------------------------------------------------------------------------------

            try
            {
                startFreq = Convert.ToDouble("1");
                pkToPk = 2000000; //1v?
                offset = Convert.ToInt32("0");

            }
            catch
            {
                MessageBox.Show("Error with start frequency, offset and/or pktopk", "INVALID VALUES", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }


            stopFreq = startFreq;
            increment = 0;
            dwellTime = 0;
            sweeptype = Imports.SweepType.PS5000A_UP;

            Imports.WaveType wavetype = Imports.WaveType.PS5000A_SQUARE;// PS5000A_SINE;

            if (wavetype == Imports.WaveType.PS5000A_DC_VOLTAGE)
            {
                pkToPk = 0;
            }

            status = Imports.SetSigGenBuiltInV2(_handle, offset, pkToPk, wavetype, startFreq, stopFreq, increment, dwellTime, sweeptype,
                                                    operations, shots, sweeps, triggertype, triggersource, extinthreshold);

            if (status != StatusCodes.PICO_OK)
            {
                MessageBox.Show("Error SetSigGenBuiltInV2 error code :" + status.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            status = Imports.SetSigGenBuiltInV2(_handle, offset, pkToPk, wavetype, startFreq, stopFreq, increment, dwellTime, sweeptype,
                                                    operations, shots, sweeps, triggertype, triggersource, extinthreshold);

            //---------------------------------------------------------------------------------------------------------------------------------


            chRange = 10;

            status = Imports.SetChannel(_handle, Imports.Channel.ChannelA, 1, Imports.Coupling.PS5000A_DC, Imports.Range.Range_10V, 0);
            status = Imports.SetChannel(_handle, Imports.Channel.ChannelB, 1, Imports.Coupling.PS5000A_DC, Imports.Range.Range_10V, 0);
            //status = Imports.SetChannel(_handle, Imports.Channel.ChannelC, 0, Imports.Coupling.PS5000A_DC, Imports.Range.Range_10V, 0);
            //status = Imports.SetChannel(_handle, Imports.Channel.ChannelD, 0, Imports.Coupling.PS5000A_DC, Imports.Range.Range_10V, 0);

            short enable = 1;
            uint delay = 0;
            short threshold = 0;
            short auto = 0;

            status = Imports.SetSimpleTrigger(_handle, enable, Imports.Channel.External, threshold, Imports.ThresholdDirection.Rising, delay, auto);

            _ready = false;
            _callbackDelegate = BlockCallback;
            _channelCount = 4;
           
            PinnedArray<short>[] minPinned = new PinnedArray<short>[_channelCount];
            PinnedArray<short>[] maxPinned = new PinnedArray<short>[_channelCount];

            int timeIndisposed;
            minBuffersChA = new short[sampleCount];
            maxBuffersChA = new short[sampleCount];
            minBuffersChB = new short[sampleCount];
            maxBuffersChB = new short[sampleCount];
            bufferValueChA = new short[sampleCount];
            bufferValueChB = new short[sampleCount];

            minPinned[0] = new PinnedArray<short>(minBuffersChA);
            maxPinned[0] = new PinnedArray<short>(maxBuffersChA);
            minPinned[1] = new PinnedArray<short>(minBuffersChB);
            maxPinned[1] = new PinnedArray<short>(maxBuffersChB);
            status = Imports.SetDataBuffers(_handle, Imports.Channel.ChannelA, maxBuffersChA, minBuffersChA, (int)sampleCount, 0, Imports.RatioMode.None);
            status = Imports.SetDataBuffers(_handle, Imports.Channel.ChannelB, maxBuffersChB, minBuffersChB, (int)sampleCount, 0, Imports.RatioMode.None);

           
            int maxSamples;
            while (Imports.GetTimebase(_handle, _timebase, (int)sampleCount, out timeInterval, out maxSamples, 0) != 0)
            {
                //textMessage.AppendText("Timebase selection\n");
                _timebase++;

            }
            _timebase = 3;

           
            //textMessage.AppendText("Timebase Set\n");

            /* Start it collecting, then wait for completion*/
            _ready = false;
            _callbackDelegate = BlockCallback;

            while (!acqStopped)
            {               
                do
                {
                    retry = false;
                    status = Imports.RunBlock(_handle, 0, (int)sampleCount, _timebase, out timeIndisposed, 0, _callbackDelegate, IntPtr.Zero);
                   
                    if (status == (short)StatusCodes.PICO_POWER_SUPPLY_CONNECTED || status == (short)StatusCodes.PICO_POWER_SUPPLY_NOT_CONNECTED || status == (short)StatusCodes.PICO_POWER_SUPPLY_UNDERVOLTAGE)
                    {
                        status = Imports.ChangePowerSource(_handle, status);
                        retry = true;
                    }
                    else
                    {
                        //textMessage.AppendText("Run Block Called\n");
                    }
                }
                while (retry);
               
                while (!_ready)
                {
                    //Thread.Sleep();
                }
               
                Imports.Stop(_handle);

                if (_ready)
                {
                    short overflow;

                   
                    status = Imports.GetValues(_handle, 0, ref sampleCount, 1, Imports.DownSamplingMode.None, 0, out overflow);
                   
                    if (status == (short)StatusCodes.PICO_OK)
                    {
                       
                    }
                    else
                    {
                        //textMessage.AppendText("No Data\n");

                    }
                }
                else
                {
                    //textMessage.AppendText("data collection aborted\n");
                }               
                Imports.Stop(_handle);
               
                //Thread.Sleep(25);             
            }
            foreach (PinnedArray<short> p in minPinned)
            {
                if (p != null)
                    p.Dispose();
            }
            foreach (PinnedArray<short> p in maxPinned)
            {
                if (p != null)
                    p.Dispose();
            }

        }
mzeeshan
Newbie
 
Posts: 0
Joined: Wed Jun 28, 2017 7:26 am

Re: Working with multiple picoscopes

Postby Martyn » Wed Nov 15, 2017 9:32 am

It would be easier if you could send in your project, zipped up but without exe and dll files, to support@picotech.com
Martyn
Technical Support Manager
Martyn
Site Admin
Site Admin
 
Posts: 2816
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots


Return to .Net Languages (C#, VB.Net, .)

Who is online

Users browsing this forum: No registered users and 1 guest