Using JNA to call PicoScope/PicoLog API Functions

Post your Java discussions here
Post Reply
Hitesh

Using JNA to call PicoScope/PicoLog API Functions

Post by Hitesh »

As an alternative to using Java Native Interface (JNI) to call PicoScope and PicoLog API functions, you can use Java Native Access (JNA) to do the same without having create an interim Dynamic Link Library (DLL).

This post uses the API functions for the PicoScope 3000 series devices provided by the ps3000a.dll driver to provide some example code.

Requirements:

From the Software Development Kit for your device:
  • Dynamic link library files for the device (e.g. ps3000a.dll and PicoIpp.dll)
  • Header file ((in this case, ps3000aApi.h, for reference)
  • Programmer’s Guide
  • This example also uses the PicoScope.jar file from the following thread http://www.picotech.com/support/topic12887.html
From the Oracle Java SE Download section:
From the Java Native Access repository:
Interface Definition

The first step is to define an interface which maps methods to the functions defined in the header file. Note the mapping of the data types.

Don’t forget the relevant import statements.

Code: Select all

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.ShortByReference;

public interface PS3000aCLibrary extends Library
{
	
	PS3000aCLibrary INSTANCE = (PS3000aCLibrary) Native.loadLibrary
                                    ("ps3000a", PS3000aCLibrary.class);
	
        // API function definition : 
	//  PICO_STATUS ps3000aEnumerateUnits(int16_t * count, int8_t * serials, int16_t serialLth)
        int ps3000aEnumerateUnits(ShortByReference count, byte[] serials, ShortByReference serialLth);
        
	// API function definition :	
        // PICO_STATUS ps3000aOpenUnit (int16_t * handle, int8_t * serial)
        int ps3000aOpenUnit(ShortByReference handle, String serial);
	
	// API function definition:
	// PICO_STATUS ps3000aCloseUnit(int16_t handle);
	int ps3000aCloseUnit(short handle);
	
        // API function definition:
        // PICO_STATUS ps3000aGetUnitInfo(int16_t handle, int8_t *string, int16_t stringLength,       
        // int16_t *requiredSize, PICO_INFO info)
        int ps3000aGetUnitInfo(short handle, byte[] string, short stringLength, ShortByReference requiredSize, int info);
        
        // API function definition:
        //unit32_t ps3000aChangePowerSource(int16_t      handle, PICO_STATUS powerstate)
        int ps3000aChangePowerSource(short handle, int powerstate);
        
}
Calling the Methods

Below are some examples of calling code from within the main method of a class. The import statements are given below:

Import statements:

Code: Select all

import com.sun.jna.ptr.ShortByReference;
import com.picotech.picoscope.*;
import com.sun.jna.Native;
import java.io.UnsupportedEncodingException;
Finding which devices are present:

Code: Select all

System.out.println("Searching for PicoScope 3000 Series devices...");
        
        ShortByReference countRef = new ShortByReference();
        byte[] serials = new byte[100];
        ShortByReference serialsLthRef = new ShortByReference();
        serialsLthRef.setValue((short) 0);
        
        int enumerateStatus = PS3000aCLibrary.INSTANCE.ps3000aEnumerateUnits(countRef, serials, serialsLthRef);
        
        System.out.println("Enumerate status: " + enumerateStatus);
        System.out.println("Count: " + countRef.getValue());
        
        String deviceSerials = "";
        
        try
        {
            deviceSerials = new String(serials, "UTF-8");
        }
        catch(UnsupportedEncodingException uee)
        {
            deviceSerials = "";
            
        }
        
        System.out.println("Serial number(s): " + deviceSerials);
        System.out.println("Serials Lth: " + serialsLthRef.getValue());
Opening a connection to a device:

Code: Select all

       System.out.println("Opening PicoScope 3000 Series device ...");
        
        ShortByReference handleRef = new ShortByReference();
        handleRef.setValue((short) 0);
        
                
        //String deviceSerial = "TEST/007"; // Serial number can be specified
        String deviceSerial = null;

        int openStatus = PicoStatus.PICO_OK;
        
        try
        {
            openStatus = PS3000aCLibrary.INSTANCE.ps3000aOpenUnit(handleRef, deviceSerial);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        
        short handle = handleRef.getValue();
       
        // Handle the power change for PicoScope 340XA/B, 340XDMSO and 3207A/B devices
        if(openStatus == PicoStatus.PICO_POWER_SUPPLY_NOT_CONNECTED || 
                openStatus == PicoStatus.PICO_USB3_0_DEVICE_NON_USB3_0_PORT)
        {
            int powerChangeStatus = PS3000aCLibrary.INSTANCE.ps3000aChangePowerSource(handle, openStatus);
        }
        
        System.out.println("Handle: " + handle);
Retrieve device information:

Code: Select all

        byte[] infoBytes = new byte[40];
        ShortByReference reqSizeRef = new ShortByReference();
        
        int driverInfoStatus = PS3000aCLibrary.INSTANCE.ps3000aGetUnitInfo(handle, infoBytes, (short) infoBytes.length, reqSizeRef, PicoInfo.PICO_DRIVER_VERSION);
		
        String driverInfo = new String();
        
        try
        {
            driverInfo = new String(infoBytes, "UTF-8");
        }
        catch(UnsupportedEncodingException uee)
        {
            driverInfo = "";
            
        }
        
        System.out.println("Driver: " + driverInfo);
        
        reqSizeRef.setValue((short) infoBytes.length);
        int variantInfoStatus = PS3000aCLibrary.INSTANCE.ps3000aGetUnitInfo(handle, infoBytes, (short) infoBytes.length, reqSizeRef, PicoInfo.PICO_VARIANT_INFO);
        
        System.out.println("Variant: " + Native.toString(infoBytes));
Note that the above example shows two ways of retrieving modified strings from the method call.

Close the connection to the device:

Code: Select all

PS3000aCLibrary.INSTANCE.ps3000aCloseUnit(handle);
Run time JVM arguments

You may need to set the following JVM command at runtime:

Code: Select all

-Djna.nosys=true
Please note that Pico Technology is not responsible for the content of third party sites.

Feel free to try this code and post code snippets in this forum area :)

Regards,

KimTaeGyeong
Newbie
Posts: 0
Joined: Wed Feb 04, 2015 5:36 am

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by KimTaeGyeong »

I'm wanted to ask many. But I can't speak English very well. sorry...
1. How to use ps3000aBlockReady
2. How to use ps3000aSetChannel

please answer me

Hitesh

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by Hitesh »

Hi,

Below is some code on how to define ps3000aSetChannel:

Code: Select all

// uint32_t ps3000aSetChannel(int16_t handle, PS3000A_CHANNEL channel, short enabled, PS3000A_COUPLING type, PS3000A_RANGE range, float analogueOffset)
    int ps3000aSetChannel(short handle, int channel, short enabled, int type, int range, float analogueOffset);
I also define enumerations for the channel, coupling and range:

Code: Select all

    public enum PS3000AChannel
    {
        PS3000A_CHANNEL_A,
        PS3000A_CHANNEL_B,
        PS3000A_CHANNEL_C,
        PS3000A_CHANNEL_D,
        PS3000A_EXTERNAL
    }
    
    public enum PS3000ACoupling
    {
        PS3000A_AC,
        PS3000A_DC
    }
    
    public enum PS3000ARange
    {
        PS3000A_10MV,
        PS3000A_20MV,
        PS3000A_50MV,
        PS3000A_100MV,
        PS3000A_200MV,
        PS3000A_500MV,
        PS3000A_1V,
        PS3000A_2V,
        PS3000A_5V,
        PS3000A_10V,
        PS3000A_20V,
        PS3000A_50V,
        PS3000A_MAX_RANGES
    }
Here is an example of how to call the method:

Code: Select all

int channel = PS3000aCLibrary.PS3000AChannel.PS3000A_CHANNEL_A.ordinal();
        short enabled = 1;
        int coupling = PS3000aCLibrary.PS3000ACoupling.PS3000A_DC.ordinal();
        int range = PS3000aCLibrary.PS3000ARange.PS3000A_5V.ordinal();
        float offset = 0.0f;
        
        // Set a channel 
        int setChannelStatus = PS3000aCLibrary.INSTANCE.ps3000aSetChannel(handle, channel, enabled, coupling, range, offset);
I will get back to you regarding ps3000aBlockReady or you could call ps3000aRunBlock and call ps3000aIsReady instead.

Regards,

KimTaeGyeong
Newbie
Posts: 0
Joined: Wed Feb 04, 2015 5:36 am

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by KimTaeGyeong »

Hi

Thanks for the answer.

KimTaeGyeong
Newbie
Posts: 0
Joined: Wed Feb 04, 2015 5:36 am

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by KimTaeGyeong »

I forgot. That there is a other question.

How to use ps3000aGetTimebase2

Hitesh

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by Hitesh »

Hi,

The ps3000aGetTimebase2 function is used to query the driver as to whether the timebase selected is valid for the number of samples to be collected in a segment and with the current channel configuration.

To define the function:

Code: Select all

// uint32_t ps3000aGetTimebase2(int16_t handle, uint32_t timebase, int32_t noSamples, float //*timeIntervalNanoseconds, int16_t oversample, int32_t *maxSamples, uint32_t segmentIndex)

    int ps3000aGetTimebase2(short handle, int timebase, int noSamples, FloatByReference timeIntervalNanoseconds, short oversample, IntByReference maxSamples, int segmentIndex);
To use the method:

Code: Select all

        int timebase = 0;
        int numSamples = 1024; // Set to total number of samples required
        
        FloatByReference timeIntervalNsRef = new FloatByReference();
        timeIntervalNsRef.setValue((float) 0.0);
        
        short oversample = 1; // Do not change this value
        
        IntByReference maxSamplesRef = new IntByReference();
        maxSamplesRef.setValue(0);
        
        int segmentIndex = 0;
        
        int getTimebase2Status = 14; // Initialise to PICO_INVALID_TIMEBASE
        
        // Loop until a valid timebase has been found
        
        while(getTimebase2Status != 0)
        {
            getTimebase2Status = PS3000aCLibrary.INSTANCE.ps3000aGetTimebase2(handle, timebase, numSamples, timeIntervalNsRef, oversample, maxSamplesRef, segmentIndex);
            
            if(getTimebase2Status == 0)
            {
                break;
            }
            else
            {
                timebase = timebase + 1;
            }
        }
        
        System.out.println("Timebase: " + timebase);
        System.out.println("Time interval: " + timeIntervalNsRef.getValue());
        System.out.println("Max Samples: " + maxSamplesRef.getValue());

KimTaeGyeong
Newbie
Posts: 0
Joined: Wed Feb 04, 2015 5:36 am

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by KimTaeGyeong »

Thanks answers.

I have been a lot of progress Because of you.

However, there is a difficult problem to solve alone.

1MS when more than data display Data processing is very slow.

I want to know. 'PicoScope 6' is how the data processing

Hitesh

Re: Using JNA to call PicoScope/PicoLog API Functions

Post by Hitesh »

Hi,

PicoScope 6 requests aggregated data (min / max values) from the driver in order to display the data as you would not have millions of pixels across the screen (unless you have a very large screen! :lol: ).

You can call the ps3000aSetDataBuffer function and set the ratioMode parameter to PS3000A_RATIO_MODE_AGGREGATE. When you then call ps3000aGetValues, it should be possible to request aggregate and raw data values (by passing the OR of the AGGREGATE and NONE ratios for the ratioMode parameter) as long as you have set up data buffers for both types of ratio mode.

Regards,

Post Reply