PicoScope 7 Software
Available on Windows, Mac and Linux
Code: Select all
#!/usr/bin/env python
'''picoscope ps2000 library interface'''
import sys
import time
from functools import partial
from ctypes import * # shouldn't import *, but there are so many items to use...
LIBNAME = 'ps2000.dll'
# channel range values/codes
RANGE_20MV = 1 # 20 mV
RANGE_50MV = 2 # 50 mV
RANGE_100MV = 3 # 100 mV
RANGE_200MV = 4 # 200 mV
RANGE_500MV = 5 # 500 mV
RANGE_1V = 6 # 1 V
RANGE_2V = 7 # 2 V
RANGE_5V = 8 # 5 V
RANGE_10V = 9 # 10 V
RANGE_20V = 10 # 20 V
# probe tip lights
LIGHT_OFF = 0
LIGHT_ON = 1
LIGHT_STATES = [LIGHT_ON, LIGHT_OFF]
# LED states
LED_RED = 1
LED_GREEN = 2
LED_OFF = 3
LED_STATES = [LED_RED, LED_GREEN, LED_OFF]
# channels
CHANNEL_A = 0
CHANNEL_B = 1
CHANNEL_NONE = 5
CHANNELS = [CHANNEL_A, CHANNEL_B, CHANNEL_NONE]
# coupling
COUPLING_DC = 1
COUPLING_AC = 0
COUPLINGS = [COUPLING_DC, COUPLING_AC]
# trigger direction
DIR_FALLING = 1
DIR_RISING = 0
DIRECTIONS = [DIR_RISING, DIR_FALLING]
class PicoError(Exception):
'''pico scope error'''
# TODO: add checks in methods to ensure lib, handle are valid
class PicoWrapper(object):
'''picoscope ps2000 interface'''
def __init__(self):
self.handle = None
# load the library
self.lib = windll.LoadLibrary(LIBNAME)
if not self.lib:
raise PicoError('could not open library: %s' % LIBNAME)
################## low level methods #####################
def __getattr__(self, name):
'''this method will call methods starting with ps2000_ via the library'''
# get a handle to the requested method if name looks like a PS2000 method
if name.lower().startswith('ps2000_'):
try:
func = getattr(self.lib, name)
except AttributeError:
raise PicoError('Library "%s" does not support method "%s"' % (LIBNAME, func_name))
else:
# return a partial function of the library method with handle passed in
return partial(func, self.handle)
# not a ps2000 request, defer
else:
raise AttributeError
def ps2000_close_unit(self):
'''low-level close the interface to the unit'''
res = self.lib.ps2000_close_unit(self.handle)
self.handle = None
return res
def ps2000_open_unit(self):
'''low-level open interface to unit'''
self.handle = self.lib.ps2000_open_unit()
return self.handle
################## higher level methods #####################
def close_unit(self):
'''close the unit'''
res = self.ps2000_close_unit()
if res == 0:
raise PicoError('flash_led: invalid handle')
def flash_led(self):
'''flash led on front of unit'''
res = self.ps2000_flash_led()
if res == 0:
raise PicoError('flash_led: invalid handle')
#ps2000_get_streaming_last_values
#ps2000_get_streaming_values
#ps2000_get_streaming_values_no_aggregation
def get_timebase(self, timebase, num_samples, oversample):
'''return the (time_interval, time_units, max_samples) for the given parameters'''
time_interval = c_long()
time_units = c_short()
max_samples = c_long()
res = self.ps2000_get_timebase(timebase, num_samples, byref(time_interval),
byref(time_units), oversample, byref(max_samples))
if res == 0:
raise PicoError('get_timebase: parameter out of range')
else:
return time_interval.value, time_units.value, max_samples.value
def get_times_and_values(self, time_units, num_points):
'''return requested amount of data (times, chA, chB, overflowA, overflowB)'''
times = (c_long * num_points)()
ch_a_data = (c_long * num_points)()
ch_b_data = (c_long * num_points)()
overflow = c_short()
res = self.ps2000_get_times_and_values(byref(times), byref(ch_a_data), byref(ch_b_data),
None, None, byref(overflow), time_units, num_points)
if res == 0:
raise PicoError('get_times_and_values: failed!')
else:
return tuple(times), tuple(ch_a_data), tuple(ch_b_data)
#ps2000_get_unit_info
def get_values(self, num_points):
'''return requested amount of data (chA, chB, overflowA, overflowB)'''
ch_a_data = (c_long * num_points)()
ch_b_data = (c_long * num_points)()
overflow = c_short()
res = self.ps2000_get_values(byref(ch_a_data), byref(ch_b_data),
None, None, byref(overflow), num_points)
if res == 0:
raise PicoError('get_values: failed!')
else:
return tuple(ch_a_data), tuple(ch_b_data)
#ps2000_last_button_press
def open_unit(self):
'''open interface to unit'''
res = self.ps2000_open_unit()
if res < 0:
raise PicoError('open: failed to open scope')
elif res == 0:
raise PicoError('open: could not find picoscope unit')
#ps2000_open_unit_async
#ps2000_open_unit_progress
#ps2000_overview_buffer_status
def ready(self):
'''indicate if previous block acquire is complete - returns bool'''
res = self.ps2000_ready()
if res < 1:
raise PicoError('ready: oscilloscope not attached')
else:
return bool(res)
def run_block(self, num_samples, timebase, oversample):
'''start acquisition of block of data; return expected duration of acquisition in mS'''
time_indisposed_ms = c_long()
res = self.ps2000_run_block(num_samples, timebase, oversample, byref(time_indisposed_ms))
if res == 0:
raise PicoError('run_block: parameter out of range')
else:
return time_indisposed_ms.value
#ps2000_run_streaming
#ps2000_run_streaming_ns
#ps2000SetAdvTriggerChannelConditions
#ps2000SetAdvTriggerChannelDirections
#ps2000SetAdvTriggerChannelProperties
#ps2000SetAdvTriggerDelay
def set_channel(self, channel, enabled, coupling, range):
'''select channel and modes'''
res = self.ps2000_set_channel(channel, enabled, coupling, range)
if res == 0:
raise PicoError('set_channel: failed')
#ps2000_set_ets
def set_led(self, state):
'''set colour/state of led on scope'''
if state not in LED_STATES:
raise PicoError('set_led: unknown led state: %s' % state)
res = self.ps2000_set_led(state)
if res == 0:
raise PicoError('set_led: failed')
def set_light(self, state):
'''enable/disable light on probe tip'''
if state not in LIGHT_STATES:
raise PicoError('set_light: unknown light state: %s' % state)
res = self.ps2000_set_light(state)
if res == 0:
raise PicoError('set_light: failed')
#ps2000SetPulseWidthQualifier
#ps2000SetSigGenArbitrary
#ps2000SetSigGenBuiltIn
def set_trigger(self, source, threshold, direction, delay, auto_trigger_ms):
'''set the trigger mode'''
res = self.ps2000_set_trigger(source, threshold, direction, delay, auto_trigger_ms)
if res == 0:
raise PicoError('set_trigger: failed')
#ps2000_set_trigger2
def stop(self):
'''stop scope acquisition'''
res = self.ps2000_stop()
if res == 0:
raise PicoError('stop: failed')
class PS2000(PicoWrapper):
'''PS2000 class utilizing the PicoWrapper with higher level functionality'''
def __init__(self):
PicoWrapper.__init__(self)
self.interval = None
self.units = None
self.timebase = None
self.oversample = None
def set_timebase(self, max_interval_ps, min_samples, oversample):
'''set the timebase specifying...; return actual sample interval'''
for i in range(256): # ??
try:
interval, units, samples = self.get_timebase(i, min_samples, oversample)
except PicoError:
pass
else:
# once the sample interval is more than we want, we move back one
if interval > max_interval_ps:
self.timebase = i-1
self.oversample = oversample
self.sample_interval, self.units, samples = self.get_timebase(self.timebase, min_samples, oversample)
print 'selected', self.sample_interval, self.units
return self.sample_interval
def get_data(self, num_samples):
'''blocking call to wait for data'''
while not self.ready():
pass # TODO: sleep
return self.get_values(num_samples)
def get_timed_data(self, num_samples):
'''blocking call to wait for data'''
while not self.ready():
pass # TODO: sleep
return self.get_times_and_values(self.units, num_samples)
def acquire_block(self, num_samples):
'''acquisition of num_samples at current sample_interval'''
self.run_block(num_samples, self.timebase, 0)
returnself.get_data()
def start_block(self, num_samples):
'''start run_block with current data setup'''
self.run_block(num_samples, self.timebase, self.oversample)
################################################################################
if __name__ == '__main__':
# example code
print 'creating'
scope = PS2000()
print 'open'
print scope.open_unit()
print 'set channel'
print scope.set_channel(CHANNEL_A, True, COUPLING_DC, RANGE_5V)
print scope.set_channel(CHANNEL_B, True, COUPLING_DC, RANGE_5V)
print 'set trigger'
print scope.set_trigger(CHANNEL_NONE, 0, DIR_RISING, 0, 10)
#print scope.set_trigger(CHANNEL_A, 0x1000, DIR_RISING, -5, 100) # TODO: fix threshold
print 'set timebase'
print scope.set_timebase(1000000, 1000, 0)
print 'start_block'
print scope.start_block(1000)
print 'get_data'
print scope.get_data(1000)
print 'done'
from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed()
ipshell()
Code: Select all
open
info
DRIVER_VERSION: 3.6.2.0 Linux
USB_VERSION: 2.0
HARDWARE_VERSION: 16
VARIANT_INFO: 2205
BATCH_AND_SERIAL: AU075/222
CAL_DATE: 15Apr10
ERROR_CODE: 0
Traceback (most recent call last):
File "./picoscope.py", line 485, in
scope.set_timebase(80000000)
File "./picoscope.py", line 127, in __getattr__
raise AttributeError
AttributeError
Code: Select all
open
info
DRIVER_VERSION: 3.6.2.0 Linux
USB_VERSION: 2.0
HARDWARE_VERSION: 16
VARIANT_INFO: 2205
BATCH_AND_SERIAL: AU075/222
CAL_DATE: 15Apr10
ERROR_CODE: 0
Traceback (most recent call last):
File "./picoscope.py", line 480, in
chlA, chlB = scope.get_data(scaleB=10) # 10x divider on probe
File "./picoscope.py", line 387, in get_data
a, b = self.get_values(PS_MAX_SAMPLES)
File "./picoscope.py", line 215, in get_values
raise PicoError('get_values: failed!')
__main__.PicoError: get_values: failed!
Code: Select all
import sys, time
from ctypes import *
from socket import *
from functools import partial
from array import array
LIBNAME = 'ps2000.dll'
PS2000_SINE = 0
PS2000_UPDOWN = 2
class PicoError(Exception):
'''pico scope error'''
# TODO: add checks in methods to ensure lib, handle are valid
class PicoWrapper(object):
'''picoscope ps2000 interface'''
def __init__(self):
self.handle = None
# load the library
if sys.platform == 'win32':
self.lib = windll.LoadLibrary(LIBNAME)
else:
self.lib = cdll.LoadLibrary(LIBNAME)
if not self.lib:
raise PicoError('could not open library: %s' % LIBNAME)
def __getattr__(self, name):
'''this method will call methods starting with ps2000_ via the library'''
# get a handle to the requested method if name looks like a PS2000 method
if name.lower().startswith('ps2000_'):
try:
func = getattr(self.lib, name)
except AttributeError:
raise PicoError('Library "%s" does not support method "%s"' % (LIBNAME, func_name))
else:
# return a partial function of the library method with handle passed in
return partial(func, self.handle)
# not a ps2000 request, defer
else:
raise AttributeError
if __name__ == '__main__':
scoop = PicoWrapper() #Open scope
scoop.handle = scoop.lib.ps2000_open_unit()
print('Handle', scoop.handle)
res = scoop.ps2000_set_sig_gen_built_in(
c_long(0), #Voffset
c_ulong(1900), #pk-pk voltage in mV
PS2000_SINE, #PS2000_WAVE_TYPE; sine
c_float(1000), #Start frequency
c_float(9000), #Stop frequency
c_float(9.0), #Increment
c_float(2.0), #Dwell time (sec)
PS2000_UPDOWN, #PS2000_SWEEP_TYPE
c_ulong(9)) #Sweeps
if res != 0:
print('Set sig gen faalt', res)
res = scoop.ps2000_set_trigger(0, #Source; channel A
100, #Threshold
1, #Direction
0, #Delay; start at trigger
100) #Auto trigger ms
if res != 1:
print('Set trigger faalt', res)
timeBase = 2
numSamples = 2**4
timeInterval = c_long(0)
timeUnits = c_short(0)
oversample = 16
maxSamples = c_long()
res = scoop.ps2000_get_timebase(
timeBase, #Timebase
numSamples, #No of samples
byref(timeInterval),#Time interval
byref(timeUnits), #Time units
oversample, #Oversample
byref(maxSamples), #Max samples
)
if res != 1:
print('Get timebase faalt', res)
numSamples = maxSamples.value
print('numSamples', numSamples)
timeIndisposed = c_long(0)
res = scoop.ps2000_run_block(maxSamples, timeBase, oversample, byref(timeIndisposed))
if res != 1:
raise Exception
while not 1==scoop.ps2000_ready():
time.sleep(1)
print('Scoop niet klaar')
bufferA = (c_short * numSamples)()
bufferB = (c_short * numSamples)()
bufferC = (c_short * numSamples)()
bufferD = (c_short * numSamples)()
overflow = c_short(0)
res = scoop.ps2000_get_values(
byref(bufferA),
byref(bufferB),
byref(bufferC),
byref(bufferD),
byref(overflow),
numSamples)
if res == 0:
print('Get values faalt', res)
for i in bufferA:
print(i, end='\t')
print('\nOverflow: ', overflow.value)
time.sleep(10) #wait some time in case signal generator is actually doing something
scoop.ps2000_stop()
Can anyone see why the signal generator doesn't do anything? Thanks.Variabele 0 in get unit info: 2.0.8.163
Variabele 1 in get unit info: 2.0
Variabele 2 in get unit info: 16
Variabele 3 in get unit info: 2205
Variabele 4 in get unit info: AP845/519
Variabele 5 in get unit info: 04Sep12
Variabele 6 in get unit info: 0