How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post your C and C++ discussions here
XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

Dear all,
Following your helps and suggestions on my former message, I have used successfully the function within ps4000 folder to control my card ps4262 with C++Builder.
Now I have met another difficulty with my new card ps4824a. In ps4000a folder, there are some examples (3 years’ ago) designed for the card ps4824a: https://github.com/picotech/picosdk-c-examples.
I think these functions may be designed for either Visual C++ or Linux. In fact, I have compiled some functions successfully with C++Builder but I can’t get data, there is something wrong in the function “ps4000aRunBlock(unit->handle, 0, sampleCount, timebase, &timeIndisposed, 0, CallBackBlock, NULL)”, the data is never ready!
Many thanks in advance
Warm regards
Xavier

Martyn
Site Admin
Site Admin
Posts: 4137
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by Martyn »

Can you post your code here, or to support@picotech.com , and we can take a look.
Martyn
Technical Support Manager

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

Thank you Martyn.
Here is the function adapted to C++Builder 64bits, version 10.4.
Main issue is in the function "ps4000aRunBlock()": no return value of "timeIndisposed" !
Xavier
void BlockDataHandlerXY(UNIT * unit, int8_t * text, int32_t offset)
{
int32_t timeIndisposed;
int32_t maxSamples;
int32_t i, j;
float timeInterval;
int32_t sampleCount = BUFFER_SIZE;
int16_t *buffers[PS4000A_MAX_CHANNEL_BUFFERS];
FILE *fp = NULL;
PICO_STATUS status;
for (i = 0; i < unit->channelCount; i++)
{
if (unit->channelSettings.enabled)
{
buffers[i * 2] = (int16_t*) calloc(sampleCount, sizeof(int16_t));
buffers[i * 2 + 1] = (int16_t*) calloc(sampleCount, sizeof(int16_t));
status = ps4000aSetDataBuffers(unit->handle, (PS4000A_CHANNEL)i, buffers[i * 2], buffers[i * 2 + 1], sampleCount, 0, PS4000A_RATIO_MODE_NONE);
// printf(status?"BlockDataHandler:ps4000aSetDataBuffers(channel %d) ------ 0x%08x \n":"", i, status);
if (status)
Form1->Memo1->Lines->Add("BlockDataHandler:ps4000aSetDataBuffers ------ channel " + IntToStr(i) + " " + FloatToStr(status));
}

}
/* find the maximum number of samples, the time interval (in timeUnits),
* the most suitable time units */
while (ps4000aGetTimebase2(unit->handle, timebase, sampleCount, &timeInterval, &maxSamples, 0))
{
timebase++;
}
Form1->Memo1->Lines->Add(String("Timebase, SampleInterval: ") + FloatToStr(timebase) + " , " + FloatToStr(timeInterval) );

/* Start it collecting, then wait for completion*/
g_ready = FALSE;
status = ps4000aRunBlock(unit->handle, 0, sampleCount, timebase, &timeIndisposed, 0, CallBackBlock, NULL);
// Problem: no return value of "timeIndisposed" !!!

if (status != PICO_OK && status != PICO_USB3_0_DEVICE_NON_USB3_0_PORT)
{
Form1->Memo1->Lines->Add("Error in BlockDataHandler:ps4000aRunBlock status: " + FloatToStr(status) );
return;
}
Form1->Memo1->Lines->Add("Waiting for trigger...Press a key to abort");

// Why g_ready is never true!
while (!g_ready)
{
Sleep(0);
}

if (g_ready)
{
// Data processing ......
}
else
{
Form1->Memo1->Lines->Add("data collection aborted");
}

if ((status = ps4000aStop(unit->handle)) != PICO_OK)
{
Form1->Memo1->Lines->Add("BlockDataHandler:ps4000aStop ------ 0x%08x " + FloatToStr(status));
}

if (fp != NULL)
{
fclose(fp);
}

for (i = 0; i < unit->channelCount; i++)
if (unit->channelSettings.enabled)
{
free(buffers[i * 2]);
free(buffers[i * 2 + 1]);
}

ClearDataBuffers(unit);
}


void PREF4 CallBackBlock(int16_t handle, PICO_STATUS status, void * pParameter)
{
if (status != PICO_CANCELLED)
{
g_ready = TRUE;
}
}

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

Here is the entrance for data collection:
void __fastcall TForm1::CollectBlockImmediateXY(UNIT * unit)
{
struct tPwq pulseWidth;
struct tPS4000ADirection directions;
memset(&directions, 0, sizeof(struct tPS4000ADirection));
memset(&pulseWidth, 0, sizeof(struct tPwq));

//Memo1->Lines->Add("Collect block immediate...");

SetDefaults(unit);
/* Trigger disabled */
SetTrigger(unit, NULL, 0, NULL, 0, &directions, 1, &pulseWidth, 0, 0, 0);
BlockDataHandlerXY(unit, "First 10 readings\n", 0);
}

Martyn
Site Admin
Site Admin
Posts: 4137
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by Martyn »

Does ps4000aRunBlock return with status OK?

timeIndisposed will return a value in msecs, if the time taken to collect a block of data defined by the settings for timebase and sampleCount is less than 1 msec then the value will be 0
Martyn
Technical Support Manager

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

ps4000aRunBlock doesn't return with status OK (g_ready is always false).
timeIndisposed has always its big and random value. It is not changed after ps4000aRunBlock().
Thanks a lot
Xavier

Martyn
Site Admin
Site Admin
Posts: 4137
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by Martyn »

What error code is being returned?
What values are used for sampleCount and timebase?

Try with a sampleCount of 1000 and a timebase of 2000 and see if you get a value for timeIndisposed (with a different model scope I get 67), and that the BlockCapture runs and collects data.
Martyn
Technical Support Manager

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

In fact, there is no error returned, only status = 286. I have tried with a computer with true USB3.0, always 286 returned.
I have tried with a sampleCount of 1000 and a timebase of 2000: the same as before, timeIndisposed didn't change.
Many thanks
Xavier

Martyn
Site Admin
Site Admin
Posts: 4137
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by Martyn »

You probably get this code on Open Unit as well, you need to use

Code: Select all

ps4000aChangePowerSource
PICO_STATUS ps4000aChangePowerSource
(
int16_t handle,
PICO_STATUS powerstate
)
This function controls the two-stage power-up sequence when the device is plugged
into a non-USB 3.0 port. 
If you receive the PICO_USB3_0_DEVICE_NON_USB3_0_PORT status code from one of
the OpenUnit functions (ps4000aOpenUnit, ps4000aOpenUnitAsync or
ps4000aOpenUnitProgress), you must then call ps4000aChangePowerSource to
switch the device into non-USB 3.0-power mode.
Note. The PicoScope 4824 has two power supply options:
1.To power it from a USB 3.0 port, use the USB 3.0 cable supplied. 
2.To power it from a non-USB 3.0 port, use the double-headed USB 2.0 cable supplied
and plug it into two USB 1.1 or USB 2.0 ports on the host machine.
Martyn
Technical Support Manager

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

Great!
Thanks of your help, it progresses, although I haven't got yet successful result.
Here are modified codes:
void BlockDataHandlerXY(UNIT * unit, int8_t * text, int32_t offset)
{
int32_t timeIndisposed;
int32_t maxSamples;
int32_t i, j;
float timeInterval;
int32_t sampleCount = BUFFER_SIZE;
int16_t *buffers[PS4000A_MAX_CHANNEL_BUFFERS];
FILE *fp = NULL;
PICO_STATUS status;
for (i = 0; i < unit->channelCount; i++)
{
if (unit->channelSettings.enabled)
{
buffers[i * 2] = (int16_t*) calloc(sampleCount, sizeof(int16_t));
buffers[i * 2 + 1] = (int16_t*) calloc(sampleCount, sizeof(int16_t));
status = ps4000aSetDataBuffers(unit->handle, (PS4000A_CHANNEL)i, buffers[i * 2], buffers[i * 2 + 1], sampleCount, 0, PS4000A_RATIO_MODE_NONE);
// printf(status?"BlockDataHandler:ps4000aSetDataBuffers(channel %d) ------ 0x%08x \n":"", i, status);
if (status)
Form1->Memo1->Lines->Add("BlockDataHandler:ps4000aSetDataBuffers ------ channel " + IntToStr(i) + " " + FloatToStr(status));
}
}

/* find the maximum number of samples, the time interval (in timeUnits),
* the most suitable time units */
while (ps4000aGetTimebase2(unit->handle, timebase, sampleCount, &timeInterval, &maxSamples, 0))
{
timebase++;
}
Form1->Memo1->Lines->Add(String("Timebase, SampleInterval: ") + FloatToStr(timebase) + " , " + FloatToStr(timeInterval) );

// 2021.01
unit->openStatus = (int16_t) ChangePowerSource(unit->handle, unit->openStatus);

// Just for testing:
sampleCount = 1000;
timebase = 2000;

/* Start it collecting, then wait for completion*/
g_ready = FALSE;
status = ps4000aRunBlock(unit->handle, 0, sampleCount, timebase, &timeIndisposed, 0, CallBackBlock, NULL);
Form1->Memo1->Lines->Add(String("Returned timeIndisposed = ") + IntToStr(timeIndisposed));

if (status != PICO_OK)
{
Form1->Memo1->Lines->Add("Error in BlockDataHandler:ps4000aRunBlock status: " + FloatToStr(status) );
return;
}
Form1->Memo1->Lines->Add("Waiting for trigger...Press a key to abort");

while (!g_ready)
{
// Sleep(0);
timebase = timebase; // do something as Sleep(0) can't work in my system?
}

if (g_ready)
{
// Data processing ......
status = ps4000aGetValues(unit->handle, 0, (uint32_t*) &sampleCount, 1, PS4000A_RATIO_MODE_NONE, 0, &g_ready);
if (status != PICO_OK)
{
Form1->Memo1->Lines->Add("Error, BlockDataHandler:ps4000aGetValues ------ 0x%08x " + FloatToStr(status));
}
else
{
// Print out the first 10 readings, converting the readings to mV if required
//------------------------------------------------------------------------
Form1->Memo1->Lines->Add(text);
if (scaleVoltages)
Form1->Memo1->Lines->Add("Channel readings are in mV");
else Form1->Memo1->Lines->Add("Channel readings are in ADC Counts");

String AAA = " ";
for (j = 0; j < unit->channelCount; j++)
if (unit->channelSettings[j].enabled)
AAA += String("Channel ") + (char) ('A' + j) + " ";
Form1->Memo1->Lines->Add(AAA);

// Show Values
for (i = offset; i < offset+10; i++)
{
AAA = " ";
for (j = 0; j < unit->channelCount; j++)
if (unit->channelSettings[j].enabled)
{
// Int values and scaled Voltages
AAA += IntToStr(buffers[j * 2]) + " " + IntToStr(adc_to_mv(buffers[j * 2], unit->channelSettings[PS4000A_CHANNEL_A + j].range, unit)) + " ";
}

Form1->Memo1->Lines->Add(AAA);
}


}
}
else
{
Form1->Memo1->Lines->Add("data collection aborted");
}

if ((status = ps4000aStop(unit->handle)) != PICO_OK)
{
Form1->Memo1->Lines->Add("BlockDataHandler:ps4000aStop ------ 0x%08x " + FloatToStr(status));
}
if (fp != NULL)
{
fclose(fp);
}
for (i = 0; i < unit->channelCount; i++)
if (unit->channelSettings.enabled)
{
free(buffers[i * 2]);
free(buffers[i * 2 + 1]);
}
ClearDataBuffers(unit);
}



Here are the tested results:
Channels A and B are selected with scale 10V
The input of the two chennels are short-circuited with 50 Ohm resistances.
The results are not good in values:

Returned timeIndisposed = 42
Waiting for trigger...Press a key to abort
First 10 readings

Channel readings are in mV
Channel A Channel B
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

Just a result of some additional tests with signal generator:
ChanelA is connected to a signal generator: 0 to 2.5V, 10kHz square waveform.
ChanelA is set to no DC coupling (otherwise, all saturation).
ChanelB is short-circuited with 50 Ohm resistor
The recorded time step is correct according to first 100 samples (40 samples / cycle), but the values are not correct: saturation value int16?
If I use Picoscope6, all correct.

Results of my program:
Timebase, SampleInterval: 199 , 2.5E-6 (second)
Returned timeIndisposed = 252
Waiting for trigger...Press a key to abort
First N-point readings.
Channel readings are in ADC Counts and mV
Channel A Channel B
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 -32767 -9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 32767 9990
32767 9990 32767 9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
32767 9990 -32767 -9990
-32767 -9990 -32767 -9990
-32767 -9990 32767 9990
-32767 -9990 32767 9990

Martyn
Site Admin
Site Admin
Posts: 4137
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by Martyn »

What values are you passing to the SetChannel call?
Martyn
Technical Support Manager

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

I have taken the following function (sorry, I don't totally understand the content):
void SetDefaults(UNIT * unit)
{
PICO_STATUS status;
PICO_STATUS powerStatus;
int32_t i;
unit->resolution = Form1->ComboBox2->ItemIndex; // 0 to 4 (I have tested from 8bits to 16 bits)
if (unit->hasETS)
{
status = ps4000aSetEts(unit->handle, PS4000A_ETS_OFF, 0, 0, NULL);
Form1->Memo1->Lines->Add(status?String("SetDefaults:ps4000aSetEts------ %08x "):"" + String(status));
}
powerStatus = ps4000aCurrentPowerSource(unit->handle);
for (i = 0; i < unit->channelCount; i++)
{
status = ps4000aSetChannel(unit->handle, (PS4000A_CHANNEL)(PS4000A_CHANNEL_A + i),
unit->channelSettings[PS4000A_CHANNEL_A + i].enabled,
(PS4000A_COUPLING)unit->channelSettings[PS4000A_CHANNEL_A + i].DCcoupled,
(PS4000A_RANGE)unit->channelSettings[PS4000A_CHANNEL_A + i].range,
unit->channelSettings[PS4000A_CHANNEL_A + i].analogueOffset);
// printf(status?"SetDefaults:ps4000aSetChannel------ 0x%08x \n":"", status);
Form1->Memo1->Lines->Add( status?String("SetDefaults:ps4000aSetChannel------ 0x%08x "):" " + String(status));
}
}
Per some tests, I realized that in each chanel, it measured either -32767 or + 32767. It behaviors as a sign detector!
At the entrance of ps4000aRunBlock(....), I have captured all values of unit by debug (I try to upload a picture, I am not sure it works, here is the link: http://xaviery.free.fr/000.jpg):
Image

Many thanks for your help.
Xavier

Martyn
Site Admin
Site Admin
Posts: 4137
Joined: Fri Jun 10, 2011 8:15 am
Location: St. Neots

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by Martyn »

Try setting

(PS4000A_RANGE)unit->channelSettings[PS4000A_CHANNEL_A + i].range,

to the 50V range, and see if you get sensible values. This is the maximum gange for your device.
Martyn
Technical Support Manager

XavierPico
Newbie
Posts: 0
Joined: Thu Jan 23, 2020 5:16 pm

Re: How to control Picoscope card 4824a by Embarcadero C++ Builder?

Post by XavierPico »

I have tried to set
(PS4000A_RANGE)unit->channelSettings[PS4000A_CHANNEL_A + i].range: 5, 10 and 50V.
In all these cases, buffer values are always -32767, +32767, i.e. .range doesn't have any effect on the channels.
Furthermore, when DCCoupled is enabled, results are even worse: almost all saturation.
I wonder if any different format of INT values: the order of High byte and Low byte? (but with my 4642, every thing is OK).

Post Reply