1+ #
2+ # Copyright (C) 2020-2024 Pico Technology Ltd. See LICENSE file for terms.
3+ #
4+ # PS6000 A MSO BLOCK MODE DIGITAL TRIGGER EXAMPLE
5+ # This example opens a 6000a driver device, sets up one analogue channel and one digital channel and a digital 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 .ps6000a import ps6000a as ps
11+ from picosdk .PicoDeviceEnums import picoEnum as enums
12+ import matplotlib .pyplot as plt
13+ from picosdk .functions import adc2mV , assert_pico_ok , splitMSODataFast
14+
15+ # Create chandle and status ready for use
16+ chandle = ctypes .c_int16 ()
17+ status = {}
18+
19+ # Open 6000 A series PicoScope
20+ # returns handle to chandle for use in future API functions
21+ resolution = enums .PICO_DEVICE_RESOLUTION ["PICO_DR_8BIT" ]
22+ status ["openunit" ] = ps .ps6000aOpenUnit (ctypes .byref (chandle ), None , resolution )
23+ assert_pico_ok (status ["openunit" ])
24+
25+ # Set channel A on
26+ # handle = chandle
27+ channelA = enums .PICO_CHANNEL ["PICO_CHANNEL_A" ]
28+ coupling = enums .PICO_COUPLING ["PICO_DC_50OHM" ]
29+ channelRange = 5
30+ # analogueOffset = 0 V
31+ bandwidth = enums .PICO_BANDWIDTH_LIMITER ["PICO_BW_FULL" ]
32+ status ["setChannelA" ] = ps .ps6000aSetChannelOn (chandle , channelA , coupling , channelRange , 0 , bandwidth )
33+ assert_pico_ok (status ["setChannelA" ])
34+
35+ # set channel B-H off
36+ for x in range (1 , 7 , 1 ):
37+ channel = x
38+ status ["setChannel" ,x ] = ps .ps6000aSetChannelOff (chandle ,channel )
39+ assert_pico_ok (status ["setChannel" ,x ])
40+
41+ # set MSO pod 1 on
42+ # handle = chandle
43+ port = enums .PICO_CHANNEL ["PICO_PORT0" ]
44+ # logic level needs to be set individually for all digital channels/pins in the port
45+ pins = 8
46+ logicThresholdLevel = (ctypes .c_int16 * pins )(0 )
47+ logicThresholdLevel [0 ] = 1000
48+ logicThresholdLevelLength = len (logicThresholdLevel )
49+ hysteresis = enums .PICO_DIGITAL_PORT_HYSTERESIS ["PICO_LOW_50MV" ]
50+ status ["setDigitalPortOn" ] = ps .ps6000aSetDigitalPortOn (chandle , port , ctypes .byref (logicThresholdLevel ), logicThresholdLevelLength , hysteresis )
51+ assert_pico_ok (status ["setDigitalPortOn" ])
52+
53+ # Set MSO pod 2 off
54+ port2 = enums .PICO_CHANNEL ["PICO_PORT1" ]
55+ status ["setDigitalPortOff" ] = ps .ps6000aSetDigitalPortOff (chandle ,port2 )
56+ assert_pico_ok (status ["setDigitalPortOff" ])
57+
58+ # get max ADC value
59+ # handle = chandle
60+ minADC = ctypes .c_int16 ()
61+ maxADC = ctypes .c_int16 ()
62+ status ["getAdcLimits" ] = ps .ps6000aGetAdcLimits (chandle , resolution , ctypes .byref (minADC ), ctypes .byref (maxADC ))
63+ assert_pico_ok (status ["getAdcLimits" ])
64+
65+ # Set trigger on digital channel 0 Port 1 for rising logic level transition
66+ conditions = (struct .PICO_CONDITION * 1 )()
67+ conditions = struct .PICO_CONDITION (enums .PICO_CHANNEL .PICO_PORT0 , enums .PICO_TRIGGER_STATE ["PICO_CONDITION_TRUE" ])
68+ nConditions = 1
69+ clear = enums .PICO_ACTION ["PICO_CLEAR_ALL" ]
70+ add = enums .PICO_ACTION ["PICO_ADD" ]
71+ action = clear | add
72+ status ["setTriggerChannelConditions" ] = ps .ps6000aSetTriggerChannelConditions (chandle , ctypes .byref (conditions ),nConditions ,action )
73+ assert_pico_ok (status ["setTriggerChannelConditions" ])
74+
75+ directions = (struct .PICO_DIGITAL_CHANNEL_DIRECTIONS * 1 )()
76+ directions = stuct .PICO_DIGITAL_CHANNEL_DIRECTIONS (enums .PICO_PORT_DIGITAL_CHANNEL .PICO_PORT_DIGITAL_CHANNEL0 ,enums .PICO_DIGITAL_DIRECTION .PICO_DIGITAL_DIRECTION_RISING )
77+ nDirections = 1
78+ status ["setTriggerDigitalPortProperties" ] = ps .ps6000a .SetTriggerDigitalPortProperties (chandle ,port ,ctypes .byref (directions ),nDirections )
79+ assert_pico_ok (status ["setTriggerDigitalPortProperties" ])
80+
81+
82+ # Set number of samples to be collected
83+ noOfPreTriggerSamples = 500000
84+ noOfPostTriggerSamples = 1000000
85+ nSamples = noOfPostTriggerSamples + noOfPreTriggerSamples
86+
87+ # Check timebase is valid
88+ # handle = chandle
89+ timebase = ctypes .c_uint32 (1 )
90+ timeInterval = ctypes .c_double (0 )
91+ returnedMaxSamples = ctypes .c_uint64 ()
92+ #segment = 0
93+ status ["getTimebase" ] = ps .ps6000aGetTimebase (chandle , timebase , nSamples , ctypes .byref (timeInterval ), ctypes .byref (returnedMaxSamples ), 0 )
94+ assert_pico_ok (status ["getTimebase" ])
95+ print ("timebase = " , timebase .value )
96+ print ("sample interval =" , timeInterval .value , "ns" )
97+
98+ # Create buffers
99+ bufferAMax = (ctypes .c_int16 * nSamples )()
100+ bufferAMin = (ctypes .c_int16 * nSamples )() # used for downsampling which isn't in the scope of this example
101+
102+ bufferDPort0Max = (ctypes .c_int16 * nSamples )()
103+ bufferDPort0Min = (ctypes .c_int16 * nSamples )()
104+
105+ # Set data buffers
106+ # handle = chandle
107+ # channel = channelA
108+ # bufferMax = bufferAMax
109+ # bufferMin = bufferAMin
110+ # nSamples = nSamples
111+ dataType = enums .PICO_DATA_TYPE ["PICO_INT16_T" ]
112+ waveform = 0
113+ downSampleMode = enums .PICO_RATIO_MODE ["PICO_RATIO_MODE_RAW" ]
114+ clear = enums .PICO_ACTION ["PICO_CLEAR_ALL" ]
115+ add = enums .PICO_ACTION ["PICO_ADD" ]
116+ action = clear | add # PICO_ACTION["PICO_CLEAR_WAVEFORM_CLEAR_ALL"] | PICO_ACTION["PICO_ADD"]
117+ status ["setDataChABuffers" ] = ps .ps6000aSetDataBuffers (chandle , channelA , ctypes .byref (bufferAMax ), ctypes .byref (bufferAMin ), nSamples , dataType , waveform , downSampleMode , action )
118+ assert_pico_ok (status ["setDataChABuffers" ])
119+
120+ status ["setDataDP0Buffers" ] = ps .ps6000aSetDataBuffers (chandle , port , ctypes .byref (bufferDPort0Max ), ctypes .byref (bufferDPort0Min ), nSamples , dataType , waveform , downSampleMode , action )
121+ assert_pico_ok (status ["setDataDP0Buffers" ])
122+
123+ # Run block capture
124+ # handle = chandle
125+ # timebase = timebase
126+ timeIndisposedMs = ctypes .c_double (0 )
127+ # segmentIndex = 0
128+ # lpReady = None Using IsReady rather than a callback
129+ # pParameter = None
130+ status ["runBlock" ] = ps .ps6000aRunBlock (chandle , noOfPreTriggerSamples , noOfPostTriggerSamples , timebase , ctypes .byref (timeIndisposedMs ), 0 , None , None )
131+ assert_pico_ok (status ["runBlock" ])
132+
133+ # Check for data collection to finish using ps5000aIsReady
134+ ready = ctypes .c_int16 (0 )
135+ check = ctypes .c_int16 (0 )
136+ while ready .value == check .value :
137+ status ["isReady" ] = ps .ps6000aIsReady (chandle , ctypes .byref (ready ))
138+
139+ # Get data from scope
140+ # handle = chandle
141+ # startIndex = 0
142+ noOfSamples = ctypes .c_uint64 (nSamples )
143+ # downSampleRatio = 1
144+ # segmentIndex = 0
145+ overflow = ctypes .c_int16 (0 )
146+ status ["getValues" ] = ps .ps6000aGetValues (chandle , 0 , ctypes .byref (noOfSamples ), 1 , downSampleMode , 0 , ctypes .byref (overflow ))
147+ assert_pico_ok (status ["getValues" ])
148+
149+
150+
151+ # convert ADC counts data to mV
152+ adc2mVChAMax = adc2mV (bufferAMax , channelRange , maxADC )
153+
154+ # Obtain binary for Digital Port 0
155+ # The tuple returned contains the channels in order (D7, D6, D5, ... D0).
156+ bufferDPort0 = splitMSODataFast (noOfSamples , bufferDPort0Max )
157+
158+ # Create time data
159+ time = np .linspace (0 , (nSamples - 1 ) * timeInterval .value * 1000000000 , nSamples )
160+
161+ # plot data from channel A and B
162+ plt .figure (num = 'Channel A Data' )
163+ plt .plot (time , adc2mVChAMax [:])
164+ plt .xlabel ('Time (ns)' )
165+ plt .ylabel ('Voltage (mV)' )
166+ plt .title ('Channel A data' )
167+ #plt.show()
168+
169+ # Plot the data from digital channels onto a graph
170+ plt .figure (num = 'Digital Port 0 Data' )
171+ plt .title ('Plot of Digital Port 0 digital channels vs. time' )
172+ plt .plot (time , bufferDPort0 [0 ], label = 'D7' ) # D7 is the first array in the tuple.
173+ plt .plot (time , bufferDPort0 [1 ], label = 'D6' )
174+ plt .plot (time , bufferDPort0 [2 ], label = 'D5' )
175+ plt .plot (time , bufferDPort0 [3 ], label = 'D4' )
176+ plt .plot (time , bufferDPort0 [4 ], label = 'D3' )
177+ plt .plot (time , bufferDPort0 [5 ], label = 'D2' )
178+ plt .plot (time , bufferDPort0 [6 ], label = 'D1' )
179+ plt .plot (time , bufferDPort0 [7 ], label = 'D0' ) # D0 is the last array in the tuple.
180+ plt .xlabel ('Time (ns)' )
181+ plt .ylabel ('Logic Level' )
182+ plt .legend (loc = "upper right" )
183+ plt .show ()
184+
185+ # Close the scope
186+ status ["closeunit" ] = ps .ps6000aCloseUnit (chandle )
187+ assert_pico_ok (status ["closeunit" ])
188+
189+ print (status )
0 commit comments