Skip to content

Commit 1aaab0a

Browse files
authored
Merge pull request #181 from bmoneke/ps6000a
Adding Ps6000a Series
2 parents 144eca2 + 22a4406 commit 1aaab0a

File tree

7 files changed

+1354
-9
lines changed

7 files changed

+1354
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ around, but this one tries to improve on them via:
1010
* Supports both Windows and Linux and Mac
1111

1212
System has support for:
13+
* PS6000A Class (Picoscope 6xxxE)
1314
* PS6000
1415
* PS5000A Class (PicoScope 5242A/5243A/5244A/5442A/5443A/5444A/5242B/5244B/5442B/5443B/5444B)
1516
* PS4000A Class (PicoScope 4444/4824)

examples/freqmeasure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def freq_from_crossings(self, sig):
5050

5151
def measure(self):
5252
print("Waiting for trigger")
53-
while(self.ps.isReady() is False):
53+
while not self.ps.isReady():
5454
time.sleep(0.01)
5555
print("Sampling Done")
5656
data = self.ps.getDataV("A", 50000)

examples/specgram_plot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def examplePS6000():
4141

4242
for i in range(0, 50):
4343
ps.runBlock()
44-
while(ps.isReady() is False):
44+
while not ps.isReady():
4545
time.sleep(0.01)
4646

4747
print("Sampling Done")

examples/test_ps6000a.py

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Testing the ps6000a series software-device interaction.
4+
======================================================
5+
6+
This file provides tests in order to verify that the software does with the
7+
oscilloscope, what it is supposed to do. Additionally the tests serve as
8+
examples on how to do certain tasks.
9+
10+
Usage
11+
-----
12+
13+
- Run this file in order to execute all software tests on your device.
14+
- Import this file and execute the tests you want with your already opened
15+
oscilloscope device.
16+
17+
Created on Tue Jan 25 12:20:14 2022 by Benedikt Moneke
18+
"""
19+
20+
# Imports
21+
import matplotlib.pyplot as plt
22+
import numpy as np
23+
from picoscope import ps6000a
24+
import time
25+
26+
27+
def test_general_unit_calls(ps):
28+
"""Test general unit calls"""
29+
ps.flashLed()
30+
print(ps.getAllUnitInfo())
31+
assert not ps.ping(), "Ping failed."
32+
print("General unit calls test passed.")
33+
34+
35+
def test_timebase(ps):
36+
"""Test the timebase methods."""
37+
# Preparation
38+
ps.memorySegments(1)
39+
# Tests
40+
data = ((200e-12, 0),
41+
(800e-12, 2),
42+
(3.2e-9, 4),
43+
(6.4e-9, 5),
44+
(10e-9, 5),
45+
(15e-9, 6))
46+
for (t, timebase) in data:
47+
text = "Time {} does not give timebase {}".format(t, timebase)
48+
assert ps.getTimeBaseNum(t) == timebase, text
49+
data = (
50+
(800e-12, 2),
51+
(3.2e-9, 4),
52+
(6.4e-9, 5),
53+
(12.8e-9, 6),
54+
(19.2e-9, 7),
55+
(3.84e-8, 10),
56+
(6.144e-7, 100),
57+
)
58+
for (t, timebase) in data:
59+
text = "{} s does not fit timebase {}.".format(t, timebase)
60+
assert ps.getTimestepFromTimebase(timebase) == t, "Timestep: " + text
61+
try:
62+
timestep, _ = ps._lowLevelGetTimebase(timebase, 10, None, 0)
63+
except Exception:
64+
print(
65+
"getTimebase failed at time {}, timebase {}.".format(t,
66+
timebase))
67+
raise
68+
assert timestep == t, "LowLevel: {} != {}".format(timestep, t)
69+
print("Timebase test passed.")
70+
71+
72+
def test_deviceResolution(ps):
73+
"""Test setting/getting device resolution, including ADC limits."""
74+
ps.setResolution("12")
75+
assert ps.resolution == 1, "Picoscope variable was not set."
76+
assert ps.getResolution() == "12", "Picoscope resolution is wrong."
77+
assert ps.MIN_VALUE == -32736, "Minimum adc value is wrong."
78+
assert ps.MAX_VALUE == 32736, "Maximum adc value is wrong."
79+
print("Device resolution test passed.")
80+
81+
82+
def test_rapid_block_mode(ps,
83+
n_captures=100,
84+
sample_interval=100e-9, # 100 ns
85+
sample_duration=2e-3, # 1 ms
86+
):
87+
"""Test the rapid block mode."""
88+
# Configuration of Picoscope
89+
ps.setChannel(channel="A", coupling="DC", VRange=1)
90+
ps.setChannel(channel="B", enabled=False)
91+
ps.setChannel(channel="C", enabled=False)
92+
ps.setChannel(channel="D", enabled=False)
93+
94+
ps.setResolution('12')
95+
ps.setSamplingInterval(sample_interval, sample_duration)
96+
ps.setSimpleTrigger("A", threshold_V=0.1, timeout_ms=1)
97+
98+
samples_per_segment = ps.memorySegments(n_captures)
99+
ps.setNoOfCaptures(n_captures)
100+
101+
data = np.zeros((n_captures, samples_per_segment), dtype=np.int16)
102+
103+
# Measurement
104+
t1 = time.time()
105+
106+
ps.runBlock()
107+
ps.waitReady()
108+
109+
t2 = time.time()
110+
print("Time to record data to scope: ", str(t2 - t1))
111+
112+
# downSampleMode raw (no downsampling) is 0x80000000. 0 is invalid!
113+
ps.getDataRawBulk(data=data, downSampleMode=0x80000000)
114+
115+
t3 = time.time()
116+
print("Time to copy to RAM: ", str(t3 - t2))
117+
118+
plt.imshow(data[:, 0:ps.noSamples], aspect='auto', interpolation='none',
119+
cmap=plt.cm.hot)
120+
plt.colorbar()
121+
plt.title("rapid block mode")
122+
plt.show()
123+
print("Rapid block mode test passed.")
124+
125+
126+
class Handler:
127+
128+
def printing(self, text):
129+
print(text)
130+
131+
def data_ready(self, handle, status, noOfSamples, overflow,
132+
pParameter=None):
133+
"""Show the asynchronously received data."""
134+
if status == 0:
135+
self.printing("{} samples received with overflow: {}".format(
136+
noOfSamples, overflow))
137+
plt.plot(self.data)
138+
plt.title("async")
139+
plt.show()
140+
self.ps._lowLevelClearDataBuffer(self.config[0], 0,
141+
downSampleMode=0x80000000)
142+
self.printing("Data reading asynchronously test passed.")
143+
else:
144+
self.printing("Data receiving error {}.".format(status))
145+
146+
def test_read_async(self, handle=None, status=0, pParameter=None):
147+
"""
148+
Test reading data asynchronously.
149+
150+
If you call it manually instead of using it as a callback, use
151+
pParameter for handing over the picoscope instance.
152+
"""
153+
if pParameter is not None:
154+
ps = pParameter
155+
else:
156+
ps = self.ps
157+
if status == 0:
158+
self.printing("Block is ready and can be read.")
159+
# config is a global variable written by the caller.
160+
channel, numSamples = self.config
161+
# Define data for data_ready.
162+
self.data = np.zeros(ps.noSamples, dtype=np.int16)
163+
if not isinstance(channel, int):
164+
channel = ps.CHANNELS[channel]
165+
self.config = channel, numSamples
166+
ps._lowLevelClearDataBufferAll(channel, 0)
167+
ps._lowLevelSetDataBuffer(channel, self.data,
168+
downSampleMode=0x80000000,
169+
segmentIndex=0)
170+
ps._lowLevelGetValuesAsync(ps.noSamples, 0, 1, 0x80000000, 0,
171+
self.data_ready, None)
172+
self.printing("Get values async started.")
173+
else:
174+
self.printing("Data is not ready. RunBlock had an error.")
175+
176+
177+
def test_runBlock_async(ps, channel="A", sample_interval=100e-9,
178+
sample_duration=2e-3):
179+
"""Test running a block asynchronously."""
180+
# Define a handler to exchange data
181+
global handler
182+
handler = Handler()
183+
handler.ps = ps
184+
# Configuration of Picoscope
185+
ps.setChannel(channel=channel, coupling="DC", VRange=1)
186+
ps.memorySegments(1)
187+
ps.setNoOfCaptures(1)
188+
ps.setResolution('12')
189+
interval, samples, maxSamples = ps.setSamplingInterval(sample_interval,
190+
sample_duration)
191+
ps.setSimpleTrigger("A", threshold_V=0.1, timeout_ms=1)
192+
193+
handler.config = channel, samples
194+
# Run the block
195+
ps.runBlock(callback=handler.test_read_async)
196+
print("Run block started, waiting 1 s.")
197+
time.sleep(1)
198+
print("Run block finished.")
199+
200+
201+
def test_downsampling(ps,
202+
sample_interval=100e-9, # 100 ns
203+
sample_duration=2e-3, # 1 ms
204+
):
205+
"""Test for different downsampling methods."""
206+
ps._lowLevelClearDataBufferAll()
207+
ps.setChannel(channel="A", coupling="DC", VRange=1)
208+
ps.setChannel(channel="B", enabled=False)
209+
ps.setChannel(channel="C", enabled=False)
210+
ps.setChannel(channel="D", enabled=False)
211+
212+
ps.setResolution('12')
213+
ps.memorySegments(1)
214+
ps.setNoOfCaptures(1)
215+
interval, samples, maxSamples = ps.setSamplingInterval(sample_interval,
216+
sample_duration)
217+
ps.setSimpleTrigger("A", threshold_V=0.1, timeout_ms=1)
218+
219+
ps.runBlock()
220+
ps.waitReady()
221+
222+
data0 = np.zeros(ps.noSamples, dtype=np.int16)
223+
data1 = np.zeros(ps.noSamples, dtype=np.int16)
224+
data2 = np.zeros(ps.noSamples, dtype=np.int16)
225+
226+
# downSampleMode raw (no downsampling) is 0x80000000. 0 is invalid!
227+
ps.getDataRaw(data=data0, downSampleMode=0x80000000)
228+
ps.getDataRaw(data=data1, downSampleMode=ps.RATIO_MODE['decimate'],
229+
downSampleRatio=10)
230+
ps.getDataRaw(data=data2, downSampleMode=ps.RATIO_MODE['average'],
231+
downSampleRatio=10)
232+
233+
samplesReduced = len(data0) // 10
234+
plt.plot(data0, label="raw")
235+
plt.plot(range(0, 10 * samplesReduced, 10)[:samplesReduced],
236+
data1[:samplesReduced], label="decimate")
237+
plt.plot(range(0, 10 * samplesReduced, 10)[:samplesReduced],
238+
data2[:samplesReduced], label="average")
239+
plt.title("downsampling")
240+
plt.legend()
241+
plt.show()
242+
print("Downsampling test passed.")
243+
244+
245+
if __name__ == "__main__":
246+
"""Run all the tests."""
247+
# Initialize the picoscope
248+
ps = ps6000a.PS6000a()
249+
250+
try:
251+
# Run tests.
252+
test_general_unit_calls(ps)
253+
test_timebase(ps)
254+
test_deviceResolution(ps)
255+
test_rapid_block_mode(ps)
256+
test_downsampling(ps)
257+
test_runBlock_async(ps)
258+
finally:
259+
# Close the connection
260+
ps.close()
261+
print("All tests passed.")

0 commit comments

Comments
 (0)