why dt getting from ''time.per_count() '' not constant with total sampling time?

Post your Python discussions here.
Post Reply
KellyDy
Newbie
Posts: 0
Joined: Tue Jun 11, 2024 11:40 am

why dt getting from ''time.per_count() '' not constant with total sampling time?

Post by KellyDy »

I'm performing sampling using this script. As mentioned earlier, the time difference (dt) measured using time.perf_counter() is not consistent with the total sampling time and varies each time. When the sampling time step is set to 1000 microseconds, the error can even reach nearly 30 milliseconds. I couldn't figure out the reason for this discrepancy. Can anyone help identify the cause of this issue?

```python

Code: Select all

import ctypes
from picosdk.ps5000a import ps5000a as ps
from picosdk.functions import splitMSODataFast, assert_pico_ok
import numpy as np
import csv
import time


def my_sleep(dt):  # dt in ns
    st = time.perf_counter_ns()
    while True:
        if time.perf_counter_ns() - st >= dt:
            break
    return


# Gives the device a handle
status = {}
chandle = ctypes.c_int16()

# Opens the device/s
status["openunit"] = ps.ps5000aOpenUnit(ctypes.byref(chandle), None, ps.PS5000A_DEVICE_RESOLUTION["PS5000A_DR_8BIT"])

try:
    assert_pico_ok(status["openunit"])
except:
    powerstate = status["openunit"]

    if powerstate == 282:
        status["ChangePowerSource"] = ps.ps5000aChangePowerSource(chandle, 282)
    elif powerstate == 286:
        status["ChangePowerSource"] = ps.ps5000aChangePowerSource(chandle, 286)
    else:
        raise

    assert_pico_ok(status["ChangePowerSource"])

# D0-D7
digital_port0 = ps.PS5000A_CHANNEL["PS5000A_DIGITAL_PORT0"]
status["SetDigitalPort0"] = ps.ps5000aSetDigitalPort(chandle, digital_port0, 1, 10000)
assert_pico_ok(status["SetDigitalPort0"])
digital_port1 = ps.PS5000A_CHANNEL["PS5000A_DIGITAL_PORT1"]
status["SetDigitalPort1"] = ps.ps5000aSetDigitalPort(chandle, digital_port1, 1, 10000)
assert_pico_ok(status["SetDigitalPort1"])

# Set the number of samples to be collected
k = 1
preTriggerSamples = 50 * k
postTriggerSamples = 50 * k
totalSamples = preTriggerSamples + postTriggerSamples

timebase = 1252  # 10us
timeIntervalNs = ctypes.c_float()
returnedMaxSamples = ctypes.c_int32()
status["GetTimebase"] = ps.ps5000aGetTimebase2(chandle,
                                               timebase,
                                               totalSamples,
                                               ctypes.byref(timeIntervalNs),
                                               ctypes.byref(returnedMaxSamples),
                                               0)
assert_pico_ok(status["GetTimebase"])
print('timeIntervalNs (us): ', timeIntervalNs.value / 1000)

# Create buffers ready for assigning pointers for data collection
totalSamples *= 2
bufferDPort0Max0 = (ctypes.c_int16 * totalSamples)()
bufferDPort0Min0 = (ctypes.c_int16 * totalSamples)()
bufferDPort0Max1 = (ctypes.c_int16 * totalSamples)()
bufferDPort0Min1 = (ctypes.c_int16 * totalSamples)()
status["SetDataBuffers0"] = ps.ps5000aSetDataBuffers(chandle,
                                                     ps.PS5000A_CHANNEL["PS5000A_DIGITAL_PORT0"],
                                                     ctypes.byref(bufferDPort0Max0),
                                                     ctypes.byref(bufferDPort0Min0),
                                                     totalSamples,
                                                     0,
                                                     0)
status["SetDataBuffers1"] = ps.ps5000aSetDataBuffers(chandle,
                                                     ps.PS5000A_CHANNEL["PS5000A_DIGITAL_PORT1"],
                                                     ctypes.byref(bufferDPort0Max1),
                                                     ctypes.byref(bufferDPort0Min1),
                                                     totalSamples,
                                                     0,
                                                     0)
assert_pico_ok(status["SetDataBuffers0"])
assert_pico_ok(status["SetDataBuffers1"])

# status["autoTriggerus"] = ps.ps5000aSetAutoTriggerMicroSeconds(chandle, 10000)
# assert_pico_ok(status["autoTriggerus"])

# Starts the block capture
status["runblock"] = ps.ps5000aRunBlock(chandle,
                                        preTriggerSamples,
                                        postTriggerSamples,
                                        timebase,
                                        None,
                                        0,
                                        None,
                                        None)

i = 0
while i <= 20:
    ready = ctypes.c_int16(0)
    st1 = time.perf_counter_ns()
    assert_pico_ok(status["runblock"])
    # my_sleep(0.005 * 1e9)
    while ready.value == 0:
        status["isReady"] = ps.ps5000aIsReady(chandle, ctypes.byref(ready))
        # print(time.perf_counter_ns() / 1e6)
    ed = time.perf_counter_ns()
    # print(f"ed in pico: {(ed) / 1e6} ms")
    print(f"Elapsed time: {(ed - st1) / 1e6} ms")

    # Retrieves the data
    cTotalSamples = ctypes.c_int32(totalSamples)
    overflow = (ctypes.c_int16 * 10)()
    status["GetValues"] = ps.ps5000aGetValues(chandle, 0, ctypes.byref(cTotalSamples), 1, 0, 0, ctypes.byref(overflow))
    assert_pico_ok(status["GetValues"])

    # print("Data collection complete.")

    # Obtain binary for Digital Port 0
    bufferDPort0 = splitMSODataFast(cTotalSamples, bufferDPort0Max0)
    bufferDPort1 = splitMSODataFast(cTotalSamples, bufferDPort0Max1)

    # Create the time data
    time_data = np.linspace(0, (cTotalSamples.value - 1) * timeIntervalNs.value, cTotalSamples.value)

    # Combine time data and channel data into a single array for CSV export
    data = np.vstack((time_data, bufferDPort0, bufferDPort1)).T

    # Save data to CSV
    with open('picoscope_data.csv', 'w', newline='') as csvfile:
        csvwriter = csv.writer(csvfile)
        header = ['Time (ns)', 'D7', 'D6']  # Add more headers as needed
        csvwriter.writerow(header)
        csvwriter.writerows(data)

    # print("Data saved to picoscope_data.csv")

    # Stop the scope
    status["stop"] = ps.ps5000aStop(chandle)
    assert_pico_ok(status["stop"])
    my_sleep(2 * 1e9)
    i += 1
    status["runblock"] = ps.ps5000aRunBlock(chandle,
                                            preTriggerSamples,
                                            postTriggerSamples,
                                            timebase,
                                            None,
                                            0,
                                            None,
                                            None)
    # print(ready)

# Close the unit
status["closeUnit"] = ps.ps5000aCloseUnit(chandle)
assert_pico_ok(status["closeUnit"])

# Display the status returns
print(status)
```python

Post Reply