Skip to content

Commit 2a8bdd7

Browse files
authored
Merge pull request #173 from bmoneke/fix-timebase-4000a
Fix timebase and open with serial number, add pingUnit to ps4000a
2 parents 62cb0bd + 5ce4050 commit 2a8bdd7

File tree

1 file changed

+63
-27
lines changed

1 file changed

+63
-27
lines changed

picoscope/ps4000a.py

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ class PS4000a(_PicoscopeBase):
117117
"milliseconds": 4,
118118
"seconds": 5}
119119

120+
SIGGEN_TRIGGER_TYPES = {"Rising": 0, "Falling": 1,
121+
"GateHigh": 2, "GateLow": 3}
122+
123+
SIGGEN_TRIGGER_SOURCES = {"None": 0, "ScopeTrig": 1,
124+
"AuxIn": 2, "ExtIn": 3, "SoftTrig": 4}
125+
120126
def __init__(self, serialNumber=None, connect=True):
121127
"""Load DLLs."""
122128
self.handle = None
@@ -140,14 +146,15 @@ def __init__(self, serialNumber=None, connect=True):
140146

141147
super(PS4000a, self).__init__(serialNumber, connect)
142148

143-
def _lowLevelOpenUnit(self, sn):
149+
def _lowLevelOpenUnit(self, serialNumber):
144150
c_handle = c_int16()
145-
if sn is not None:
146-
serialNullTermStr = create_string_buffer(str(sn))
151+
if serialNumber is not None:
152+
serialNumberStr = create_string_buffer(bytes(serialNumber,
153+
encoding='utf-8'))
147154
else:
148-
serialNullTermStr = None
155+
serialNumberStr = None
149156
# Passing None is the same as passing NULL
150-
m = self.lib.ps4000aOpenUnit(byref(c_handle), serialNullTermStr)
157+
m = self.lib.ps4000aOpenUnit(byref(c_handle), serialNumberStr)
151158
self.handle = c_handle.value
152159

153160
# This will check if the power supply is not connected
@@ -163,17 +170,18 @@ def _lowLevelOpenUnit(self, sn):
163170

164171
self.model = self.getUnitInfo('VariantInfo')
165172

166-
def _lowLevelOpenUnitAsync(self, sn):
173+
def _lowLevelOpenUnitAsync(self, serialNumber):
167174
c_status = c_int16()
168-
if sn is not None:
169-
serialNullTermStr = create_string_buffer(sn)
175+
if serialNumber is not None:
176+
serialNumberStr = create_string_buffer(bytes(serialNumber,
177+
encoding='utf-8'))
170178
else:
171-
serialNullTermStr = None
172-
179+
serialNumberStr = None
173180
# Passing None is the same as passing NULL
174-
m = self.lib.ps4000aOpenUnitAsync(byref(c_status), serialNullTermStr)
181+
m = self.lib.ps4000aOpenUnitAsync(byref(c_status), serialNumberStr)
175182
self.checkResult(m)
176183

184+
# Set the model after completion in _lowLevelOpenUnitProgress.
177185
return c_status.value
178186

179187
def _lowLevelOpenUnitProgress(self):
@@ -188,6 +196,7 @@ def _lowLevelOpenUnitProgress(self):
188196

189197
if complete.value != 0:
190198
self.handle = handle.value
199+
self.model = self.getUnitInfo('VariantInfo')
191200

192201
# if we only wanted to return one value, we could do somethign like
193202
# progressPercent = progressPercent * (1 - 0.1 * complete)
@@ -291,27 +300,51 @@ def _lowLevelIsReady(self):
291300
else:
292301
return False
293302

294-
def _lowLevelGetTimebase(self, tb, noSamples, oversample, segmentIndex):
295-
"""Return (timeIntervalSeconds, maxSamples)."""
303+
def _lowLevelGetTimebase(self, timebase, noSamples, oversample,
304+
segmentIndex):
305+
"""
306+
Calculate the sampling interval and maximum number of samples.
307+
308+
timebase
309+
Number of the selected timebase.
310+
noSamples
311+
Number of required samples.
312+
oversample
313+
Nnot used.
314+
segmentIndex
315+
Index of the segment to save samples in
316+
317+
Return
318+
-------
319+
timeIntervalSeconds : float
320+
Time interval between two samples in s.
321+
maxSamples : int
322+
maximum number of samples available depending on channels
323+
and timebase chosen.
324+
"""
296325
maxSamples = c_int32()
297-
sampleRate = c_float()
326+
timeIntervalSeconds = c_float()
298327

299-
m = self.lib.ps4000aGetTimebase2(c_int16(self.handle), c_uint32(tb),
300-
c_int32(noSamples), byref(sampleRate),
328+
m = self.lib.ps4000aGetTimebase2(c_int16(self.handle),
329+
c_uint32(timebase),
330+
c_int32(noSamples),
331+
byref(timeIntervalSeconds),
301332
byref(maxSamples),
302333
c_uint32(segmentIndex))
303334
self.checkResult(m)
304335

305-
return (sampleRate.value / 1.0E9, maxSamples.value)
336+
return (timeIntervalSeconds.value / 1.0E9, maxSamples.value)
306337

307338
def getTimeBaseNum(self, sampleTimeS):
308-
""" Convert the sample interval (float of seconds) to the
309-
corresponding integer timebase value as defined by the API.
310-
See "Timebases" section of the PS4000a programmers guide
339+
"""
340+
Convert `sampleTimeS` in s to the integer timebase number.
341+
342+
See "Timebases" section of the PS4000a programmer's guide
311343
for more information.
312344
"""
313345

314346
if self.model == '4828':
347+
# TODO does a model 4828 exist?
315348
maxSampleTime = (((2 ** 32 - 1) + 1) / 8E7)
316349

317350
if sampleTimeS <= 12.5E-9:
@@ -339,6 +372,14 @@ def getTimeBaseNum(self, sampleTimeS):
339372

340373
timebase = math.floor((sampleTimeS * 5.0E7) + 2)
341374

375+
elif self.model.startswith('4824'):
376+
maxSampleTime = (((2 ** 32 - 1) + 1) / 8E7)
377+
378+
if sampleTimeS > maxSampleTime:
379+
sampleTimeS = maxSampleTime
380+
timebase = math.floor(sampleTimeS * 8e7 - 1)
381+
timebase = max(0, timebase)
382+
342383
else: # The original case from non "A" series
343384
warnings.warn("The model PS4000a you are using may not be "
344385
"fully supported", stacklevel=2)
@@ -354,13 +395,11 @@ def getTimeBaseNum(self, sampleTimeS):
354395

355396
timebase = math.floor((sampleTimeS * 2e7) + 1)
356397

357-
# is this cast needed?
358-
timebase = int(timebase)
359398
return timebase
360399

361400
def getTimestepFromTimebase(self, timebase):
362-
"""Return timebase to sampletime as seconds."""
363-
if self.model == '4828':
401+
"""Convert `timebase` index to sampletime in seconds."""
402+
if self.model == '4828' or self.model.startswith('4824'):
364403
dt = (timebase + 1) / 8.0E7
365404
elif self.model == '4444':
366405
if timebase < 3:
@@ -385,9 +424,6 @@ def _lowLevelSetDataBuffer(self, channel, data, downSampleMode,
385424
Be sure to call _lowLevelClearDataBuffer
386425
when you are done with the data array
387426
or else subsequent calls to GetValue will still use the same array.
388-
389-
segmentIndex is unused, but required by other versions of the API
390-
(eg PS5000a)
391427
"""
392428
dataPtr = data.ctypes.data_as(POINTER(c_int16))
393429
numSamples = len(data)

0 commit comments

Comments
 (0)