Radek Posted June 10, 2021 Share Posted June 10, 2021 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 Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted June 21, 2021 Share Posted June 21, 2021 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. Quote Link to comment Share on other sites More sharing options...
Radek Posted June 25, 2021 Author Share Posted June 25, 2021 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) Quote Link to comment Share on other sites More sharing options...
Radek Posted June 25, 2021 Author Share Posted June 25, 2021 Sorry tge repsonse was> "Class does not exist, can't instantiate.: PICOBlockRead Line 4 - Uncaught error in sequence PICOBlockRead" Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted June 25, 2021 Share Posted June 25, 2021 This is only supported in the latest release of DAQFactory, i.e. 18.1 and possibly 17.1. It is not documented. Quote Link to comment Share on other sites More sharing options...
Radek Posted June 26, 2021 Author Share Posted June 26, 2021 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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted June 28, 2021 Share Posted June 28, 2021 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. Quote Link to comment Share on other sites More sharing options...
Radek Posted June 28, 2021 Author Share Posted June 28, 2021 OK, agree, thanks. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.