|
| 1 | +# |
| 2 | +# Copyright (C) 2024 Pico Technology Ltd. See LICENSE file for terms. |
| 3 | +# |
| 4 | +# PSOSPA STREAMING MODE EXAMPLE |
| 5 | +# This example opens a psospa driver device, sets up two channels then collects a streamed set of data. |
| 6 | +# The data from channel A is then plotted as mV against time in ns. |
| 7 | + |
| 8 | +import ctypes |
| 9 | +import numpy as np |
| 10 | +from picosdk.psospa import psospa as ps |
| 11 | +from picosdk.PicoDeviceEnums import picoEnum as enums |
| 12 | +from picosdk.PicoDeviceStructs import picoStruct as structs |
| 13 | +import matplotlib.pyplot as plt |
| 14 | +from picosdk.functions import adc2mVV2, assert_pico_ok, mV2adcV2 |
| 15 | +from picosdk.constants import PICO_STATUS |
| 16 | +import time |
| 17 | + |
| 18 | +# Create chandle and status ready for use |
| 19 | +chandle = ctypes.c_int16() |
| 20 | +status = {} |
| 21 | + |
| 22 | +# Open a psospa driver device |
| 23 | +# returns handle for future API functions |
| 24 | +resolution = enums.PICO_DEVICE_RESOLUTION["PICO_DR_8BIT"] |
| 25 | +status["openUnit"] = ps.psospaOpenUnit(ctypes.byref(chandle), None, resolution, None) |
| 26 | +assert_pico_ok(status["openUnit"]) |
| 27 | + |
| 28 | +# Set channel A on |
| 29 | +# handle = chandle |
| 30 | +channelA = enums.PICO_CHANNEL["PICO_CHANNEL_A"] |
| 31 | +coupling = enums.PICO_COUPLING["PICO_DC"] |
| 32 | +rangeMax = 2000000000 #nV |
| 33 | +rangeMin = -rangeMax #nV |
| 34 | +rangeType = 0 #probes.PICO_PROBE_RANGE_INFO["PICO_PROBE_NONE_NV"] |
| 35 | +analogueOffset = 0 |
| 36 | +bandwidth = enums.PICO_BANDWIDTH_LIMITER["PICO_BW_FULL"] |
| 37 | +status["setChannelA"] = ps.psospaSetChannelOn(chandle, channelA, coupling, rangeMin, rangeMax, rangeType, analogueOffset, bandwidth) |
| 38 | +assert_pico_ok(status["setChannelA"]) |
| 39 | + |
| 40 | +channelB = enums.PICO_CHANNEL["PICO_CHANNEL_B"] |
| 41 | +status["setChannelB"] = ps.psospaSetChannelOn(chandle, channelB, coupling, rangeMin, rangeMax, rangeType, analogueOffset, bandwidth) |
| 42 | +assert_pico_ok(status["setChannelB"]) |
| 43 | + |
| 44 | +# set channel C-D off |
| 45 | +for x in range(2, 3, 1): |
| 46 | + channel = x |
| 47 | + status["setChannel", x] = ps.psospaSetChannelOff(chandle, channel) |
| 48 | + assert_pico_ok(status["setChannel", x]) |
| 49 | + |
| 50 | +# Set number of samples to be collected |
| 51 | +noOfPreTriggerSamples = 100000 |
| 52 | +noOfPostTriggerSamples = 900000 |
| 53 | +nSamples = noOfPostTriggerSamples + noOfPreTriggerSamples |
| 54 | + |
| 55 | +# get max ADC value |
| 56 | +# handle = chandle |
| 57 | +minADC = ctypes.c_int16() |
| 58 | +maxADC = ctypes.c_int16() |
| 59 | +status["getAdcLimits"] = ps.psospaGetAdcLimits(chandle, resolution, ctypes.byref(minADC), ctypes.byref(maxADC)) |
| 60 | +assert_pico_ok(status["getAdcLimits"]) |
| 61 | + |
| 62 | +# Set simple trigger on channel A, 1 V rising with 1 s autotrigger |
| 63 | +# handle = chandle |
| 64 | +# enable = 1 |
| 65 | +source = channelA |
| 66 | +# threshold = 100 mV |
| 67 | +direction = enums.PICO_THRESHOLD_DIRECTION["PICO_RISING"] |
| 68 | +# delay = 0 s |
| 69 | +# autoTriggerMicroSeconds = 1000000 us |
| 70 | +status["setSimpleTrigger"] = ps.psospaSetSimpleTrigger(chandle, 1, source, (mV2adcV2(100,rangeMax,maxADC)), direction, 0, 1000000) |
| 71 | +assert_pico_ok(status["setSimpleTrigger"]) |
| 72 | + |
| 73 | +# create buffers |
| 74 | +maxBuffers = 10 |
| 75 | + |
| 76 | +bufferA = ((ctypes.c_int16 * nSamples) * 10)() |
| 77 | +bufferB = ((ctypes.c_int16 * nSamples) * 10)() |
| 78 | + |
| 79 | +# Set data buffers |
| 80 | +# handle = chandle |
| 81 | +# channel = channelA |
| 82 | +# bufferMax = bufferAMax |
| 83 | +# bufferMin = bufferAMin |
| 84 | +# nSamples = nSamples |
| 85 | +dataType = enums.PICO_DATA_TYPE["PICO_INT16_T"] |
| 86 | +waveform = 0 |
| 87 | +downSampleMode = enums.PICO_RATIO_MODE["PICO_RATIO_MODE_RAW"] |
| 88 | +clear = enums.PICO_ACTION["PICO_CLEAR_ALL"] |
| 89 | +add = enums.PICO_ACTION["PICO_ADD"] |
| 90 | +action = clear | add # PICO_ACTION["PICO_CLEAR_WAVEFORM_CLEAR_ALL"] | PICO_ACTION["PICO_ADD"] |
| 91 | +actionAdd = add |
| 92 | +status["setDataBuffersA"] = ps.psospaSetDataBuffer(chandle, channelA, ctypes.byref(bufferA[0]), nSamples, dataType, |
| 93 | + waveform, downSampleMode, action) |
| 94 | +assert_pico_ok(status["setDataBuffersA"]) |
| 95 | +status["setDataBuffersB"] = ps.psospaSetDataBuffer(chandle, channelB, ctypes.byref(bufferB[0]), nSamples, dataType, |
| 96 | + waveform, downSampleMode, actionAdd) |
| 97 | +assert_pico_ok(status["setDataBuffersB"]) |
| 98 | + |
| 99 | +# Run streaming |
| 100 | +sampleInterval = ctypes.c_double(1) |
| 101 | +sampleIntervalTimeUnits = enums.PICO_TIME_UNITS["PICO_US"] |
| 102 | +autoStop = 0 |
| 103 | +downSampleRatio = 1 |
| 104 | + |
| 105 | +status["runStreaming"] = ps.psospaRunStreaming(chandle, ctypes.byref(sampleInterval), sampleIntervalTimeUnits, |
| 106 | + noOfPreTriggerSamples, noOfPostTriggerSamples, autoStop, |
| 107 | + downSampleRatio, downSampleMode) |
| 108 | +assert_pico_ok(status["runStreaming"]) |
| 109 | + |
| 110 | +streamData = (structs.PICO_STREAMING_DATA_INFO * 2)() |
| 111 | +streamData[0] = structs.PICO_STREAMING_DATA_INFO(channelA, downSampleMode, dataType, 0, 0, 0, 0) |
| 112 | +streamData[1] = structs.PICO_STREAMING_DATA_INFO(channelB, downSampleMode, dataType, 0, 0, 0, 0) |
| 113 | + |
| 114 | +streamTrigger = structs.PICO_STREAMING_DATA_TRIGGER_INFO(0, 0, 0) |
| 115 | + |
| 116 | +count = 0 |
| 117 | + |
| 118 | +picoOk = PICO_STATUS["PICO_OK"] |
| 119 | + |
| 120 | +collectedSamples = 0 |
| 121 | + |
| 122 | +while collectedSamples < (maxBuffers*nSamples): |
| 123 | + |
| 124 | + status["getStreamingLatestValues"] = ps.psospaGetStreamingLatestValues(chandle, ctypes.byref(streamData), 1, |
| 125 | + ctypes.byref(streamTrigger)) |
| 126 | + |
| 127 | + if status["getStreamingLatestValues"] == picoOk: |
| 128 | + # do nothing |
| 129 | + time.sleep(0.01) |
| 130 | + else: |
| 131 | + count = count + 1 |
| 132 | + if count < maxBuffers: |
| 133 | + status["setDataBufferA"] = ps.psospaSetDataBuffer(chandle, channelA, ctypes.byref(bufferA[count]), |
| 134 | + nSamples, dataType, waveform, downSampleMode, actionAdd) |
| 135 | + assert_pico_ok(status["setDataBufferA"]) |
| 136 | + status["setDataBufferB"] = ps.psospaSetDataBuffer(chandle, channelB, ctypes.byref(bufferB[count]), |
| 137 | + nSamples, dataType, waveform, downSampleMode, actionAdd) |
| 138 | + assert_pico_ok(status["setDataBufferB"]) |
| 139 | + print(count) |
| 140 | + |
| 141 | + collectedSamples = collectedSamples + streamData[0].noOfSamples |
| 142 | + |
| 143 | +# stop scope streaming |
| 144 | +status["stop"] = ps.psospaStop(chandle) |
| 145 | +assert_pico_ok(status["stop"]) |
| 146 | + |
| 147 | +# get total number of streamed data points |
| 148 | +noOfStreamedSamples=ctypes.c_uint64() |
| 149 | +status["noOfStreamedSamples"] = ps.psospaNoOfStreamingValues(chandle, ctypes.byref(noOfStreamedSamples)) |
| 150 | +assert_pico_ok(status["noOfStreamedSamples"]) |
| 151 | + |
| 152 | +print("streaming finished") |
| 153 | +print("Number of samples collected during streaming") |
| 154 | +print(noOfStreamedSamples.value) |
| 155 | + |
| 156 | + |
| 157 | +# convert ADC counts data to mV |
| 158 | +bufferAmV = [] |
| 159 | +for k in range (0, maxBuffers, 1): |
| 160 | + mvValues = adc2mVV2(bufferA[k], rangeMax, maxADC) |
| 161 | + bufferAmV.append(mvValues) |
| 162 | + |
| 163 | +time = np.linspace(0, ((nSamples -1)*maxBuffers) * sampleInterval.value * 1000000, (nSamples*maxBuffers)) |
| 164 | +startTime = 0 |
| 165 | +endTime = nSamples |
| 166 | +# plot data |
| 167 | +for h in range (0, maxBuffers, 1): |
| 168 | + plt.plot(time[startTime:endTime],bufferAmV[h]) |
| 169 | + startTime += nSamples |
| 170 | + endTime += nSamples |
| 171 | +plt.xlabel('Time (us)') |
| 172 | +plt.ylabel('Voltage (mV)') |
| 173 | +plt.show() |
| 174 | + |
| 175 | + |
| 176 | +# Close the scope |
| 177 | +status["closeunit"] = ps.psospaCloseUnit(chandle) |
| 178 | +assert_pico_ok(status["closeunit"]) |
| 179 | + |
| 180 | +print(status) |
0 commit comments