PicoScope SDK


Radek

Recommended Posts

Hello,

I woudl appreciate if someone would be able to help me :).

Im trying to read Picoscope 4224 IEPE  (4000 Series). Im using the ps4000.dll from the Pico SDK. Following their programmer's Guide Im able to connect the unit, also it looks all the functions for the "Block" read mode are returning no errorr messages. However Im not able to get any data into the PSBufferCHA_raw or  V.PICO_CH_A, there are only -1 values I set as a baseline. Please see bellow the code for the Block acquisistion. Also attachig the programmer's guide.

Thanks,

Radek

Code>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

/////PICO SCOPE Measurment Block read
global PSBufferCHA_raw[8192] = 0

global PSsampleInterval = 20  //Sample time in us / mikrosekund cas pro samplovani  - NENI POUZITO, je to jen pro stream, ktery nefunguje
global PSTimebase = 500  ///500 is cca 40kHz  20e6/(500-1)
global PSsampleInterval_ns = 20  //real sample time ins ns / skutecny samplovaci cas v ns, je pak aktualizovano funkci ..GetTimebase  
global PStimeIndisposedMs = 0  //real time to take one block / skutecny cas na sebrani jednoho bloku v Ms
global PSmaxSamples = 8192  //max no of samples / skutecne mnozstvi samplu ktere umoznuje pamet zarizeni, je pak aktualizovano funkci ..GetTimebase
global PSnoOfSamples = 8192 //on entry: the number of samples requested; on exit,the number of samples actually returned, aktualizovano funkci ..GetValues
global PSnoOfSamplesExit = 8192   //samples in buffer after data acquisistion  /pocet dat buferu po mereni
global PSoverflow = 0  //indicate whether an overvoltage has occurred on any of the channels. It is a bit pattern with bit 0 denoting Channel A and bit 1 Channel B.
global PSReady = 1  //on exit, indicates the state of the collection. If zero, the device is still collecting. If non-zero, the device has finished collecting and ps4000GetValues can be used to retrieve the data.

global PICOStatusRunBlock = -1
global PICOStatusIsReady = -1
global PICOStatusSetDataBuffer = -1
global PICOStatusGetValues = -1

private i = 0

extern("ps4000.dll","long ps4000SetChannel(word, byte, word, word, byte)","ps4000SetChannel","stdcall") //CH A setting / nastaveni kanalu A 
extern("ps4000.dll","long ps4000GetTimebase(word, ulong, long, long[1], word, long[1], uword)","ps4000GetTimebase","stdcall") ///Time base check / zjisteni Time Base
extern("ps4000.dll","long ps4000RunBlock(word, long, long, ulong, word, long[1], uword, long, long[1])","ps4000RunBlock","stdcall")  ///spusteni mereni Bloku
extern("ps4000.dll","long ps4000GetValues(word, ulong, ulong[1], ulong, word, uword, word[1])","ps4000GetValues","stdcall") ////stazeni hodnot z buferu driveru pro Blok mod
extern("ps4000.dll","long ps4000IsReady(word, word[1])","ps4000IsReady","stdcall")
extern("ps4000.dll","long ps4000SetDataBuffer(word, word, word[8192], long)","ps4000SetDataBuffer","stdcall") ///registrace data Bufferu A

i=0
while (i <= PSnoOfSamples)                         ///baseline buffer setting -1 set to confirm it is reading something/ vycteni hodnot z bufferu do virtualniho kanalu
   PSBufferCHA_raw = -1
      i=i+1
endwhile
  
///SET CHANNELS
while (PICOStatus != 0)
   PICOStatus = ps4000SetChannel(PSHandle,0,1,1,8) ///handle, channel, enabled, AC /DC (0/1), range
   PICOStatus = ps4000SetChannel(PSHandle,1,0,1,8)
endwhile

///GET TIME BASE
PICOStatus = ps4000GetTimebase(PSHandle,PSTimebase,8192,@PSsampleInterval_ns,1,@PSmaxSamples,0) ///handle, timebase (500 odpovida cca 40kHz  20e6/(500-1)), noSamples, *timeIntervalNanoseconds, oversample, *maxsample, segmentIndex

PSnoOfSamples = 8192  ///sresetovani nastaveni bufferu aby se stale nezmensoval

if (PSnoOfSamples > PSmaxSamples )   ///check if buffer demand is not higher then capability of the device / kontrola zda neni pozadovan vetsi bufer nez zarizeni zvladne
   PSnoOfSamples = PSmaxSamples
endif


////MEASUREMENT
while (1)   ///opakovani mereni

   PSReady = 0
///RUN BLOCK / spusteni mereni Bloku
     PICOStatusRunBlock = ps4000RunBlock(PSHandle,0,PSnoOfSamples,PSTimebase,1,@PStimeIndisposedMs,0,NULL,NULL) ///handle, noOfPreTriggerSamples, noOfPostTriggerSamples, timebase, oversample, * timeIndisposedMs, segmentIndex, lpReady, * pParameter 

   PSnoOfSamplesExit= PSnoOfSamples  //srovnani velikosti buferu aby se nezmensoval    
    
   ///IS READY
   PICOStatusIsReady = ps4000IsReady(PSHandle,@PSReady)   ///handle, *PSReady 
     
   while (PSReady == 0)                                  ////procedura ceka na ukonceni mereni
     PICOStatusIsReady = ps4000IsReady(PSHandle,@PSReady)
   delay(0.05)
   endwhile   

   ///SET DATA BUFFER
   PICOStatusSetDataBuffer = ps4000SetDataBuffer(PSHandle,0,@PSBufferCHA_raw,PSnoOfSamples)   ///handle, channel, buffer, buffer length
   
   ///GET VALUES  / stazeni hodnot z buferu driveru pro Blok mod
   PICOStatusGetValues = ps4000GetValues(PSHandle,0,@PSnoOfSamplesExit,1,0,0,@PSoverflow)   ///handle, startIndex, * noOfSamples, downSampleRatio, downSampleRatioMode, segmentIndex, * overflow 


   V.PICO_CH_A.AddValue = PSBufferCHA_raw
  
endwhile

Code>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  

picoscope-4000-series-programmers-guide.pdf

Link to comment
Share on other sites

  • 2 weeks later...

I'm surprised you didn't crash DAQFactory truthfully.  The issue is that pointers passed to external functions only exist as long as the function is running.  So, the SetDataBuffer call that passes a pointer isn't valid once the function returns.  That's because internally DAQFactory doesn't actually store data in the way that DLL's want it.  If you need to pass a buffer, you have to utilize an internal object called "DMemory".   It has the following member functions:

alloc(size)
free()
getPointer()
noAutoDelete()
getAsByte()
getAsUByte()
getAsWord()
getAsUWord()
getAsRWord()
getAsURWord()

alloc is the only one that takes a parameter, which is the size, in bytes, to allocate memory.  Free() releases that memory, as does destruction of the object unless you call noAutoDelete() after alloc().  If you do call noAutoDelete() then your DLL is going to have release the memory.  DAQFactory won't under any circumstances (including quitting).  getPointer() returns a pointer to the allocated memory and is what you would pass to SetDataBuffer().  The rest of the functions simply retrieve the data as a normal DAQFactory array, translated based on the function called.

So, the general format would be:

global myBlock = new(DMemory)
myBlock.alloc(8192*2)
ps4000SetDataBuffer(...., myBlock.getPointer(),...)


If you don't call noAutoDelete(), which likely you should not, be careful that you tell your DLL that the pointer is no longer valid before letting the DMemory object go out of scope or otherwise be destroyed (for example by setting myBlock to some other value, or calling alloc() again).

Note also that your extern() function should replace word[8192] with unsigned long, since it is a 32 bit pointer you are passing and not a DAQFactory generated pointer.  Also note that you need to make sure and allocate enough to cover what you tell the DLL, in your case 8192 WORDs, which are 2 bytes each, thus alloc(2*8192)

BTW: using this is a bit advanced and if you misuse you will get memory leaks and/or DAQFactory crashes, so save often!  Also watch Task Manager and make sure your DAQFactory memory usage isn't constantly climbing (indicating that you are leaking).  You likely won't leak unless you call noAutoDelete(), but you will crash DAQFactory if you reallocate memory without telling your DLL because the DLL will then try and access invalid memory in the background and DAQFactory can't protect against that.

Link to comment
Share on other sites

Thank you for reply.

Looks like the Daq Factory cant find Class "DMemory". Also havent found the DMemory in DAQF help.

My code> 

global PSBufferCHA_raw = new(DMemory)
PSBufferCHA_raw.alloc(8192*2)

Response> global PSBufferCHA_raw = new(DMemory)
PSBufferCHA_raw.alloc(8192*2)

Link to comment
Share on other sites

Perfect, Resolved, thank you for your help it works with the 18.1.

Regards, Radek.

Final code for ref>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

/////PICO SCOPE Measurment Block read
//global PSBufferCHA_raw[8192][2] = 0

global PSBufferCHA_raw = new(DMemory)
PSBufferCHA_raw.alloc(8192*2)
global PSBufferCHA_rawPointer = 0
PSBufferCHA_rawPointer = PSBufferCHA_raw.getPointer()
global PSBufferCHA_rawWord[8192] = -1

global PSsampleInterval = 20  //Sample time in us / mikrosekund cas pro samplovani  - NENI POUZITO, je to jen pro stream, ktery nefunguje
global PSTimebase = 500  ///500 is cca 40kHz  20e6/(500-1)
global PSsampleInterval_ns = 20  //real sample time ins ns / skutecny samplovaci cas v ns, je pak aktualizovano funkci ..GetTimebase  
global PStimeIndisposedMs = 0  //real time to take one block / skutecny cas na sebrani jednoho bloku v Ms
global PSmaxSamples = 8192  //max no of samples / skutecne mnozstvi samplu ktere umoznuje pamet zarizeni, je pak aktualizovano funkci ..GetTimebase
global PSnoOfSamples = 8192 //on entry: the number of samples requested; on exit,the number of samples actually returned, aktualizovano funkci ..GetValues
global PSnoOfSamplesExit = 8192   //samples in buffer after data acquisistion  /pocet dat buferu po mereni
global PSoverflow = 0  //indicate whether an overvoltage has occurred on any of the channels. It is a bit pattern with bit 0 denoting Channel A and bit 1 Channel B.
global PSReady = 1  //on exit, indicates the state of the collection. If zero, the device is still collecting. If non-zero, the device has finished collecting and ps4000GetValues can be used to retrieve the data.

global PICOStatusRunBlock = -1
global PICOStatusIsReady = -1
global PICOStatusSetDataBuffer = -1
global PICOStatusGetValues = -1

private i = 0

extern("ps4000.dll","long ps4000SetChannel(word, byte, word, word, byte)","ps4000SetChannel","stdcall") //CH A setting / nastaveni kanalu A 
extern("ps4000.dll","long ps4000GetTimebase(word, ulong, long, long[1], word, long[1], uword)","ps4000GetTimebase","stdcall") ///Time base check / zjisteni Time Base
extern("ps4000.dll","long ps4000RunBlock(word, long, long, ulong, word, long[1], uword, long, long[1])","ps4000RunBlock","stdcall")  ///spusteni mereni Bloku
extern("ps4000.dll","long ps4000GetValues(word, ulong, ulong[1], ulong, word, uword, word[1])","ps4000GetValues","stdcall") ////stazeni hodnot z buferu driveru pro Blok mod
extern("ps4000.dll","long ps4000IsReady(word, word[1])","ps4000IsReady","stdcall")
extern("ps4000.dll","long ps4000SetDataBuffer(word, word, ulong, long)","ps4000SetDataBuffer","stdcall") ///registrace data Bufferu A

i=0
while (i <= PSnoOfSamples)                         ///baseline buffer setting -1 set to confirm it is reading something/ vycteni hodnot z bufferu do virtualniho kanalu
   PSBufferCHA_rawWord = -1
      i=i+1
endwhile
  
///SET CHANNELS
while (PICOStatus != 0)
   PICOStatus = ps4000SetChannel(PSHandle,0,1,1,8) ///handle, channel, enabled, AC /DC (0/1), range
   PICOStatus = ps4000SetChannel(PSHandle,1,0,1,8)
endwhile

///GET TIME BASE
PICOStatus = ps4000GetTimebase(PSHandle,PSTimebase,8192,@PSsampleInterval_ns,1,@PSmaxSamples,0) ///handle, timebase (500 odpovida cca 40kHz  20e6/(500-1)), noSamples, *timeIntervalNanoseconds, oversample, *maxsample, segmentIndex

PSnoOfSamples = 8192  ///sresetovani nastaveni bufferu aby se stale nezmensoval

if (PSnoOfSamples > PSmaxSamples )   ///check if buffer demand is not higher then capability of the device / kontrola zda neni pozadovan vetsi bufer nez zarizeni zvladne
   PSnoOfSamples = PSmaxSamples
endif

 
 ///SET DATA BUFFER
 PICOStatusSetDataBuffer = ps4000SetDataBuffer(PSHandle,0,PSBufferCHA_rawPointer,PSnoOfSamples)   ///handle, channel, buffer, buffer length

////MEASUREMENT
while (1)   ///opakovani mereni

   PSReady = 0
///RUN BLOCK / spusteni mereni Bloku
     PICOStatusRunBlock = ps4000RunBlock(PSHandle,0,PSnoOfSamples,PSTimebase,1,@PStimeIndisposedMs,0,NULL,NULL) ///handle, noOfPreTriggerSamples, noOfPostTriggerSamples, timebase, oversample, * timeIndisposedMs, segmentIndex, lpReady, * pParameter 

   PSnoOfSamplesExit= PSnoOfSamples  //srovnani velikosti buferu aby se nezmensoval    
    
   ///IS READY
   PICOStatusIsReady = ps4000IsReady(PSHandle,@PSReady)   ///handle, *PSReady 
     
   while (PSReady == 0)                                  ////procedura ceka na ukonceni mereni
     PICOStatusIsReady = ps4000IsReady(PSHandle,@PSReady)
   delay(0.05)
   endwhile 
   
      
   ///GET VALUES  / stazeni hodnot z buferu driveru pro Blok mod
   PICOStatusGetValues = ps4000GetValues(PSHandle,0,@PSnoOfSamplesExit,1,0,0,@PSoverflow)   ///handle, startIndex, * noOfSamples, downSampleRatio, downSampleRatioMode, segmentIndex, * overflow 

   PSBufferCHA_rawWord = PSBufferCHA_raw.getAsWord()
   
   V.PICO_CH_A.AddValue = PSBufferCHA_rawWord
  
endwhile

PSBufferCHA_raw.free()   ///this to be included also in closing PICO close Sequence to freeup memory

End Code>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Link to comment
Share on other sites

My only recommendation would be to create PSBufferCHA_raw once at startup and then don't mess with it at all.  DAQFactory will destroy the memory automatically when it quits and you have no real reason to free that memory during execution.  It is not a big block and freeing it runs the risk of an errant pointer.  In your case, you forgot to tell the Pico to stop using the memory before you called free() which is exactly my concern.  

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.