Rapid Block Mode Problem (2407B, Python)

Post general discussions on using our drivers to write your own software here
Post Reply
Stefan_MS
Newbie
Posts: 0
Joined: Tue Jun 06, 2023 12:29 pm

Rapid Block Mode Problem (2407B, Python)

Post by Stefan_MS »

Hi,

I'm using the PicoScope 2407B and for my measurements I'm using 3 input signals (A, B - signal, C - trigger).
I checked the Rapid Block Mode with GetValuesBulk and it works now. But I don't get the times with ps2000aGetValuesTriggerTimeOffsetBulk64. What's the problem here? And is there a way to get the maximum number of segments (with for example 3000 samples), which I can use for this mode?

Code: Select all

from ctypes import *
import matplotlib.pyplot as plt
import numpy as np
from picosdk.ps2000a import ps2000a
from picosdk.functions import assert_pico_ok
import time


# ------------------------------------------------------------------------------------------------------ PICOSCOPE 2407B
class PicoScope2407B:
    name = "PicoScope 2407B"

    def __init__(self):
        super().__init__()
        self.__default_picoscope_settings()
        self.status = {}

    def __default_picoscope_settings(self):
        channel = ps2000a.PS2000A_CHANNEL
        coupling = ps2000a.PS2000A_COUPLING
        voltage_range = ps2000a.PS2000A_RANGE
        direction = ps2000a.PS2000A_THRESHOLD_DIRECTION
        self.handle = c_int16()
        self.chA = {"channel": channel["PS2000A_CHANNEL_A"],
                    "enabled": True,
                    "coupling": coupling["PS2000A_DC"],
                    "voltage_range": voltage_range["PS2000A_5V"],
                    "analog_offset": float(0)}
        self.chB = {"channel": channel["PS2000A_CHANNEL_B"],
                    "enabled": True,
                    "coupling": coupling["PS2000A_DC"],
                    "voltage_range": voltage_range["PS2000A_5V"],
                    "analog_offset": float(0)}
        self.chC = {"channel": channel["PS2000A_CHANNEL_C"],
                    "enabled": True,
                    "coupling": coupling["PS2000A_DC"],
                    "voltage_range": voltage_range["PS2000A_5V"],
                    "analog_offset": float(0)}
        self.chD = {"channel": channel["PS2000A_CHANNEL_D"],
                    "enabled": False,
                    "coupling": coupling["PS2000A_DC"],
                    "voltage_range": voltage_range["PS2000A_5V"],
                    "analog_offset": float(0)}
        self.trigger = {"enabled": True,
                        "source": channel["PS2000A_CHANNEL_C"],
                        "threshold_adc": 0,
                        "direction": direction["PS2000A_RISING"],
                        "delay": 0,
                        "autoTrigger_ms": 0}

    def open_unit(self):
        self.status["OpenUnit"] = ps2000a.ps2000aOpenUnit(
            byref(self.handle),
            None
        )
        assert_pico_ok(self.status["OpenUnit"])

    def set_channels(self):
        channels = [self.chA, self.chB, self.chC, self.chD]
        names = ["A", "B", "C", "D"]
        for ch, name in zip(channels, names):
            self.status[f"SetCh{name}"] = ps2000a.ps2000aSetChannel(
                self.handle,
                ch["channel"],
                ch["enabled"],
                ch["coupling"],
                ch["voltage_range"],
                ch["analog_offset"]
            )
            assert_pico_ok(self.status[f"SetCh{name}"])

    def set_simple_trigger(self):
        self.status[f"SetSimpleTrigger"] = ps2000a.ps2000aSetSimpleTrigger(
            self.handle,
            self.trigger["enabled"],
            self.trigger["source"],
            self.trigger["threshold_adc"],
            self.trigger["direction"],
            self.trigger["delay"],
            self.trigger["autoTrigger_ms"]
        )
        assert_pico_ok(self.status[f"SetSimpleTrigger"])

    def get_timebase(self, samples=1000, wanted_time_interval_ns=10):
        timebase = 0
        time_interval_ns = c_float()
        oversample = c_int16(0)
        max_samples = c_int32()
        segment_index = 0
        while ps2000a.ps2000aGetTimebase2(
                self.handle,
                timebase,
                samples,
                byref(time_interval_ns),
                oversample,
                byref(max_samples),
                segment_index
            ) != 0 or time_interval_ns.value <= wanted_time_interval_ns:
            timebase += 1
        timebase -= 1
        self.status[f"GetTimebase2"] = ps2000a.ps2000aGetTimebase2(
            self.handle,
            timebase,
            samples,
            byref(time_interval_ns),
            oversample,
            byref(max_samples),
            segment_index
        )
        assert_pico_ok(self.status[f"GetTimebase2"])
        return timebase, time_interval_ns.value, max_samples.value

    def memory_segments(self, segments=10, samples=1000):
        max_samples = c_int32(samples)
        self.status[f"MemorySegments"] = ps2000a.ps2000aMemorySegments(
            self.handle,
            segments,
            byref(max_samples)
        )
        assert_pico_ok(self.status[f"MemorySegments"])
        return max_samples.value

    def set_captures(self, captures=10):
        self.status[f"SetNoOfCaptures"] = ps2000a.ps2000aSetNoOfCaptures(
            self.handle,
            captures
        )
        assert_pico_ok(self.status[f"SetNoOfCaptures"])

    def run_block(self, pre_trigger_samples=0, post_trigger_samples=1000, timebase=0, segment_index=0):
        oversample = 1
        time_indisposed_ms = c_int32()
        lpReady = None
        pParameter = None
        self.status[f"RunBlock"] = ps2000a.ps2000aRunBlock(
            self.handle,
            pre_trigger_samples,
            post_trigger_samples,
            timebase,
            oversample,
            byref(time_indisposed_ms),
            segment_index,
            lpReady,
            pParameter
        )
        assert_pico_ok(self.status[f"RunBlock"])
        return time_indisposed_ms.value

    def set_data_buffer(self, segments=10, samples=1000):
        channels = [self.chA, self.chB, self.chC, self.chD]
        mode = ps2000a.PS2000A_RATIO_MODE
        for ch in channels:
            if ch["enabled"]:
                ch["buffer"] = ((c_int16 * samples) * segments)()
                for segment_index in range(segments):
                    self.status[f"SetDataBuffer"] = ps2000a.ps2000aSetDataBuffer(
                        self.handle,
                        ch["channel"],
                        byref(ch["buffer"][:][segment_index]),
                        samples,
                        segment_index,
                        mode["PS2000A_RATIO_MODE_NONE"]
                    )
                assert_pico_ok(self.status[f"SetDataBuffer"])

    def is_ready(self):
        ready = c_int16(0)
        check = c_int16(0)
        while ready.value == check.value:
            self.status["IsReady"] = ps2000a.ps2000aIsReady(
                self.handle,
                byref(ready)
            )
        assert_pico_ok(self.status[f"IsReady"])

    def get_maxadc(self):
        value = c_int32()
        self.status[f"MaximumValue"] = ps2000a.ps2000aMaximumValue(
            self.handle,
            byref(value)
        )
        assert_pico_ok(self.status[f"MaximumValue"])
        return value.value

    def stop(self):
        self.status[f"Stop"] = ps2000a.ps2000aStop(
            self.handle
        )
        assert_pico_ok(self.status[f"Stop"])

    def close_unit(self):
        self.status[f"CloseUnit"] = ps2000a.ps2000aCloseUnit(
            self.handle
        )
        assert_pico_ok(self.status[f"CloseUnit"])

    def convert_values_adc2mV(self, maxADC=32767):
        channels = [self.chA, self.chB, self.chC, self.chD]
        channel_input_ranges = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000]
        for ch in channels:
            if ch["enabled"]:
                ch["buffer"] = (np.asarray(ch["buffer"]) / maxADC) * channel_input_ranges[ch["voltage_range"]]

    def display_data(self):
        channels = [self.chA, self.chB, self.chC, self.chD]
        for ch in channels:
            if ch["enabled"]:
                plt.figure()
                #plt.plot(np.mean(ch["buffer"], axis=0))
                plt.imshow(ch["buffer"], cmap='gray', aspect='auto')
                plt.show()

    def get_values_bulk(self, segments=10, samples=1000):
        max_samples = c_uint32(samples)
        down_sample_ratio = 0
        from_segment_index = 0
        to_segment_index = segments - 1
        down_sample_ratio_mode = ps2000a.PS2000A_RATIO_MODE["PS2000A_RATIO_MODE_NONE"]
        overflow = (c_int16 * segments)()
        self.status[f"GetValuesBulk"] = ps2000a.ps2000aGetValuesBulk(
            self.handle,
            byref(max_samples),
            from_segment_index,
            to_segment_index,
            down_sample_ratio,
            down_sample_ratio_mode,
            byref(overflow)
        )
        assert_pico_ok(self.status[f"GetValuesBulk"])
        return max_samples.value, overflow

    def get_values_trigger_time_offset_bulk(self, segments=10):
        times = (c_int64 * segments)()
        time_units = c_char()
        from_segment_index = 0
        to_segment_index = segments - 1
        self.status[f"GetValuesTriggerTimeOffsetBulk"] = ps2000a.ps2000aGetValuesTriggerTimeOffsetBulk64(
            self.handle,
            byref(times),
            byref(time_units),
            from_segment_index,
            to_segment_index
        )
        assert_pico_ok(self.status[f"GetValuesTriggerTimeOffsetBulk"])

    def rapid_block_mode(self):
        #  Block mode example like in the programming guide.
        n_segments = 3000
        max_samples = 3000

        #  Open the oscilloscope.
        self.open_unit()
        #  Select channel ranges and AC/DC coupling.
        self.set_channels()
        #  Set up single trigger
        self.set_simple_trigger()
        #  Get timebase information
        timebase, time_interval_ns, samples = self.get_timebase(samples=max_samples, wanted_time_interval_ns=10)
        #  Set the number of memory segments equal to or greater than the number of captures required.
        #  Specify the number of waveforms to capture before each run.
        self.memory_segments(segments=n_segments, samples=max_samples)
        self.set_captures(captures=n_segments)
        #  Start the oscilloscope running.
        self.run_block(pre_trigger_samples=0, post_trigger_samples=max_samples, timebase=timebase)
        #  Tell the driver where your memory buffers are. Call the function once for each channel/segment combination
        #  for which you require data.
        self.set_data_buffer(segments=n_segments, samples=max_samples)
        #  Start collecting data.
        self.is_ready()
        #  Transfer the blocks of data from the oscilloscope
        self.get_values_bulk(segments=n_segments, samples=max_samples)
        #  Get times.
        #self.get_values_trigger_time_offset_bulk(segments=n_segments)
        #  Find the max ADC count and convert values.
        maxADC = self.get_maxadc()
        self.convert_values_adc2mV(maxADC)
        #  Display data.
        self.display_data()
        #  Stop the oscilloscope.
        self.stop()
        #  Close Unit.
        self.close_unit()


if __name__ == '__main__':
    pico = PicoScope2407B()
    if pico.name == "PicoScope 2407B":
        pico.rapid_block_mode()
        print(pico.status)
Thanks in advance!

Post Reply