Digital Triggering

Post general discussions on using our drivers to write your own software here
Post Reply
Will252
Newbie
Posts: 0
Joined: Wed Aug 05, 2015 1:39 pm

Digital Triggering

Post by Will252 »

Hi, I am writing a python program to interface with a PicoScope 2205MSO. I can set the timebase and voltage range, run in block, rapid block and streaming modes, set a data buffer and read back the data. But I am having trouble setting a digital trigger.

My script calls ps2000aSetTriggerDigitalPortProperties without any errors but the data returned doesn't seem to have been triggered, it appears to have just starts recording immediately. Do I need to call any other functions to set a digital trigger?

Hitesh

Re: Digital Triggering

Post by Hitesh »

Hi Will252,

Try calling the ps2000aSetTriggerChannelConditions() function to indicate that a digital trigger will be used.

Regards,

Will252
Newbie
Posts: 0
Joined: Wed Aug 05, 2015 1:39 pm

Re: Digital Triggering

Post by Will252 »

So I've tried calling ps2000aSetTrggerChannelConditions. When I set channel A as the trigger channel it runs without errors but if I try to use digital I get the error: PICO_CONDITIONS (One or more of the conditions are incorrect.).

The reason I didn't try it before is the manual says
channelC, channelD, aux, digita: not used.
. I assume that is why it is ok with channel A but not digital.

Hitesh

Re: Digital Triggering

Post by Hitesh »

Hi Will252,

Which version of the ps2000a.dll are you using?

A new function (ps2000aSetDigitalAnalogTriggerOperand()) has been introduced - please refer to section 3.41 of the Programmer's Guide.

If you are using the dll provided as part of the PicoScope 6.11 installation, try calling this function with operand set to PS2000A_OPERAND_OR.

If this does not work, please post your code showing how the trigger is being set up.

I will check here in case there is an error in the Programmer's Guide with respect to the ps2000aSetTriggerChannelConditions() function.

Regards,

mrrg
Newbie
Posts: 0
Joined: Mon Nov 14, 2016 4:44 pm

Re: Digital Triggering

Post by mrrg »

Hello

I am having similar problems in Linux.

What is the status of ps2000aSetTriggerChannelConditions() ?

Should I call this to set the digital triggering?

Hitesh

Re: Digital Triggering

Post by Hitesh »

Hi mmrg,

You will need to call ps2000aSetTriggerChannelConditions() and set the trigger state for the digital ports to PS2000A_CONDITION_TRUE. Next, you will need to call ps2000aSetTriggerDigitalPortProperties() to set the actual digital trigger properties.

Regards,

mrrg
Newbie
Posts: 0
Joined: Mon Nov 14, 2016 4:44 pm

Re: Digital Triggering

Post by mrrg »

Ok, now I am setting one condition with

Code: Select all

cond[0].digital=PS2000A_CONDITION_TRUE;


all others are set to

Code: Select all

PS2000A_CONDITION_FALSE
This returns

Code: Select all

 PICO_OK
I also made sure that ps2000aSetTriggerChannelConditions() receives the correct pointer and number of conditions, (made an array of conditions but use only the first).

Now the program started to crash on ps2000aRunStreaming () this worked before adding the condition.

bt
#0 0x00007ffff6249fe6 in ?? () from /opt/picoscope/lib/libps2000a.so.2
#1 0x00007ffff62441b6 in ?? () from /opt/picoscope/lib/libps2000a.so.2
#2 0x00007ffff6238a07 in ?? () from /opt/picoscope/lib/libps2000a.so.2
#3 0x00007ffff61cfeca in ps2000aRunStreaming () from /opt/picoscope/lib/libps2000a.so.2

Do the order of the calls matter?
I am calling in this order:

ps2000aOpenUnit()
ps2000aSetChannel()
ps2000aSetDigitalPort()
ps2000aSetTriggerDigitalPortProperties()
ps2000aSetTriggerChannelConditions()
ps2000aSetDataBuffer()
ps2000aRunStreaming()

Best regards
Reine

Hitesh

Re: Digital Triggering

Post by Hitesh »

Hi Reine,

I would suggest calling ps2000aSetTriggerChannelConditions() BEFORE ps2000aSetTriggerDigitalPortProperties().

Which version of the ps2000a driver are you using?

Is it possible to post your source code here or e-mail it to support@picotech.com?

Regards,

mrrg
Newbie
Posts: 0
Joined: Mon Nov 14, 2016 4:44 pm

Re: Digital Triggering

Post by mrrg »

Hello

I moved the ps2000aSetTriggerChannelConditions() but it still do not trigger.
Also I have very big problems to make the picoscope application to trigger.

I can not post all of the code since it is a lot of unrelated software GUI stuff etc... but I can post the interface code to your device. The following function calls are done on the device class from the GUI and they in turn call your functions, the toplevel functions are at the left column..lower levels to the right.

Code: Select all

// dev->openDevice()         calls ps2000aOpenUnit()
// dev->maplist2Channel()    calls setChannel() 
//                           calls ps2000aSetChannel() and ps2000aSetTriggerChannelConditions()
//
// dev->setDigitalPort()     calls ps2000aSetDigitalPort()
// dev->maplist2Directions() calls setDirections() calls ps2000aSetTriggerDigitalPortProperties()
// dev->setDataDevBuffer()   calls ps2000aSetDataBuffer()
// dev->startStreaming()     calls ps2000aRunStreaming() 
// dev->getStream()          calls ps2000aGetStreamingLatestValues() with callback void lpPs2000AReady()
Here is the header file

Code: Select all

//
// $HeadURL: svn://squid.irfu.se/swada/libGUI/Device.H $
// $Revision: 333 $
// $Date: 2013-09-27 18:44:22 +0200 (fre, 27 sep 2013) $
// $Author: rg $
//
// Copyright: (C) Reine Gill 2010-2016
//
#ifndef _DEVICE_H_
#define _DEVICE_H_
#include 
//#include 
#include 
#include 
#include 

#include "Map.H"
#include "SDLThreads.H"

// Device we have is PicoScope 2208B MSO, DX123/0056
//
// According to user manual we shall use the API:
//
///opt/picoscope/include/libps2000a-1.1/
// PicoStatus.h  ps2000aApi.h
// libps2000a
//
//
using namespace std;

// global function not part of the device object
void lpPs2000AReady(
		    int16_t handle,
		    int32_t noOfSamples,
		    uint32_t startIndex,
		    int16_t overflow,
		    uint32_t triggerAt,
		    int16_t triggered,
		    int16_t autoStop,void *nParameter
		    );

typedef struct channel_type_def
{
  int16_t enabled;
  PS2000A_COUPLING type;
  PS2000A_RANGE range;
  float analogOffset;

} channel_type;

typedef struct port_type_def
{
  int16_t enabled;
  int16_t logiclevel;
} port_type;

class Device
{
public:
  Device();
  ~Device();
  
  bool openDevice();
  bool closeDevice();

  // Set device functions
  bool setChannel(PS2000A_CHANNEL ch);
  bool setDigitalPort(PS2000A_DIGITAL_PORT port);

  bool setDirections();
  bool setDataDevBuffer(int32_t ch);
  bool startStreaming();
  bool stopStreaming();

  // Get device functions
  bool getMaxDownsampling();
  bool getStream();
  unsigned int getNoSamples();
  string getSamplingRateStr();
  void getDataPointer(int16_t **ap,uint32_t *len);

  void ValueHz(double val,char *str);

  // Convert lists of GUI parameters to update device data and also call device set functions
  void maplist2Channel(PS2000A_CHANNEL ch,const char *key,Value *v);
  void maplist2Directions(const char *key,Value *v,int offset);


  void func_lpPs2000AReady(int16_t handle,int32_t noOfSamples,uint32_t startIndex, 
			   int16_t overflow,uint32_t triggerAt,int16_t triggered,
			   int16_t autoStop,void *nParameter);

  // Public Device parameters
  uint32_t requsted_sample_interval;                  // Requested sample interval
  uint32_t used_sample_interval;                      // Actual sample interval

  PS2000A_TIME_UNITS sample_interval_time_unit;        // Units
  uint32_t maxPreTriggerSamples;                       // Maximum pre trigger samples
  uint32_t maxPostTriggerSamples;                      // Maximum post trigger samples
  int16_t autoStop;                                    // Stop then max samples reached

  uint16_t segments;                                   // Number of memory segments

  uint32_t downSampleRatio;                            // Down sample ratio
  uint32_t maxDownSampleRatio;                         // Maximum downsample ratio
  PS2000A_RATIO_MODE downSampleRatioMode;              // Down sample ratio mode

  PS2000A_DIGITAL_CHANNEL_DIRECTIONS directions[32];  // Port directions
  int16_t ndirections;                                // Number of directions

  int present_port_ind;                               // Present port index 0 or 1

  int16_t nconditions; 
  PS2000A_TRIGGER_CONDITIONS cond[8];                



  std::map channel;
  std::map    port;

  std::map range2str;
  std::map str2range;

  std::map str2direction;

  std::map unit2str;

  std::map unit2factor;


private:   
  // Private device parameters
  int16_t handle;
  int16_t *devBuff[2];       // Data devBuffer
  int32_t  dev_buff_len[2];  // Data devBuffer length
  int16_t *appBuff[2];       // Application buffers

  bool devbuffer_set;
};
#endif

Here is the source:

Code: Select all

//
// $HeadURL: svn://squid.irfu.se/swada/libGUI/Base.cpp $
// $Revision: 323 $
// $Date: 2013-09-23 16:44:37 +0200 (mån, 23 sep 2013) $
// $Author: rg $
//
// Copyright: (C) Reine Gill 2010-2016
//
#include 
#include 
#include "Device.H"

extern Device     *dev; // Pointer to the picoscope device class, only one
extern Signal scopeProcess0_sig;


// dev->openDevice()         calls ps2000aOpenUnit()
// dev->maplist2Channel()    calls setChannel() 
//                           calls ps2000aSetChannel() and ps2000aSetTriggerChannelConditions()
//
// dev->setDigitalPort()     calls ps2000aSetDigitalPort()
// dev->maplist2Directions() calls setDirections() calls ps2000aSetTriggerDigitalPortProperties()
// dev->setDataDevBuffer()   calls ps2000aSetDataBuffer()
// dev->startStreaming()     calls ps2000aRunStreaming() 
// dev->getStream()          calls ps2000aGetStreamingLatestValues() with callback void lpPs2000AReady()
Device::Device()
{
  int i;

  requsted_sample_interval  = 20;
  used_sample_interval      = 20;
  sample_interval_time_unit = PS2000A_US;

  // Setup a map to convert time units to strings
  unit2str[PS2000A_FS]="fs";
  unit2str[PS2000A_PS]="ps";
  unit2str[PS2000A_NS]="ns";
  unit2str[PS2000A_US]="us";
  unit2str[PS2000A_MS]="ms";
  unit2str[PS2000A_S]="s";

  // Setup a map to convert time units to factors
  unit2factor[PS2000A_FS]=1e-15;
  unit2factor[PS2000A_PS]=1e-12;
  unit2factor[PS2000A_NS]=1e-9;
  unit2factor[PS2000A_US]=1e-6;
  unit2factor[PS2000A_MS]=1e-3;
  unit2factor[PS2000A_S] =1.0;

  // Default no Autostop
  autoStop=0;

  // Set default number of samples 
  dev_buff_len[0]=200000;
  dev_buff_len[1]=200000;

  present_port_ind=0; // Set the present digital port to 0

  // Half before trigg half after
  //maxPreTriggerSamples=(dev_buff_len[0]>>1);
  //maxPostTriggerSamples=(dev_buff_len[0]>>1);

  // No samples before trigg
  maxPreTriggerSamples=0;
  maxPostTriggerSamples=dev_buff_len[0];
    
  // Allocate buffers for ports and application
  devBuff[0]=new int16_t[dev_buff_len[0]];
  devBuff[1]=new int16_t[dev_buff_len[1]];

  appBuff[0]=new int16_t[dev_buff_len[0]];
  appBuff[1]=new int16_t[dev_buff_len[1]];

  // To begin with use only one memory segment
  segments=1;

  // Set the default downsampling ratio
  downSampleRatio=1;

  // Do not do any downsampling
  downSampleRatioMode=PS2000A_RATIO_MODE_NONE;

  // Setup channels, stored in a map not array
  channel[PS2000A_CHANNEL_A].enabled=0;
  channel[PS2000A_CHANNEL_B].enabled=0;
  channel[PS2000A_CHANNEL_C].enabled=0;
  channel[PS2000A_CHANNEL_D].enabled=0;

  channel[PS2000A_CHANNEL_A].type=PS2000A_AC;
  channel[PS2000A_CHANNEL_B].type=PS2000A_AC;
  channel[PS2000A_CHANNEL_C].type=PS2000A_AC;
  channel[PS2000A_CHANNEL_D].type=PS2000A_AC;

  channel[PS2000A_CHANNEL_A].range=PS2000A_5V;
  channel[PS2000A_CHANNEL_B].range=PS2000A_5V;
  channel[PS2000A_CHANNEL_C].range=PS2000A_5V;
  channel[PS2000A_CHANNEL_D].range=PS2000A_5V;

  channel[PS2000A_CHANNEL_A].analogOffset=0.0f;
  channel[PS2000A_CHANNEL_B].analogOffset=0.0f;
  channel[PS2000A_CHANNEL_C].analogOffset=0.0f;
  channel[PS2000A_CHANNEL_D].analogOffset=0.0f;


  // Setup digital port stored in a map not an array
  port[PS2000A_DIGITAL_PORT0].enabled=0;
  port[PS2000A_DIGITAL_PORT0].logiclevel=0;
  
  port[PS2000A_DIGITAL_PORT1].enabled=0;
  port[PS2000A_DIGITAL_PORT1].logiclevel=0;
 
  ndirections=16; // PS2000A_MAX_DIGITAL_CHANNELS is 32 this is wrong for our device

  // Setup default directions
  for(i=0;ifunc_lpPs2000AReady(
			   handle,
			   noOfSamples,
			   startIndex,
			   overflow,
			   triggerAt,
			   triggered,
			   autoStop,
			   nParameter
			   ); // Call our own device class function
}

bool Device::getStream()
{
  PICO_STATUS stat;

    stat=ps2000aGetStreamingLatestValues
    (
     handle,
     lpPs2000AReady,
     NULL
     );

  if(stat==PICO_OK)
    { 
      return true;
    }

  return false;
}

void Device::func_lpPs2000AReady(  
				 int16_t handle,
				 int32_t noOfSamples,
				 uint32_t startIndex,
				 int16_t overflow,
				 uint32_t triggerAt,
				 int16_t triggered,
				 int16_t autoStop,
				 void *nParameter
				   )
{

  memcpy(&appBuff[present_port_ind][startIndex],&devBuff[present_port_ind][startIndex],noOfSamples*sizeof(int16_t));
 
  /*
  printf("nandle %d\n",handle);
  printf("noOfSamples %d\n",noOfSamples);
  printf("startIndex  %d\n",startIndex);
  printf("overflow    %d\n",overflow);
  */

  if(triggered>0)
    printf("trigger!\n");

}

unsigned int Device::getNoSamples()
{
 PICO_STATUS stat;
 uint32_t noOfValues;

 stat=ps2000aNoOfStreamingValues
      (
       handle,
       &noOfValues
       );

  if(stat==PICO_OK)
    { 
      LogMessage("Number of samples available %d\n",noOfValues);
    }
  else
     LogMessage("Failed to get number of samples\n");

  return noOfValues;

}

void Device::getDataPointer(int16_t **ap,uint32_t *len)
{
  *ap = appBuff[present_port_ind];
  *len = dev_buff_len[present_port_ind];
}

void Device::maplist2Channel(PS2000A_CHANNEL ch,const char *key,Value *v)
{

  if(!strcmp(key,"enabled"))
    {
      if(v->value=="Enabled")
	channel[ch].enabled=1;
      else
	channel[ch].enabled=0;
    }

  if(!strcmp(key,"type"))
    {
      if(v->value=="AC")
	channel[ch].type=PS2000A_AC;
      else
	channel[ch].type=PS2000A_DC;
    }
  
  if(!strcmp(key,"range"))
    {
      channel[ch].range=(PS2000A_RANGE)str2range[v->value];
    }

  if(!strcmp(key,"offset"))
    channel[ch].analogOffset=0.0f;


  setChannel(ch); // Apply to device
}

void Device::maplist2Directions(const char *key,Value *v,int offset)
{
  // Modify direction array
  directions[v->position+offset].direction=(PS2000A_DIGITAL_DIRECTION)str2direction[v->value];

  LogMessage("Digital channel %d\n",v->position+offset);
  LogMessage("Direction str   %s\n",v->value.c_str());
  LogMessage("Direction enum  %d\n",(PS2000A_DIGITAL_DIRECTION)str2direction[v->value]);
  
  setDirections(); // Update directions
}

// Return the used sampling rate as a string
string Device::getSamplingRateStr()
{
  double freq;
  string rate;
  char tmp[20];

  freq=1.0/(unit2factor[sample_interval_time_unit]*((double)dev->used_sample_interval));

  ValueHz(freq,tmp);

  rate=tmp;

  return rate;
}

void Device::ValueHz(double val,char *str)
{
  if(fabs(val)<999e3) 
    {
      sprintf(str,"%09.3f/[KHz]",val*1.0e-3);
      return;
    }

  if(fabs(val)<999e6) 
    {
      sprintf(str,"%09.3f/[MHz]",val*1.0e-6);
      return;
    }

  if(fabs(val)<999e9) 
    {
      sprintf(str,"%09.3f/[GHz]",val*1.0e-9);
      return;
    }


  sprintf(str,"%09.3f/[THz]",val*1.0e-9);

  return;
}

bool Device::getMaxDownsampling()
{
  PICO_STATUS stat;
  
  stat=ps2000aGetMaxDownSampleRatio
	(
	 handle,
	 dev_buff_len[present_port_ind]*downSampleRatio,
	 &maxDownSampleRatio,
	 downSampleRatioMode,
	 0
	 );

  if(stat==PICO_OK)
    {
      LogMessage("Maximum downsampling ratio: %d, ps2000aGetMaxDownSampleRatio()\n",maxDownSampleRatio);
      return true;
    }

  LogMessage("PICO Status %d\n",stat);

  return false;
}

Hitesh

Re: Digital Triggering

Post by Hitesh »

Hi mrrg,

Apologies for the delay in getting back to you.

Just to confirm, are you using a PicoScope 2205 MSO (light blue case) or a PicoScope 2205A MSO (small form factor with dark blue case)?

Which version of the PS2000A Linux Driver are you using? Have you updated to using the latest available libps2000a package?

If you are able to provide information on the actual parameter values passed to the following function calls (including structure fields), I can try to reproduce the problem here:
  • ps2000aSetChannel()
  • ps2000aSetDigitalPort()
  • ps2000aSetTriggerChannelConditions()
  • ps2000aSetTriggerDigitalPortProperties()
  • ps2000aSetDataBuffer()
  • ps2000aRunStreaming()
Many thanks,

Post Reply