PicoScope 7 Software
Available on Windows, Mac and Linux
Code: Select all
import ctypes
import numpy as np
from picosdk.ps5000a import ps5000a as ps
import matplotlib.pyplot as plt
from picosdk.functions import adc2mV, assert_pico_ok, mV2adc
from picosdk.constants import make_enum #Needs this to make missing PWQ enum
# This enumerator is missing from the picoSDK? create it here.
PS5000A_PULSE_WIDTH_TYPE = make_enum([
"PS5000A_PW_TYPE_NONE",
"PS5000A_PW_TYPE_LESS_THAN",
"PS5000A_PW_TYPE_GREATER_THAN",
"PS5000A_PW_TYPE_IN_RANGE",
"PS5000A_PW_TYPE_OUT_OF_RANGE",
"PS5000A_DIGITAL_DIRECTION_RISING_OR_FALLING",
"PS5000A_PULSE_WIDTH_TYPE"
])
# Create chandle and status ready for use
chandle = ctypes.c_int16()
status = {}
# picoSDK can not adjust for probe attenuation, a 1:1 probe should be used where possible.
# If not, set the probe attenuation here so the attenuation can be applied after aquisition.
probeAttenuation = 10
# Open 5000 series PicoScope========================================================================================================
# Resolution set to 12 Bit
resolution =ps.PS5000A_DEVICE_RESOLUTION["PS5000A_DR_12BIT"]
# Returns handle to chandle for use in future API functions
status["openunit"] = ps.ps5000aOpenUnit(ctypes.byref(chandle), None, resolution)
try:
assert_pico_ok(status["openunit"])
except: # PicoNotOkError:
powerStatus = status["openunit"]
if powerStatus == 286:
status["changePowerSource"] = ps.ps5000aChangePowerSource(chandle, powerStatus)
elif powerStatus == 282:
status["changePowerSource"] = ps.ps5000aChangePowerSource(chandle, powerStatus)
else:
raise
assert_pico_ok(status["changePowerSource"])
# Set up channels================================================================================================================
channelA = ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"]
channelB = ps.PS5000A_CHANNEL["PS5000A_CHANNEL_B"]
enabled = 1
coupling_type = ps.PS5000A_COUPLING["PS5000A_DC"]
chARange = ps.PS5000A_RANGE["PS5000A_1V"] #volts per division (10 divisions total)
chBRange = ps.PS5000A_RANGE["PS5000A_1V"] #volts per division (10 divisions total)
analogue_offset = 0 #(Volts)
status["setChA"] = ps.ps5000aSetChannel(chandle, channelA, enabled, coupling_type, chARange, analogue_offset)
assert_pico_ok(status["setChA"])
status["setChB"] = ps.ps5000aSetChannel(chandle, channelB, enabled, coupling_type, chBRange, analogue_offset)
assert_pico_ok(status["setChB"])
# find maximum ADC count value===============================================================================================
maxADC = ctypes.c_int16()
status["maximumValue"] = ps.ps5000aMaximumValue(chandle, ctypes.byref(maxADC))
assert_pico_ok(status["maximumValue"])
# Set up a ulse width trigger==============================================================================================================
#Set Conditions----------------------------------------------------------------------------------------------------------------------------
clear = 1
add = 2
num_conditions = 1
#Set Channel A as the trigger channel
triggerConditions = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"]
)
status["ps5000aSetTriggerChannelConditionsV2"] = ps.ps5000aSetTriggerChannelConditionsV2(chandle,ctypes.byref(triggerConditions), num_conditions, clear)
assert_pico_ok(status["ps5000aSetTriggerChannelConditionsV2"])
#Apply the pulse width qualifier to channel A
status["ps5000aSetPulseWidthQualifierConditions"] = ps.ps5000aSetPulseWidthQualifierConditions(chandle,ctypes.byref(triggerConditions), num_conditions, clear)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierConditions"])
#Set Directions---------------------------------------------------------------------------------------------------------------------------
#For positive pulse detection, we need to trigger on the falling edge and set the PWQ to reset/start counting on the rising edge.
num_directions = 1
triggerDirection = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_FALLING"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
status["ps5000aSetTriggerChannelDirectionsV2"] = ps.ps5000aSetTriggerChannelDirectionsV2(chandle, ctypes.byref(triggerDirection), num_directions)
assert_pico_ok(status["ps5000aSetTriggerChannelDirectionsV2"])
PWQDirection = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_RISING"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
status["ps5000aSetPulseWidthQualifierDirections"] = ps.ps5000aSetPulseWidthQualifierDirections(chandle, ctypes.byref(triggerDirection), num_directions)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierDirections"])
#Set Properties---------------------------------------------------------------------------------------------------------------------------
triggerLevelmV = 1000
triggerLevel = triggerLevelmV/probeAttenuation
adcTriggerLevel = mV2adc(triggerLevel, chARange, maxADC)
thresholdUpperHysteresis = 10
thresholdLower = 0 #not used for rising or falling edge directions
thresholdLowerHysteresis = 10
triggerProperties = ps.PS5000A_TRIGGER_CHANNEL_PROPERTIES_V2( adcTriggerLevel, # Threhold upper
thresholdUpperHysteresis,
thresholdLower, #Threshold lower
thresholdLowerHysteresis,
ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"]
)
status["ps5000aSetTriggerChannelPropertiesV2"] = ps.ps5000aSetTriggerChannelPropertiesV2(chandle, ctypes.byref(triggerProperties), 1, 0)
assert_pico_ok(status["ps5000aSetTriggerChannelPropertiesV2"])
lower = 162 #time base of 3 at 12bit gives a 8ns sample time. 8ns*162= 1.296us
upper = 0 # Not used for greater than trigger, only used for in-range or out-of-range triggers
PWQType = PS5000A_PULSE_WIDTH_TYPE["PS5000A_PW_TYPE_GREATER_THAN"]
status["ps5000aSetPulseWidthQualifierProperties"] = ps.ps5000aSetPulseWidthQualifierProperties(chandle, lower, upper, PWQType)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierProperties"])
#Configure timebase======================================================================================================================================
preTriggerSamples = 1000
postTriggerSamples = 5000
maxSamples = preTriggerSamples + postTriggerSamples
timebase = 3 #8ns at 12-bit
segment_index = 0
returnedTimeIntervalns = ctypes.c_float()
returnedMaxSamples = ctypes.c_int32()
#pass in pointers to maxIntervalns and maxSamples and rturns actual max values
status["getTimebase2"] = ps.ps5000aGetTimebase2(chandle, timebase, maxSamples, ctypes.byref(returnedTimeIntervalns), ctypes.byref(returnedMaxSamples), segment_index)
assert_pico_ok(status["getTimebase2"])
# Run block capture======================================================================================================================================
status["runBlock"] = ps.ps5000aRunBlock(chandle, preTriggerSamples, postTriggerSamples, timebase, None, segment_index, None, None)
assert_pico_ok(status["runBlock"])
# Check for data collection to finish using ps5000aIsReady
ready = ctypes.c_int16(0)
check = ctypes.c_int16(0)
while ready.value == check.value:
status["isReady"] = ps.ps5000aIsReady(chandle, ctypes.byref(ready))
# Create buffers ready for assigning pointers for data collection==========================================================================================================
bufferAMax = (ctypes.c_int16 * maxSamples)()
bufferAMin = (ctypes.c_int16 * maxSamples)() # used for downsampling which isn't used
bufferBMax = (ctypes.c_int16 * maxSamples)()
bufferBMin = (ctypes.c_int16 * maxSamples)() # used for downsampling which isn't used
# Set data buffer location for data collection
segment_index = 0
ratio_mode = 0 #PS5000A_RATIO_MODE_NONE
status["setDataBuffersA"] = ps.ps5000aSetDataBuffers(chandle, channelA, ctypes.byref(bufferAMax), ctypes.byref(bufferAMin), maxSamples, segment_index, ratio_mode)
assert_pico_ok(status["setDataBuffersA"])
status["setDataBuffersB"] = ps.ps5000aSetDataBuffers(chandle, channelB, ctypes.byref(bufferBMax), ctypes.byref(bufferBMin), maxSamples, segment_index, ratio_mode)
assert_pico_ok(status["setDataBuffersB"])
# create overflow loaction
overflow = ctypes.c_int16()
# create converted type maxSamples
cmaxSamples = ctypes.c_int32(maxSamples)
# Retrive data from scope to buffers assigned above=====================================================================================================================
startIndex = 0
downsampleRatio = 0
downsampleRatioMode = 0 #PS5000A_RATIO_MODE_NONE
status["getValues"] = ps.ps5000aGetValues(chandle, startIndex, ctypes.byref(cmaxSamples), downsampleRatio, downsampleRatioMode, segment_index, ctypes.byref(overflow))
assert_pico_ok(status["getValues"])
# Plot the data========================================================================================================================================================
# convert ADC counts data to mV
adc2mVChAMax = adc2mV(bufferAMax, chARange, maxADC)
adc2mVChBMax = adc2mV(bufferBMax, chBRange, maxADC)
# Apply probe attenuation
attenuatedValuesA = [i * probeAttenuation for i in adc2mVChAMax]
attenuatedValuesB = [i * probeAttenuation for i in adc2mVChBMax]
# Create time data
time = np.linspace(0, (cmaxSamples.value - 1) * returnedTimeIntervalns.value, cmaxSamples.value)
# plot data from channel A and B
plt.plot(time, attenuatedValuesA[:], label='A')
plt.plot(time, attenuatedValuesB[:], label='B')
plt.legend()
plt.xlabel('Time (ns)')
plt.ylabel('Voltage (mV)')
plt.show()
# Stop the scope
status["stop"] = ps.ps5000aStop(chandle)
assert_pico_ok(status["stop"])
# Close unit Disconnect the scope
status["close"]=ps.ps5000aCloseUnit(chandle)
assert_pico_ok(status["close"])
# display status returns
print(status)
Code: Select all
# Set up a pulse width trigger==================================================================================================
# Set channel A voltage and hysteresis
triggerLevelmV = 1000
triggerLevel = triggerLevelmV/probeAttenuation
upperThreshold = mV2adc(triggerLevel, chARange, maxADC)
thresholdUpperHysteresis = 10
thresholdLower = 0 #not used for rising or falling edge directions
thresholdLowerHysteresis = 0
triggerProperties = ps.PS5000A_TRIGGER_CHANNEL_PROPERTIES_V2( upperThreshold, # Threhold upper
thresholdUpperHysteresis,
thresholdLower, #Threshold lower
thresholdLowerHysteresis,
ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"]
)
status["ps5000aSetTriggerChannelPropertiesV2"] = ps.ps5000aSetTriggerChannelPropertiesV2(chandle, ctypes.byref(triggerProperties), 1, 0)
assert_pico_ok(status["ps5000aSetTriggerChannelPropertiesV2"])
# Set channel A direction as rising and level
num_directions = 1
ChannelDirection = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_RISING"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
status["ps5000aSetPulseWidthQualifierDirections"] = ps.ps5000aSetPulseWidthQualifierDirections(chandle, ctypes.byref(ChannelDirection), num_directions)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierDirections"])
# Set channel conditions as A=FALSE & PWQ=TRUE
clear = 1
add = 2
triggerConditionsA = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_FALSE"]
)
triggerConditionsPWQ = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_PULSE_WIDTH_SOURCE"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"]
)
trigCond = [triggerConditionsA, triggerConditionsPWQ]
num_conditions = 2
Conditions = ps.PS5000A_CONDITION*num_conditions
trigConditions = Conditions(*trigCond) # Combine the condition structs into an array
status["setTriggerChannelConditions"] = ps.ps5000aSetTriggerChannelConditionsV2(chandle,ctypes.byref(trigConditions), num_conditions, clear)
assert_pico_ok(status["setTriggerChannelConditions"])
# Set PWQ direction as channel A, above and level
num_directions = 1
PWQDirection = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_ABOVE"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
status["ps5000aSetPulseWidthQualifierDirections"] = ps.ps5000aSetPulseWidthQualifierDirections(chandle, ctypes.byref(PWQDirection), num_directions)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierDirections"])
# Set pulse timing and trigger requirement
lower = 162 #time base of 3 at 12bit gives a 8ns sample time. 8ns*162= 1.296us
upper = 0 # Not used for greater than trigger, only used for in-range or out-of-range triggers
PWQType = PS5000A_PULSE_WIDTH_TYPE["PS5000A_PW_TYPE_GREATER_THAN"]
status["ps5000aSetPulseWidthQualifierProperties"] = ps.ps5000aSetPulseWidthQualifierProperties(chandle, lower, upper, PWQType)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierProperties"])
Code: Select all
# Set channel A direction as rising and level
num_directions = 1
ChannelDirection = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_RISING"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
status["ps5000aSetPulseWidthQualifierDirections"] = ps.ps5000aSetPulseWidthQualifierDirections(chandle, ctypes.byref(ChannelDirection), num_directions)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierDirections"])
Code: Select all
# Set channel A & B direction to none as checking for pulse width only
ChannelDirectionA = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_NONE"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
ChannelDirectionB = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_B"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_NONE"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
num_directions = 2
channelDir = [ChannelDirectionA, ChannelDirectionB]
Directions = ps.PS5000A_DIRECTION*num_directions
channelDirections = Directions(*channelDir) # Combine the Direction structs into an array
status["ps5000aSetTriggerChannelDirectionsV2"] = ps.ps5000aSetTriggerChannelDirectionsV2(chandle, ctypes.byref(channelDirections), num_directions)
assert_pico_ok(status["ps5000aSetTriggerChannelDirectionsV2"])
Code: Select all
# Set channel conditions as A=FALSE & PWQ=TRUE
clear = 1
add = 2
triggerConditionsA = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_FALSE"]
)
triggerConditionsPWQ = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_PULSE_WIDTH_SOURCE"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"]
)
trigCond = [triggerConditionsA, triggerConditionsPWQ]
num_conditions = 2
Conditions = ps.PS5000A_CONDITION*num_conditions
trigConditions = Conditions(*trigCond) # Combine the condition structs into an array
status["ps5000aSetTriggerChannelConditionsV2"] = ps.ps5000aSetTriggerChannelConditionsV2(chandle,ctypes.byref(trigConditions), num_conditions, clear)
assert_pico_ok(status["ps5000aSetTriggerChannelConditionsV2"])
Code: Select all
# Set CHANNEL CONDITIONS as A=TRUE & PWQ=TRUE
clear = 1
add = 2
triggerConditionsA = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"]
)
triggerConditionsPWQ = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_PULSE_WIDTH_SOURCE"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"]
)
trigCond = [triggerConditionsA, triggerConditionsPWQ]
num_conditions = 2
Conditions = ps.PS5000A_CONDITION*num_conditions
trigConditions = Conditions(*trigCond) # Combine the condition structs into an array
status["ps5000aSetTriggerChannelConditionsV2"] = ps.ps5000aSetTriggerChannelConditionsV2(chandle,ctypes.byref(trigConditions), num_conditions, clear)
assert_pico_ok(status["ps5000aSetTriggerChannelConditionsV2"])
# Set CHANNEL DIRECTION as A Falling and Level
ChannelDirectionA = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_FALLING"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
num_directions = 1
status["ps5000aSetTriggerChannelDirectionsV2"] = ps.ps5000aSetTriggerChannelDirectionsV2(chandle, ctypes.byref(ChannelDirectionA), num_directions)
assert_pico_ok(status["ps5000aSetTriggerChannelDirectionsV2"])
# Set CHANNEL PROPERTIES A threshold voltage and hysteresis as 1.9V
triggerLevelmV = 1900
triggerLevel = triggerLevelmV/probeAttenuation
upperThreshold = mV2adc(triggerLevel, chARange, maxADC)
thresholdUpperHysteresis = 10
thresholdLower = 0 #not used for rising or falling edge directions
thresholdLowerHysteresis = 0 #not used for rising or falling edge directions
triggerProperties = ps.PS5000A_TRIGGER_CHANNEL_PROPERTIES_V2( upperThreshold,
thresholdUpperHysteresis,
thresholdLower,
thresholdLowerHysteresis,
ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"]
)
status["ps5000aSetTriggerChannelPropertiesV2"] = ps.ps5000aSetTriggerChannelPropertiesV2(chandle, ctypes.byref(triggerProperties), 1, 0)
assert_pico_ok(status["ps5000aSetTriggerChannelPropertiesV2"])
#Set PWQ CONDITIONS
clear = 1
add = 2
num_PWQ_conditions = 1
PWQConditions = ps.PS5000A_CONDITION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"]
)
status["ps5000aSetPulseWidthQualifierConditions"] = ps.ps5000aSetPulseWidthQualifierConditions(chandle,ctypes.byref(trigConditions), num_PWQ_conditions, clear)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierConditions"])
# Set PWQ DIRECTIONS as channel A, rising and level
num_directions = 1
PWQDirection = ps.PS5000A_DIRECTION( ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
ps.PS5000A_THRESHOLD_DIRECTION["PS5000A_RISING"],
ps.PS5000A_THRESHOLD_MODE["PS5000A_LEVEL"]
)
status["ps5000aSetPulseWidthQualifierDirections"] = ps.ps5000aSetPulseWidthQualifierDirections(chandle, ctypes.byref(PWQDirection), num_directions)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierDirections"])
# Set PWQ PROPERTIES pulse timing and trigger requirement
lower = 162 #time base of 3 at 12bit gives a 8ns sample time. 8ns*162= 1.296us
upper = 0 # Not used for greater than trigger, only used for in-range or out-of-range triggers
PWQType = PS5000A_PULSE_WIDTH_TYPE["PS5000A_PW_TYPE_GREATER_THAN"]
status["ps5000aSetPulseWidthQualifierProperties"] = ps.ps5000aSetPulseWidthQualifierProperties(chandle, lower, upper, PWQType)
assert_pico_ok(status["ps5000aSetPulseWidthQualifierProperties"])