C# UsbDrDaq Problem with UsbDrDaqGetValues

Post your .Net discussions here
evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Hello, i have a little problem with UsbDrDaq UsbDrDaqGetValues, i try to continous capture data from UsbDrDaq with BM_STREAM.
I have used the code from collect_streaming (USBDrDAQcon.c) ported for C#

It works well if i use one channel (like in the example) but if i want to record 2 channels, i have th problem that the array positions change related to the channel.

let me explain: during the first call of UsbDrDaqGetValues i get the first channel data on array pos 0, 2, 4, ... and the second channel at 1, 3, 5, ...

but if i get multiple times this positions change!, ok, i was thinking if the last capture delivers channel one on the last position then the next block beginns with channel 2, but this is even not correct!!

UsbDrDaqGetValues seems to deliver the channels in no expeced order, or i have messed up something, there is my code:

First my DllImports

Code: Select all

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqOpenUnit(ref short handle);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqCloseUnit(short handle);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqRun(short handle, uint noOfValues, byte method);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqReady(short handle, ref short ready);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqStop(short handle);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqSetInterval(short handle, ref uint usForBlock, uint idealNoOfSamples,
                                                      uint[] channels, short noOfChannels);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqSetTrigger(short handle, short usFenabledorBlock, short autoTrigger,
                                                     short autoMs, short channel, short dir, short threshold,
                                                     short hysterisis, float delay);

        [DllImport("USBDrDAQ.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int UsbDrDaqGetValues(short handle, short[] values, ref uint noOfValues,
                                                    ref short overflow, ref uint triggerIndex);
here is my code to capture the data (working in a WorkerThread appart from the programm logic)

Code: Select all

short handle;
int status = 0;
const uint nSamples = 20000; //maximal possible samples
const uint nSampleBufferSize = nSamples * 2 * 2; //large enought buffer
var samples = new short[nSampleBufferSize]; //buffer
uint usForBlock = 100 * 1000; //get blocks each 100ms
var channels = new uint[] { 1, 4 }; //ext1 = 1, scope = 4
short nChannels = 2;

//worker variables
uint nSamplesCollected = nSampleBufferSize;
short overflow = 0;
uint triggerIndex = 0;
int sleepTime = Convert.ToInt32(usForBlock/1000); //sleep time for worker thread (100ms)
_shouldStop = false;

//Open Unit
if (UsbDrDaqOpenUnit(ref handle) != 0)
	throw new Exception("Error on Open");

//Set the trigger (disabled)
status = UsbDrDaqSetTrigger(handle, 0, 0, 0, 0, 0, 0, 0, 0);
if (status != 0)
	throw new Exception(string.Format("Error on UsbDrDaqSetTrigger {0}", status));

//set sampling rate and channels
status = UsbDrDaqSetInterval(handle, ref usForBlock, nSamples, channels, nChannels);
if (status != 0)
	throw new Exception(string.Format("Error on UsbDrDaqSetInterval {0}", status));

//Start streaming
status = UsbDrDaqRun(handle, nSamples, 2);
if (status != 0)
	throw new Exception(string.Format("Error on UsbDrDaqReady {0}", status));

//Wait until unit is ready
short isReady = 0;
while (isReady == 0)
{
	status = UsbDrDaqReady(handle, ref isReady);
	if (status != 0)
		throw new Exception(string.Format("Error on UsbDrDaqReady {0}", status));
}

//get first measure and throw it (incomplete set of data)
status = UsbDrDaqGetValues(handle, samples, ref nSamplesCollected, ref overflow, ref triggerIndex);
if (status != 0)
	throw new Exception(string.Format("Error on First UsbDrDaqGetValues {0}", status));

//wait to complete
Thread.Sleep(sleepTime);

//start working loop
while (!_shouldStop)
{
	//reset worker vars
	nSamplesCollected = nSampleBufferSize;
	overflow = 0;
	triggerIndex = 0;

	//get values from DrDaq
	status = UsbDrDaqGetValues(handle, samples, ref nSamplesCollected, ref overflow, ref triggerIndex);
	if (status != 0)
		throw new Exception(string.Format("Error on Loop UsbDrDaqGetValues {0}", status));

	//define output array with correct size
	var sampleList = new short[nSamplesCollected];

	//transfer values to output array
	for (var index = 0; index < nSamplesCollected; index++)
		sampleList[index] = samples[index];

	//detect overflow
	if (overflow != 0)
		Debug.WriteLine("-- OverFlow --" + overflow);
	
	//pass sampleList to main process, in the main process this data will be processed
	//!!sampleList array positions are not the same for each call of UsbDrDaqGetValues!!
	((BackgroundWorker)workerObject).ReportProgress(0, sampleList);
	
	//wait for next capture
	Thread.Sleep(sleepTime);
}

//stop DrDaq
status = UsbDrDaqStop(handle);
if (status != 0)
	throw new Exception(string.Format("Error on UsbDrDaqStop {0}", status));

//close Unit
if(UsbDrDaqCloseUnit(handle) != 0)
	throw new Exception("Error on Close");
I hope somebody can explain how i can solve this problem, cause this was i cant interpret the values from the channels the right way.

thanks in advance

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Any Feedback? Maybe from officials could be a bug?

Karunen
Advanced User
Advanced User
Posts: 194
Joined: Thu Nov 21, 2013 9:22 am

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by Karunen »

Hi Evo_racer,

Please accept my apologies I am currently looking into this.

Do you know which version of the dll you are using?

An easy way to find out is by using the UsbDrDaqGetUnitInfo function.

Thanks,
Karunen

Technical Specialist
Pico Technology

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Sorry, was a few days on vacation,

My version is:
USBDrDAQ.dll version 1.0.0.227
PICOPP.SYS V1.0

the strange thing is, the PicoScope displays the data correctly, only the API seems to have the problem or creates a problem interfacing with C# (for this reason maybe check my imports in the code upon)

thanks in advice

Karunen
Advanced User
Advanced User
Posts: 194
Joined: Thu Nov 21, 2013 9:22 am

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by Karunen »

Hi Evo_racer,

Please accept my apologies about the late reply.

Using your code I was able to get the correct data.

Below is the code that I used to spilt the array and export to file.

Code: Select all

for (uint index = 0; index < nSamplesCollected; index ++)
{
   if (index % 2 == 0 || index == 0)
   {
      file1.WriteLine(samples[index].ToString());
   }
   else
   {
      file2.WriteLine(samples[index].ToString());
   }
}
You may need to reduce the thread sleep as the device does not have a large memory,
so you will miss data if you are not grabbing the values fast enough.

Thanks,
Karunen

Technical Specialist
Pico Technology

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Thanks for your answer.

i have used a similar code (i % 2 == 0) in my programm as well,
but your suggestion about the buffer size (thread sleep) could solve my problem.

i try it in the next few days.

what values do you suggest for the fastest possible sample rate with two channels?

i have 20.000 samples each 100ms, i try it later with 4000 samples each 20ms, but the only thing why i used a longer sleep is the precission of windows thread sleep (~16ms accurate) so i have much less different block sizes with 100ms (but how ever this is not realy counting for my code?

but one thing i don't understand is, in documentation is written max possible sampling interval is 10
microseconds.

= 100 samples 1 milliseconds = 10000 samples / 100ms, but the device is also working with 20.000 / 100ms (see my code)

what maximal values do you suggest?
what maximum buffersize do you suggest (device memory) cause cant find a value in the documentation

thanks
i give feedback later if the buffer size was the problem

Karunen
Advanced User
Advanced User
Posts: 194
Joined: Thu Nov 21, 2013 9:22 am

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by Karunen »

Hi Evo_racer,

The 10 microsecond sample interval was from a test done previously to find out how fast you can stream data across the USB port.

Although the device can collect data at a lot faster rates, the issue is that once the device has filled up its 16KS buffer it will stop collecting new data.

Therefore the limiting factor is how fast you can take the data from the device.

This will depend on the fast you can get the data across USB port which will depend on the PC and the set up are you have.

Please note if the device fails to send across the data then it will have to resend,
which can cause additional delays.

As all I was doing was grabbing data as quickly as possible (no sleeps or processing on the data) and exporting to file.
This should not have much strain on the USB port, this is why I did not see any gaps in the data.

Thanks,
Karunen

Technical Specialist
Pico Technology

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Hi Karunen,

Sorry for my late response, but i have to do some major rewrites of my programm for final testing.

i can't remove the sleep totaly cause i need a realtime feedback for my UI, but i have reduced sleep to 15ms, and the device delivers a constant stream of with ~100.000 samples per second (thats ok)

nSamples = 5000
usForBlock = 50 * 1000

this way i get data without gaps or missing parts and the device buffer and USB speed is fast enougth.

but if i add the second channel, i must reduce the nSamples to 2500. (else i get error on UsbDrDaqSetInterval)
this results in a sample rate of 50.000 samples per second and half of the samples are for channel 1 half channel 2.

this means we have 25.000 samples per second. i was expecting 50.000 samples per second on 2 channels.

did i have done something wrong?

did you have any 2 channel streaming example for DrDaq? I prefer c# but if you have it in c++ its also ok.

thanks

Karunen
Advanced User
Advanced User
Posts: 194
Joined: Thu Nov 21, 2013 9:22 am

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by Karunen »

Hi evo_racer,

One thing is that if you set 5,000 samples over 50,000 us you will get 25 samples per second across each channel.

When you set the sample interval you need to choose the totally sample so if you want 50 samples per second on each channel you must tell the device 100 samples per second.

Regarding the example could you please email support@picotech.com where we can discus this further.

Thanks,
Karunen

Technical Specialist
Pico Technology

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Hi Karunen,

i don't understand your calculation.

i have configured the device to get 5000 samples over 50.000us (50ms), if i calculate this are 100 samples each ms and this is 100.000 samples per second (according my calculations). I don't unserstand how you get 25 samples per second...

But the strange thing is, 100.000 samples per second is working with one channel!
if i add the second channel, UsbDrDaqSetInterval returns an error (Not PICO_OK) (sorry for not providing the exact enum, but i think its PICO_INVALID_PARAMETER) the strange thing is, if i lower the sample rate by reducing nSamples to 2500 it works!

but like i told with 25.000 samples per second.

if i rise nSamples to 2600 (same error as i had with 5000)

if i use only one channel i dan use 5000 but is i rise to 5100 i have the same error like on 2600 with 2 channels.

sorry for my confusing description, if you want a more clear example, i provide you a complete demo code!

Regarding the example, i write you a email.

Thanks for your help

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Hi Karunen,

first thank you for your example via mail.

i have watched your example and i see that you collected 100 samples per second, but i neet to get 100.000 per second (this is possible according the drdaq documentation page 17: UsbDrDaqSetInterval:
The fastest possible sampling interval is 1 microsecond, when the number of samples
is 8192 divided by the number of channels active and the capture mode is
BM_SINGLE. Under all other conditions, the fastest possible sampling interval is 10
microseconds.
1/10 microseconds = 100 / 1 millisecond = 100.000 / 1 sec

i still have my problem described above, i have modified your example a bit to show you the problem,
here is the modified code:

Code: Select all

        static void Main()
        {
            //my target is to get 100.000 samples per second!

            short handle = 0;
            int status = 0;
            const uint nSamples = 5000;
            const uint nSampleBufferSize = nSamples * 2;
            var samples = new short[nSampleBufferSize];
            uint usForBlock = 50 * 1000; //get blocks each 50ms

            //this is not working (should get 50.000 samples/sec @two channels)
            //error UsbDrDaqRun 2B PICO_INVALID_SAMPLE_INTERVAL!!
            //if i change nSamples to 2500 its working but i get only 25.000 samples/sec @two channels
            //my question is how to get 100.000 samples with two channels (50.000 each channel)?
            var channels = new uint[] { 1, 4 }; //ext1 = 1, scope = 4

            //this is working!!! (100.000 samples/sec @one channel)
            //var channels = new uint[] { 1 }; //ext1 = 1, scope = 4

            short nChannels = (short)channels.Length;

            //worker variables
            uint nSamplesCollected = nSampleBufferSize;
            short overflow = 0;
            uint triggerIndex = 0;
            int sleepTime = Convert.ToInt32(usForBlock / 1000); //sleep time for worker thread (100ms)

            //Open Unit
            if ((status = Imports.UsbDrDaqOpenUnit(ref handle) )!= 0)
                throw new Exception(string.Format("Error on Open {0}", status));

            //Set the trigger (disabled)
            status = Imports.UsbDrDaqSetTrigger(handle, 0, 0, 0, 0, 0, 0, 0, 0);
            if (status != 0)
                throw new Exception(string.Format("Error on UsbDrDaqSetTrigger {0}", status));

            //set sampling rate and channels
            status = Imports.UsbDrDaqSetInterval(handle, ref usForBlock, nSamples, channels, nChannels);
            if (status != 0)
                throw new Exception(string.Format("Error on UsbDrDaqSetInterval {0}", status));

            //Start streaming
            status = Imports.UsbDrDaqRun(handle, nSamples, 2);
            if (status != 0)
                throw new Exception(string.Format("Error on UsbDrDaqRun {0}", status));

            //Wait until unit is ready
            short isReady = 0;
            while (isReady == 0)
            {
                status = Imports.UsbDrDaqReady(handle, ref isReady);
                if (status != 0)
                    throw new Exception(string.Format("Error on UsbDrDaqReady {0}", status));
            }

            //get first measure and throw it (incomplete set of data)
            status = Imports.UsbDrDaqGetValues(handle, samples, ref nSamplesCollected, ref overflow, ref triggerIndex);
            if (status != 0)
                throw new Exception(string.Format("Error on First UsbDrDaqGetValues {0}", status));

            //wait to complete
            Thread.Sleep(0);

            TextWriter file1 = new StreamWriter("stream1.txt", false);
            TextWriter file2 = new StreamWriter("stream2.txt", false);

            long sumSamples = 0;
            var timer = new Stopwatch();
            timer.Start();

            Console.WriteLine("Capture started... (duration ~10 sec)");

            //start working loop
            while (timer.ElapsedMilliseconds < 10 * 1000)
            {
                //reset worker vars
                nSamplesCollected = nSampleBufferSize;
                overflow = 0;
                triggerIndex = 0;

                //get values from DrDaq
                status = Imports.UsbDrDaqGetValues(handle, samples, ref nSamplesCollected, ref overflow, ref triggerIndex);
                if (status != 0)
                    throw new Exception(string.Format("Error on Loop UsbDrDaqGetValues {0}", status));

                sumSamples += nSamplesCollected;
                for (uint index = 0; index < nSamplesCollected; index ++)
                {
                    if (index % 2 == 0 || index == 0)
                    {
                        file1.WriteLine(samples[index].ToString());
                    }
                    else
                    {
                        file2.WriteLine(samples[index].ToString());
                    }
                }

                    //wait for next capture
                   Thread.Sleep(0);
            }

            file1.Close();
            file2.Close();
            timer.Stop();

            //stop DrDaq
            status = Imports.UsbDrDaqStop(handle);
            if (status != 0)
                throw new Exception(string.Format("Error on UsbDrDaqStop {0}", status));

            //close Unit
            if (Imports.UsbDrDaqCloseUnit(handle) != 0)
                throw new Exception("Error on Close");

            //summary
            Console.WriteLine("TotalTime: " + timer.ElapsedMilliseconds);
            Console.WriteLine("TotalSamplesCaptured: " + sumSamples);
            Console.WriteLine("Samples/Block: " + nSamples + " MilliSeconds/Block: " + usForBlock / 1000);
            Console.WriteLine("Calculated Samples/Sec: " + Math.Round((((double)nSamples * 1000) / ((double)usForBlock / 1000)), 3));
            Console.WriteLine("Samples/Sec: " + Math.Round(((double)sumSamples / timer.ElapsedMilliseconds * 1000), 3));

            Console.WriteLine("Press any Key to Close.");
            Console.ReadKey();
        }

Karunen
Advanced User
Advanced User
Posts: 194
Joined: Thu Nov 21, 2013 9:22 am

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by Karunen »

Hi evo_racer,

Please accept my apologies I misunderstood I read the wrong values :oops:

Could you try using

Code: Select all

const uint nSamples = 50000;
uint usForBlock = 50 * 10000; //get blocks each 500ms
Kind Regards,
Karunen

Technical Specialist
Pico Technology

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

No problem, :D

i tryed your values:

Code: Select all

const uint nSamples = 50000;
uint usForBlock = 500 * 1000; //get blocks each 500ms
the error disapears, and capture starts normaly, but the device gets again only 50.000 samples per second!

you can use my code above to reproduce my problem.

the source of the problem is that the usForBlock value will be changed by UsbDrDaqSetInterval to 1000000 (1sec)
then this is again 50.000 samples per second (25.000 for each channel) (maybe this could be a bug?)

i tryed a lot of value combinations, each nSamples > 10000 results in a change of usForBlock after UsbDrDaqSetInterval
each usForBlock < 50 * 1000 results into a to slow sample rate (just compare Calculated Samples / Sec and Sample / Sec output)

each value between results into Error "PICO_INVALID_PARAMETER"

I have realy no idea how the parameter should be set to get 100.000 samples.

Karunen
Advanced User
Advanced User
Posts: 194
Joined: Thu Nov 21, 2013 9:22 am

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by Karunen »

Hi Evo_racer,

This is unfortunately a documentation error.

Please look at the table in the link below

http://www.drdaq.com/specifications.html

It shows the sampling rate achievable USB streaming is 100kHz shared across active channels.

So for two active channels that means the sampling rate is 50kHz.

The driver will change the time block you are measuring into a more appropriate value.

Code: Select all

status = Imports.UsbDrDaqSetInterval(handle, ref usForBlock, nSamples, channels, nChannels);
If you set a break point after this code you will be able to see that usForBlock has changed value to get 50kHz sampling rate.

Thanks,
Karunen

Technical Specialist
Pico Technology

evo_racer
Newbie
Posts: 0
Joined: Mon Mar 31, 2014 11:51 pm

Re: C# UsbDrDaq Problem with UsbDrDaqGetValues

Post by evo_racer »

Hi Karunen,

Thanks for your Statement.

If this is realy a documentation error it would be a bit annoing for me, then i probably need ~50.000 samples to have a accurate solution for my problem.

But how ever, if this is a fact i can't change it, but the only strange thing according my experience it's strange that DrDaq is working this way.

I have tryed several data logger and normaly it works like this: if we have 100khz @ 1 channel:
2 channels = 50khz + 50khz, 4 channels = 25khz + 25khz + 25khz + 25khz, ...

even in this documentation: http://www.drdaq.com/specifications.html

USB streaming: 100 kHz# #Shared between active channels.

If thge active channels are "sharing" 100khz then it would be CH1: 50khz + CH2: 50khz on 2 channels (this is like sharing normaly works)

and 50khz => 50.000 samples for channel1 + 50.000 samples for channel2 => summ = 100.000

please review this, because its not logical that sharing 100khz between 2 channels results into 2x 25khz!

Thanks

Post Reply