Test and Measurement Forum

Can't make get_timebase() work from my C# class

Forum for discussing PicoScope (version 5)

Can't make get_timebase() work from my C# class

Postby Guest » Wed Aug 01, 2007 11:18 am

Hello,

I am writing a program in c# that's supposed to activate the picoscope and start sampling it's data and save it in a class for analysis.

in the function get_time base I am not succeeding, also I would want to make my program managed as opposed to the unmanaged class I am currently writing because of the pointers the native C functions takes.

Here is my peace of code if you can guide threw what am I doing wrong that the function doesn't succeed in giving values to my variable


Code: Select all
private short handle;
private short timebase;
private int no_of_samples = 1000;
private int time_interval_ns;
private short time_unit;
private short oversample = 2;
private int max_smaples;

public short GET_TIMEBASE()
        {
            fixed(int* TimeInterval = &time_interval_ns , MaxSamples = &max_smaples)
            {
                fixed (short* TimeUnit = &time_unit)
                {
                    //short localTimeBase = timebase;
                    //int localNumSamples = Convert.ToInt32(no_of_samples);
                    //short localOversample = no_of_samples;


                    short finishStatus = ps3000_get_timebase(handle, timebase,no_of_samples, TimeInterval, TimeUnit, oversample, MaxSamples);
                    return finishStatus;
                }
            }
             
        }


P.S
If you have any better way to suggest for writing a c# program to work with the picoscope for the my purpose please expose me to it.
Looking for a way to create a managed code :)
Guest
 

Postby markB » Wed Aug 01, 2007 11:56 am

At first glance, I see no reason why you code should not succeed but I cannot see your definition of ps3000_get_timebase and there could be a problem here.

There should be no need to use fixed blocks in this instance. Use the following function definition.

Code: Select all
    [DllImport("ps3000.dll")]
    private static extern short ps3000_get_timebase(
      short handle,
      short timebase,
      int numSamples,
      out int nsInterval,
      out ReportedTimeUnits timeUnits,
      short oversample,
      out int maxSamples);


which means you should be able to:
Code: Select all
private short handle;
private short timebase;
private int no_of_samples = 1000;
private int time_interval_ns;
private short time_unit;
private short oversample = 2;
private int max_smaples;

public short GET_TIMEBASE()
      {

            short finishStatus = ps3000_get_timebase(
                  handle,
                  timebase,
                  no_of_samples,
                  out time_interval_ns,
                  out time_unit,
                  oversample,
                  out max_smaples);

            return finishStatus;

             
        }


In fact, there should be no reason for you to use any unsafe code at all. Beacuse the PS3000.dll uses trivial parameter types, the marshaller can do all of the fixing etc for you. (I think the only exception to this is a bool. You will have to pass as a short and manually convert to a bool).
Regards

Mark
markB
Site Admin
Site Admin
 
Posts: 83
Joined: Tue Mar 27, 2007 9:43 am
Location: Cambridgeshire,UK

Postby Guest » Wed Aug 01, 2007 12:44 pm

Thank you mark,

One problem is I am not familiar yet with the concept of marshalling,

but it sounds from you as if it's something that's supposed to happen automatically.

in my code I did exactly the same accept the out part you wrote in the definitions
out int nsInterval,
out ReportedTimeUnits timeUnits,


Code: Select all
[DllImport("c://Program Files//Pico Technology//Pico Full//Examples//PS3000//ps3000.dll")]
        private static extern short ps3000_get_timebase(short handle, short timebase, int no_of_samples, int* time_intervals_ns, short* time_units, short oversample, int* maxsamples);


public short GET_TIMEBASE()
        {
            fixed(int* TimeInterval = &time_interval_ns , MaxSamples = &max_smaples)
            {
                fixed (short* TimeUnit = &time_unit)
                {
                    //short localTimeBase = timebase;
                    //int localNumSamples = Convert.ToInt32(no_of_samples);
                    //short localOversample = no_of_samples;


                    short finishStatus = ps3000_get_timebase(handle, timebase,no_of_samples, TimeInterval, TimeUnit, oversample, MaxSamples);
                    return finishStatus;
                }
            }
             
        }


P.S

I had to use fixed because we pass pointers to the native function,
and it didn't compile otherwise, which is also the reason why I am using unsafe code.
How does marshalling go in here??

Thanks in advanced.
Guest
 

Postby markB » Wed Aug 01, 2007 1:59 pm

You get the marshalling for free beacuse of the 'out'. The marshaller will spot that its an out parameter and automatically pass it to the unmanaged code as a pointer. You dont have to worry about the pointers at all.
Regards

Mark
markB
Site Admin
Site Admin
 
Posts: 83
Joined: Tue Mar 27, 2007 9:43 am
Location: Cambridgeshire,UK

thanks

Postby Guest » Wed Aug 01, 2007 3:27 pm

thanks a lot man I will try that
Guest
 

working with safe code using out

Postby Guest » Wed Aug 01, 2007 8:56 pm

Hey Mark,

I tried what you suggested, and it does ilinimate the need for unsafe code,
thouge it didn't help me in the get_unit_info function, in which I got an exception trying to use out, the exception said
An unhandled exception of type 'System.ArgumentException' occurred in PICOSCOPE.exe

Additional information: Method's type signature is not Interop compatible.


the relevant code is:

Code: Select all
[DllImport("c://Program Files//Pico Technology//Pico Full//Examples//PS3000//ps3000.dll")]
        public static extern short ps3000_get_unit_info(short handle,  out byte[] String, short stringLen, short Info);

void get_info()
        {
            string[] description = new string[6]{"Driver Version","USB Version","Hardware Version","Variant Info","Serial", "Error Code" };
            byte[] line = new byte[20];
                short i;
                for (i = 0; i < 6; i++)
                {
       
                    short check = ps3000_get_unit_info(handle, out line, 50, i);
                    Console.Write(description[i] + " ");
                    Console.Write(System.Text.Encoding.ASCII.GetString(line));
                    Console.WriteLine();
                }
           
        }
Guest
 

Postby markB » Thu Aug 02, 2007 8:36 am

I've attached a class that wraps the dll for you. You now shouldnt need to worry about the marshalling.

The wrapper class should be pretty self explainitory to use. This will modify your get_timebase code snippet to


Code: Select all
            PS3000 p = new PS3000();

      try
      {
        short timebase = 0;
        int no_of_samples = 1000;
        int time_interval_ns;
        PS3000.TimeUnits time_unit;
        short oversample = 2;
        int max_smaples;

        p.Open();
        bool ok = p.GetTimebase(
              timebase,
              no_of_samples,
              out time_interval_ns,
              out time_unit,
              oversample,
              out max_smaples);

      }
      catch (PS3000.PicoException e)
      {
          Console.WriteLine(e.Message);
      }
      p.Close();



and your last code snippet to something like
Code: Select all
      PS3000 p = new PS3000();

      try
      {
        p.Open();
        Console.WriteLine("Driver Version {0}", p.DriverVersion);
        Console.WriteLine("USB Version {0}", p.UsbVersion);
        Console.WriteLine("Hardware Version {0}", p.HardwareVersion);
        Console.WriteLine("Variant Info {0}", p.VariantInfo);
        Console.WriteLine("Serial {0}", p.Serial);
        Console.WriteLine("Error Code {0}", p.Error);
      }
      catch(PS3000.PicoException e)
      {
        Console.WriteLine(e.Message);
      }
      p.Close();
    }
Attachments
PS3000.zip
c# class that wraps PS3000.dll
(2.35 KiB) Downloaded 275 times
Regards

Mark
markB
Site Admin
Site Admin
 
Posts: 83
Joined: Tue Mar 27, 2007 9:43 am
Location: Cambridgeshire,UK

using C# code with picoscope

Postby Guest » Thu Aug 02, 2007 10:28 am

Hello again Mark,

Thank you a lot for the very good and effective help.

That wrapper class you sent seems like is going to do the trick for me.

I am very happy with the service you provided.

hope I won't need your help again on that matter.

regards.
Guest
 

run get_timebase

Postby Guest » Fri Aug 03, 2007 10:01 am

Hi mark,

I am using your class and it's very useful for solving my unsafe code problem, never the less I can't seem to succeed in running the get_timebase function.
it compiles and runs well but returns with the value of 0, which is inadequate.
ret == 0
why is that? I can't seem to make it run and return success value.

sincerely,
Dan.
Guest
 

Postby markB » Fri Aug 03, 2007 10:53 am

GetTimebase would return zero if one of your paramters is out of range. Possible reasons for this could be the number of samples is out of range or the timebase is not valid for the number of channels that you have enabled.

Before calling GetTimebase, you should set up the channels using ps3000_set_channel() and, if required, ETS mode using ps3000_set_ets() first.
Regards

Mark
markB
Site Admin
Site Admin
 
Posts: 83
Joined: Tue Mar 27, 2007 9:43 am
Location: Cambridgeshire,UK

Postby Guest » Fri Aug 03, 2007 11:09 am

I don't know what makes value out of range.
here is my code:

Code: Select all
PS3000 PICO = new PS3000();
short timaBase = 2;
int NumOfSamples = 5000000;
int nsInterval;
short overSemple = 0;
PS3000.TimeUnits TimeUnit;
int MaxSamples;

PICO.GetTimebase(timaBase, NumOfSamples, out nsInterval, out TimeUnit, overSemple, out MaxSamples);

public bool GetTimebase(short timebase, int numSamples, out int nsInterval, out TimeUnits timeUnits, short oversample, out int maxSamples)
    {
      CheckOpened();
      short ret = ps3000_get_timebase(_handle, timebase, numSamples, out nsInterval, out timeUnits, oversample, out maxSamples);

      return ret > 0;
    }


what can I do to make it work, without that phase I can't proceed.

thank you.
Guest
 

Postby markB » Fri Aug 03, 2007 11:34 am

Which device do you have?

How many channels have you enabled?
Regards

Mark
markB
Site Admin
Site Admin
 
Posts: 83
Joined: Tue Mar 27, 2007 9:43 am
Location: Cambridgeshire,UK

Postby Guest » Fri Aug 03, 2007 11:38 am

I have picoscope 3224
I am using 1 channel
Guest
 

Postby markB » Fri Aug 03, 2007 12:01 pm

Firstly, you need to check that you have only one channel enabled:

Code: Select all
SetChannel(PS3000.Channel.ChannelA, true, PS3000.Coupling.AC, PS3000.Range.Range1V);
SetChannel(PS3000.Channel.ChannelB, false, PS3000.Coupling.AC, PS3000.Range.Range1V);


Secondly, you have one too many zeros in your NumOfSamples, the PS3224 only has a 512k Samples buffer.
Regards

Mark
markB
Site Admin
Site Admin
 
Posts: 83
Joined: Tue Mar 27, 2007 9:43 am
Location: Cambridgeshire,UK

Postby Guest » Fri Aug 03, 2007 12:07 pm

Now it's working,

I guess the problem was I didn't check that channel B is not enabled

Thank you.
Guest
 

Next

Return to PicoScope 5

Who is online

Users browsing this forum: No registered users and 0 guests