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

Forum for discussing PicoScope (version 5)
Guest

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

Post by 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 :)

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

Post by 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

Guest

Post by 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.[/u]

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

Post by 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

Guest

thanks

Post by Guest » Wed Aug 01, 2007 3:27 pm

thanks a lot man I will try that

Guest

working with safe code using out

Post by 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();
                }
            
        } 

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

Post by 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 329 times
Regards

Mark

Guest

using C# code with picoscope

Post by 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

Post by 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.

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

Post by 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

Guest

Post by 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.

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

Post by markB » Fri Aug 03, 2007 11:34 am

Which device do you have?

How many channels have you enabled?
Regards

Mark

Guest

Post by Guest » Fri Aug 03, 2007 11:38 am

I have picoscope 3224
I am using 1 channel

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

Post by 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

Guest

Post by 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.

Post Reply