1+ #
2+ # Copyright (C) 2018-2022 Pico Technology Ltd. See LICENSE file for terms.
3+ #
4+ # PS5000A BLOCK MODE EXAMPLE
5+ # This example opens a 5000a driver device, sets up two channels and a trigger then collects a block of data.
6+ # This data is then plotted as mV against time in ns.
7+
8+ import ctypes
9+ import numpy as np
10+ from picosdk .ps5000a import ps5000a as ps
11+ import matplotlib .pyplot as plt
12+ from picosdk .functions import adc2mV , assert_pico_ok , mV2adc
13+ import math
14+
15+ # Create chandle and status ready for use
16+ chandle = ctypes .c_int16 ()
17+ status = {}
18+
19+ # Open 5000 series PicoScope
20+ # Resolution set to 12 Bit
21+ resolution = ps .PS5000A_DEVICE_RESOLUTION ["PS5000A_DR_12BIT" ]
22+ # Returns handle to chandle for use in future API functions
23+ status ["openunit" ] = ps .ps5000aOpenUnit (ctypes .byref (chandle ), None , resolution )
24+
25+ try :
26+ assert_pico_ok (status ["openunit" ])
27+ except : # PicoNotOkError:
28+
29+ powerStatus = status ["openunit" ]
30+
31+ if powerStatus == 286 :
32+ status ["changePowerSource" ] = ps .ps5000aChangePowerSource (chandle , powerStatus )
33+ elif powerStatus == 282 :
34+ status ["changePowerSource" ] = ps .ps5000aChangePowerSource (chandle , powerStatus )
35+ else :
36+ raise
37+
38+ assert_pico_ok (status ["changePowerSource" ])
39+
40+ # Set up channel A
41+ # handle = chandle
42+ channel = ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_A" ]
43+ # enabled = 1
44+ coupling_type = ps .PS5000A_COUPLING ["PS5000A_DC" ]
45+ chARange = ps .PS5000A_RANGE ["PS5000A_20V" ]
46+ # analogue offset = 0 V
47+ status ["setChA" ] = ps .ps5000aSetChannel (chandle , channel , 1 , coupling_type , chARange , 0 )
48+ assert_pico_ok (status ["setChA" ])
49+
50+ # Set up channel B
51+ # handle = chandle
52+ channel = ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_B" ]
53+ # enabled = 1
54+ # coupling_type = ps.PS5000A_COUPLING["PS5000A_DC"]
55+ chBRange = ps .PS5000A_RANGE ["PS5000A_2V" ]
56+ # analogue offset = 0 V
57+ status ["setChB" ] = ps .ps5000aSetChannel (chandle , channel , 1 , coupling_type , chBRange , 0 )
58+ assert_pico_ok (status ["setChB" ])
59+
60+ # find maximum ADC count value
61+ # handle = chandle
62+ # pointer to value = ctypes.byref(maxADC)
63+ maxADC = ctypes .c_int16 ()
64+ status ["maximumValue" ] = ps .ps5000aMaximumValue (chandle , ctypes .byref (maxADC ))
65+ assert_pico_ok (status ["maximumValue" ])
66+
67+ # Set number of pre and post trigger samples to be collected
68+ preTriggerSamples = 2500
69+ postTriggerSamples = 2500
70+ maxSamples = preTriggerSamples + postTriggerSamples
71+
72+ # Get timebase information
73+ # Warning: When using this example it may not be possible to access all Timebases as all channels are enabled by default when opening the scope.
74+ # To access these Timebases, set any unused analogue channels to off.
75+ # handle = chandle
76+ timebase = 8
77+ # noSamples = maxSamples
78+ # pointer to timeIntervalNanoseconds = ctypes.byref(timeIntervalns)
79+ # pointer to maxSamples = ctypes.byref(returnedMaxSamples)
80+ # segment index = 0
81+
82+ timeIntervalns = ctypes .c_float ()
83+ returnedMaxSamples = ctypes .c_int32 ()
84+ status ["getTimebase2" ] = ps .ps5000aGetTimebase2 (chandle , timebase , maxSamples , ctypes .byref (timeIntervalns ), ctypes .byref (returnedMaxSamples ), 0 )
85+ assert_pico_ok (status ["getTimebase2" ])
86+
87+ # Set up an advanced trigger
88+ adcTriggerLevel = mV2adc (500 , chARange , maxADC )
89+
90+ triggerProperties = ps .PS5000A_TRIGGER_CHANNEL_PROPERTIES_V2 (adcTriggerLevel ,
91+ 10 ,
92+ 0 ,
93+ 10 ,
94+ ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_A" ])
95+
96+ status ["setTriggerChannelPropertiesV2" ] = ps .ps5000aSetTriggerChannelPropertiesV2 (chandle , ctypes .byref (triggerProperties ), 1 , 0 )
97+ assert_pico_ok (status ["setTriggerChannelPropertiesV2" ])
98+
99+ triggerConditions = (ps .PS5000A_CONDITION * 2 )()
100+ # triggerConditions[0] = ps.PS5000A_CONDITION(ps.PS5000A_CHANNEL["PS5000A_CHANNEL_A"],
101+ # ps.PS5000A_TRIGGER_STATE["PS5000A_CONDITION_TRUE"])
102+ triggerConditions = ps .PS5000A_CONDITION (ps .PS5000A_CHANNEL ["PS5000A_PULSE_WIDTH_SOURCE" ],
103+ ps .PS5000A_TRIGGER_STATE ["PS5000A_CONDITION_TRUE" ])
104+
105+ clear = 1
106+ add = 2
107+
108+ status ["setTriggerChannelConditionsV2" ] = ps .ps5000aSetTriggerChannelConditionsV2 (chandle , ctypes .byref (triggerConditions ), 1 , (clear | add ))
109+ assert_pico_ok (status ["setTriggerChannelConditionsV2" ])
110+
111+ triggerDirections = ps .PS5000A_DIRECTION (ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_A" ],
112+ ps .PS5000A_THRESHOLD_DIRECTION ["PS5000A_RISING" ],
113+ ps .PS5000A_THRESHOLD_MODE ["PS5000A_LEVEL" ])
114+
115+ status ["setTriggerChannelDirections" ] = ps .ps5000aSetTriggerChannelDirectionsV2 (chandle , ctypes .byref (triggerDirections ), 1 )
116+ assert_pico_ok (status ["setTriggerChannelDirections" ])
117+
118+ # pulse width setup
119+ # pulse width conditions
120+ PWQConditions = ps .PS5000A_CONDITION (ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_A" ], ps .PS5000A_TRIGGER_STATE ["PS5000A_CONDITION_TRUE" ])
121+
122+ status ["setPWQualifierConditions" ] = ps .ps5000aSetPulseWidthQualifierConditions (chandle , ctypes .byref (PWQConditions ), 1 , add )
123+ assert_pico_ok (status ["setPWQualifierConditions" ])
124+
125+
126+ #set pulse width counter
127+ timeWidthNs = 3000
128+ counterSamples = math .ceil (timeWidthNs / timeIntervalns .value )
129+
130+ # pulse width properties
131+ PWtype = 2 #ps.PS5000A_PULSE_WIDTH_TYPE["PS5000A_PW_TYPE_GREATER_THAN"]
132+ status ["setPWQualifierProperties" ] = ps .ps5000aSetPulseWidthQualifierProperties (chandle , counterSamples , counterSamples , PWtype )
133+ assert_pico_ok (status ["setPWQualifierProperties" ])
134+
135+ #pulse width directions
136+ PWQDirections = ps .PS5000A_DIRECTION (ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_A" ], ps .PS5000A_THRESHOLD_DIRECTION ["PS5000A_FALLING" ], ps .PS5000A_THRESHOLD_MODE ["PS5000A_LEVEL" ])
137+ status ["setPWQualifierDirections" ] = ps .ps5000aSetPulseWidthQualifierDirections (chandle , ctypes .byref (PWQDirections ), 1 )
138+ assert_pico_ok (status ["setPWQualifierDirections" ])
139+
140+ # Run block capture
141+ # handle = chandle
142+ # number of pre-trigger samples = preTriggerSamples
143+ # number of post-trigger samples = PostTriggerSamples
144+ # timebase = 8 = 80 ns (see Programmer's guide for mre information on timebases)
145+ # time indisposed ms = None (not needed in the example)
146+ # segment index = 0
147+ # lpReady = None (using ps5000aIsReady rather than ps5000aBlockReady)
148+ # pParameter = None
149+ status ["runBlock" ] = ps .ps5000aRunBlock (chandle , preTriggerSamples , postTriggerSamples , timebase , None , 0 , None , None )
150+ assert_pico_ok (status ["runBlock" ])
151+
152+ # Check for data collection to finish using ps5000aIsReady
153+ ready = ctypes .c_int16 (0 )
154+ check = ctypes .c_int16 (0 )
155+ while ready .value == check .value :
156+ status ["isReady" ] = ps .ps5000aIsReady (chandle , ctypes .byref (ready ))
157+
158+
159+ # Create buffers ready for assigning pointers for data collection
160+ bufferAMax = (ctypes .c_int16 * maxSamples )()
161+ bufferAMin = (ctypes .c_int16 * maxSamples )() # used for downsampling which isn't in the scope of this example
162+ bufferBMax = (ctypes .c_int16 * maxSamples )()
163+ bufferBMin = (ctypes .c_int16 * maxSamples )() # used for downsampling which isn't in the scope of this example
164+
165+ # Set data buffer location for data collection from channel A
166+ # handle = chandle
167+ source = ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_A" ]
168+ # pointer to buffer max = ctypes.byref(bufferAMax)
169+ # pointer to buffer min = ctypes.byref(bufferAMin)
170+ # buffer length = maxSamples
171+ # segment index = 0
172+ # ratio mode = PS5000A_RATIO_MODE_NONE = 0
173+ status ["setDataBuffersA" ] = ps .ps5000aSetDataBuffers (chandle , source , ctypes .byref (bufferAMax ), ctypes .byref (bufferAMin ), maxSamples , 0 , 0 )
174+ assert_pico_ok (status ["setDataBuffersA" ])
175+
176+ # Set data buffer location for data collection from channel B
177+ # handle = chandle
178+ source = ps .PS5000A_CHANNEL ["PS5000A_CHANNEL_B" ]
179+ # pointer to buffer max = ctypes.byref(bufferBMax)
180+ # pointer to buffer min = ctypes.byref(bufferBMin)
181+ # buffer length = maxSamples
182+ # segment index = 0
183+ # ratio mode = PS5000A_RATIO_MODE_NONE = 0
184+ status ["setDataBuffersB" ] = ps .ps5000aSetDataBuffers (chandle , source , ctypes .byref (bufferBMax ), ctypes .byref (bufferBMin ), maxSamples , 0 , 0 )
185+ assert_pico_ok (status ["setDataBuffersB" ])
186+
187+ # create overflow loaction
188+ overflow = ctypes .c_int16 ()
189+ # create converted type maxSamples
190+ cmaxSamples = ctypes .c_int32 (maxSamples )
191+
192+ # Retried data from scope to buffers assigned above
193+ # handle = chandle
194+ # start index = 0
195+ # pointer to number of samples = ctypes.byref(cmaxSamples)
196+ # downsample ratio = 0
197+ # downsample ratio mode = PS5000A_RATIO_MODE_NONE
198+ # pointer to overflow = ctypes.byref(overflow))
199+ status ["getValues" ] = ps .ps5000aGetValues (chandle , 0 , ctypes .byref (cmaxSamples ), 0 , 0 , 0 , ctypes .byref (overflow ))
200+ assert_pico_ok (status ["getValues" ])
201+
202+
203+ # convert ADC counts data to mV
204+ adc2mVChAMax = adc2mV (bufferAMax , chARange , maxADC )
205+ adc2mVChBMax = adc2mV (bufferBMax , chBRange , maxADC )
206+
207+ # Create time data
208+ time = np .linspace (0 , (cmaxSamples .value - 1 ) * timeIntervalns .value , cmaxSamples .value )
209+
210+ # plot data from channel A and B
211+ plt .plot (time , adc2mVChAMax [:])
212+ plt .plot (time , adc2mVChBMax [:])
213+ plt .xlabel ('Time (ns)' )
214+ plt .ylabel ('Voltage (mV)' )
215+ plt .show ()
216+
217+ # Stop the scope
218+ # handle = chandle
219+ status ["stop" ] = ps .ps5000aStop (chandle )
220+ assert_pico_ok (status ["stop" ])
221+
222+ # Close unit Disconnect the scope
223+ # handle = chandle
224+ status ["close" ]= ps .ps5000aCloseUnit (chandle )
225+ assert_pico_ok (status ["close" ])
226+
227+ # display status returns
228+ print (status )
0 commit comments