# PicoScope 5000 Series (A API) Mixed Signal Instrument Driver Oscilloscope Streaming Data Capture Example

This is an example of an instrument control session using a device object. The instrument control session comprises all the steps you are likely to take when communicating with your instrument.

These steps are:

1. Create a device object
2. Connect to the instrument
3. Configure properties
4. Invoke functions
5. Disconnect from the instrument

To run the instrument control session, type the name of the file, PS5000A_ID_MSO_Streaming_Example, at the MATLAB command prompt.

The file, PS5000A_ID_MSO_STREAMING_EXAMPLE.M must be on your MATLAB PATH. For additional information on setting your MATLAB PATH, type 'help addpath' at the MATLAB command prompt.

Example: PS5000A_ID_MSO_Streaming_Example;

Description: Demonstrates how to set properties and call functions in order to capture data in streaming mode from a PicoScope 5000 Series Mixed Signal Oscilloscope using the underlying 'A' API library functions.

Note: Not all device functions used in this example are compatible with the Test and Measurement Tool.

See also: `icdevice` | `invoke`

Copyright: © 2018 Pico Technology Ltd. See LICENSE file for terms.

## Contents

- Suggested input test signals
- Clear command window and close any figures
- Load configuration information
- Parameter definitions
- Device connection
- Display unit information
- Set analog channels and digital ports
- Change resolution
- Set simple trigger
- Set data buffers
- Start streaming and collect data
- Stop the device
- Find the number of samples
- Process data
- Disconnect device

## Suggested input test signals

This example was published using the following test signals:

- Channel A: 3 Vpp, 1 Hz sine wave
- Channel B: 2 Vpp, 4 Hz square wave
- PORT0 : 10 Hz bit counter signal from test device (applied to all channels).

## Clear command window and close any figures

    clc;
    close all;

## Load configuration information

    PS5000aConfig;

## Parameter definitions

Define any parameters that might be required throughout the script.

    channelA = ps5000aEnuminfo.enPS5000AChannel.PS5000A_CHANNEL_A;
    channelB = ps5000aEnuminfo.enPS5000AChannel.PS5000A_CHANNEL_B;
    dPort0   = ps5000aEnuminfo.enPS5000AChannel.PS5000A_DIGITAL_PORT0;
    dPort1   = ps5000aEnuminfo.enPS5000AChannel.PS5000A_DIGITAL_PORT1;

## Device connection

    % Check if an Instrument session using the device object |ps5000aDeviceObj|
    % is still open, and if so, disconnect if the User chooses 'Yes' when prompted.
    if (exist('ps5000aDeviceObj', 'var') && ps5000aDeviceObj.isvalid && strcmp(ps5000aDeviceObj.status, 'open'))

        openDevice = questionDialog(['Device object ps5000aDeviceObj has an open connection. ' ...
            'Do you wish to close the connection and continue?'], ...
            'Device Object Connection Open');

        if (openDevice == PicoConstants.TRUE)

            % Close connection to device.
            disconnect(ps5000aDeviceObj);
            delete(ps5000aDeviceObj);

        else

            % Exit script if User selects 'No'.
            return;

        end

    end

    % Create a device object.
    ps5000aDeviceObj = icdevice('picotech_ps5000a_generic', '');

    % Connect device object to hardware.
    connect(ps5000aDeviceObj);

    PicoScope 5000 Series (A API) MATLAB Instrument Driver

    Copyright © 2013-2018 Pico Technology Ltd. All rights reserved.

    Number of units found: 1

    Serial number(s): FY971/0003

    Opening PicoScope 5000 Series (A API) device...

       Instrument Device Object Using Driver : picotech_ps5000a_generic.mdd

       Instrument Information
          Type:               Oscilloscope
          Manufacturer:       Pico Technology Ltd.
          Model:              PicoScope 5000A, 5000B and 5000D Series

       Driver Information
          DriverType:         MATLAB generic
          DriverName:         picotech_ps5000a_generic.mdd
          DriverVersion:      2.2.14.39

       Communication State
          Status:             open

    Default Channel Setup:-
    -----------------------

    Channel A:-
    	Enabled: True
    	Coupling: DC
    	Range: 5 V
    	Analog offset: 0.0 V

    Channel B:-
    	Enabled: True
    	Coupling: DC
    	Range: 5 V
    	Analog offset: 0.0 V

    Channel C:-
    	Enabled: True
    	Coupling: DC
    	Range: 5 V
    	Analog offset: 0.0 V

    Channel D:-
    	Enabled: True
    	Coupling: DC
    	Range: 5 V
    	Analog offset: 0.0 V

    Default Digital Port Setup:-
    ----------------------------

    PORT0:-
    	Enabled: True
    	Logic Level: +1.5 V

    PORT1:-
    	Enabled: True
    	Logic Level: +1.5 V

    Turning off Equivalent Time Sampling...
    Equivalent Time Sampling turned off.

    Turning off trigger...
    Trigger turned off.

    Default Block mode parameters:-

                   Timebase index : 65
                     Time Interval: 504 ns
     Number of pre-trigger samples: 0
    Number of post-trigger samples: 10000
           Total number of samples: 10000

    Default Streaming mode parameters:-

     Streaming interval: 1.00e-06 s
    Streaming auto stop: 1

    Default Signal generator parameters:-

    Start frequency: 1000 Hz
     Stop frequency: 1000 Hz

    Connected to PicoScope 5000 Series (A API) device:-

              Instrument Model: 5444DMSO
           Batch/Serial Number: FY971/0003
                   USB Version: 3.0
               Analog Channels: 4
              Digital Channels: 16
                    Resolution: 8 bits
                     Bandwidth: 200 MHz
                 Buffer Memory: 512 MS
         Maximum Sampling Rate: 1 GS/s
         Signal Generator Type: Arbitrary Waveform Generator
    5 V Power Supply connected: True

## Display unit information

    [status.getUnitInfo, unitInfo] = invoke(ps5000aDeviceObj, 'getUnitInfo');
    disp(unitInfo);

        'Driver version: 2.1.0.687'
        'USB version: 3.0'
        'Hardware version: 1'
        'Variant: 5444DMSO'
        'Batch & Serial: FY971/0003'
        'Cal. Date: 23May18'
        'Kernel version: 1.2'
        'Digital HW version: 1'
        'Analogue HW version: 1'

## Set analog channels and digital ports

All channels are enabled by default - if the device is a 4-channel scope, switch off channels C and D so device can be set to 15-bit resolution.

    % Channel A
    channelSettings(1).enabled = PicoConstants.TRUE;
    channelSettings(1).coupling = ps5000aEnuminfo.enPS5000ACoupling.PS5000A_DC;
    channelSettings(1).range = ps5000aEnuminfo.enPS5000ARange.PS5000A_2V;
    channelSettings(1).analogueOffset = 0.0;

    channelARangeMv = PicoConstants.SCOPE_INPUT_RANGES(channelSettings(1).range + 1);

    % Channel B
    channelSettings(2).enabled = PicoConstants.TRUE;
    channelSettings(2).coupling = ps5000aEnuminfo.enPS5000ACoupling.PS5000A_DC;
    channelSettings(2).range = ps5000aEnuminfo.enPS5000ARange.PS5000A_2V;
    channelSettings(2).analogueOffset = 0.0;

    % Variables that will be required later
    channelBRangeMv = PicoConstants.SCOPE_INPUT_RANGES(channelSettings(2).range + 1);

    if (ps5000aDeviceObj.channelCount == PicoConstants.QUAD_SCOPE)

        % Channel C
        channelSettings(3).enabled = PicoConstants.FALSE;
        channelSettings(3).coupling = ps5000aEnuminfo.enPS5000ACoupling.PS5000A_DC;
        channelSettings(3).range = ps5000aEnuminfo.enPS5000ARange.PS5000A_2V;
        channelSettings(3).analogueOffset = 0.0;

        % Channel D
        channelSettings(4).enabled = PicoConstants.FALSE;
        channelSettings(4).coupling = ps5000aEnuminfo.enPS5000ACoupling.PS5000A_DC;
        channelSettings(4).range = ps5000aEnuminfo.enPS5000ARange.PS5000A_2V;
        channelSettings(4).analogueOffset = 0.0;

    end

    % Keep the status values returned from the driver.
    numChannels = get(ps5000aDeviceObj, 'channelCount');
    status.setChannelStatus = zeros(numChannels, 1);

    [status.currentPowerSource] = invoke(ps5000aDeviceObj, 'ps5000aCurrentPowerSource');

    % Check if the power supply is connected - channels C and D will not be
    % enabled on a 4-channel oscilloscope if it is only USB powered.
    if (status.currentPowerSource == PicoStatus.PICO_POWER_SUPPLY_NOT_CONNECTED)

        numChannels = PicoConstants.DUAL_SCOPE;

    end

    for ch = 1:numChannels

        status.setChannelStatus(ch) = invoke(ps5000aDeviceObj, 'ps5000aSetChannel', ...
            (ch - 1), channelSettings(ch).enabled, ...
            channelSettings(ch).coupling, channelSettings(ch).range, ...
            channelSettings(ch).analogueOffset);

    end

Use the `ps5000aSetDigitalPort()` function to enable/disable digital ports and set the logic level threshold. This function is located in the Instrument Driver's Digital Group. Enabling a digital port will enable all channels on that port, while setting the enabled parameter to 0 will turn off all digital channels on that port.

    digitalObj = get(ps5000aDeviceObj, 'Digital');

    % Digital Port  : 128 (ps5000aEnuminfo.enPS5000AChannel.PS5000A_DIGITAL_PORT0)
    % Enabled       : 1 (On - PicoConstants.TRUE)
    % Logic Level   : 1.5 V

    status.setDPort0 = invoke(digitalObj, 'ps5000aSetDigitalPort', dPort0, 1, 1.5);

    % Digital Port  : 129 (ps5000aEnuminfo.enPS5000AChannel.PS5000A_DIGITAL_PORT1)
    % Enabled       : 0 (Off - PicoConstants.FALSE)
    % Logic Level   : 0 V

    status.setDPort1 = invoke(digitalObj, 'ps5000aSetDigitalPort', dPort1, 0, 0);

## Change resolution

The maximum resolution will depend on the number of channels enabled.

    % Set resolution to 15 bits as 2 channels will be enabled.
    [status.setResolution, resolution] = invoke(ps5000aDeviceObj, 'ps5000aSetDeviceResolution', 15);

    % Obtain the maximum Analog Digital Converter (ADC) count value from the
    % driver - this is used for scaling values returned from the driver when
    % data is collected. This value may change depending on the resolution
    % selected.
    maxADCCount = get(ps5000aDeviceObj, 'maxADCValue');

    ps5000aSetDeviceResolution: Device resolution set to 15 bits.

## Set simple trigger

Set a trigger on channel A, with an auto timeout - the default value for delay is used. The device will wait for a rising edge through the specified threshold unless the timeout occurs first.

    % Trigger properties and functions are located in the Instrument
    % Driver's Trigger group.

    triggerGroupObj = get(ps5000aDeviceObj, 'Trigger');
    triggerGroupObj = triggerGroupObj(1);

    % Set the |autoTriggerMs| property in order to automatically trigger the
    % oscilloscope after 1 second if a trigger event has not occurred. Set to 0
    % to wait indefinitely for a trigger event.

    set(triggerGroupObj, 'autoTriggerMs', 1000);

    % Channel     : 0 (ps5000aEnuminfo.enPS5000AChannel.PS5000A_CHANNEL_A)
    % Threshold   : 500 mV
    % Direction   : 2 (ps5000aEnuminfo.enPS5000AThresholdDirection.PS5000A_RISING)

    [status.setSimpleTrigger] = invoke(triggerGroupObj, 'setSimpleTrigger', 0, 500, 2);

## Set data buffers

Data buffers for channels A and B as well as Digital PORT0 - buffers should be set with the driver, and these MUST be passed with application buffers to the wrapper driver. This will ensure that data is correctly copied from the driver buffers for later processing.

    overviewBufferSize  = 100000; % Size of the buffer to collect data from buffer.
    segmentIndex        = 0;
    ratioMode           = ps5000aEnuminfo.enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE;

    % Buffers to be passed to the driver
    pDriverBufferChA    = libpointer('int16Ptr', zeros(overviewBufferSize, 1, 'int16'));
    pDriverBufferChB    = libpointer('int16Ptr', zeros(overviewBufferSize, 1, 'int16'));
    pDriverBufferDPort0 = libpointer('int16Ptr', zeros(overviewBufferSize, 1, 'int16'));

    % Call the functions to register the buffers
    status.setDataBufferChA = invoke(ps5000aDeviceObj, 'ps5000aSetDataBuffer', ...
        channelA, pDriverBufferChA, overviewBufferSize, segmentIndex, ratioMode);

    status.setDataBufferChB = invoke(ps5000aDeviceObj, 'ps5000aSetDataBuffer', ...
        channelB, pDriverBufferChB, overviewBufferSize, segmentIndex, ratioMode);

    status.setDataBufferPortD0 = invoke(ps5000aDeviceObj, 'ps5000aSetDataBuffer', ...
        dPort0, pDriverBufferDPort0, overviewBufferSize, segmentIndex, ratioMode);

    % Application Buffers - these are for copying from the driver into.
    pAppBufferChA       = libpointer('int16Ptr', zeros(overviewBufferSize, 1, 'int16'));
    pAppBufferChB       = libpointer('int16Ptr', zeros(overviewBufferSize, 1, 'int16'));
    pAppBufferDPort0    = libpointer('int16Ptr', zeros(overviewBufferSize, 1, 'int16'));

    % Streaming properties and functions are located in the Instrument Driver's
    % Streaming group.

    streamingGroupObj = get(ps5000aDeviceObj, 'Streaming');
    streamingGroupObj = streamingGroupObj(1);

    % Register application and driver buffers (with the wrapper library).
    status.setAppDriverBuffersA = invoke(streamingGroupObj, 'setAppAndDriverBuffers', channelA, ...
        pAppBufferChA, pDriverBufferChA, overviewBufferSize);

    status.setAppDriverBuffersB = invoke(streamingGroupObj, 'setAppAndDriverBuffers', channelB, ...
        pAppBufferChB, pDriverBufferChB, overviewBufferSize);

    status.setAppDriverBuffersPortD0 = invoke(streamingGroupObj, 'setAppAndDriverBuffers', dPort0, ...
        pAppBufferDPort0, pDriverBufferDPort0, overviewBufferSize);

## Start streaming and collect data

Use default value for streaming interval which is 1e-6 for 1 MS/s. Collect data for 5 seconds with auto stop - maximum array size will depend on the PC's resources - type `memory` at the MATLAB command prompt for further information.

To change the sample interval set the `streamingInterval` property of the Streaming group object. The call to the `ps5000aRunStreaming()` function will output the actual sampling interval used by the driver.

    % To change the sample interval e.g 5 us for 200 kS/s
    % set(streamingGroupObj, 'streamingInterval', 5e-6);

Set the number of pre- and post-trigger samples. If no trigger is set the library will still store `numPreTriggerSamples` + `numPostTriggerSamples`.

    set(ps5000aDeviceObj, 'numPreTriggerSamples', 0);
    set(ps5000aDeviceObj, 'numPostTriggerSamples', 5000000);

The `autoStop` parameter can be set to false (0) to allow for continuous data collection. set(streamingGroupObj, 'autoStop', PicoConstants.FALSE);

    % Set other streaming parameters
    downSampleRatio = 1;
    downSampleRatioMode = ps5000aEnuminfo.enPS5000ARatioMode.PS5000A_RATIO_MODE_NONE;

Defined buffers to store data collected from the channels. If capturing data without using the autoStop flag, or if using a trigger with the autoStop flag, allocate sufficient space (1.5 times the sum of the number of pre-trigger and post-trigger samples is shown below) to allow for additional pre-trigger data. Pre-allocating the array is more efficient than using `vertcat` to combine data.

    maxSamples = get(ps5000aDeviceObj, 'numPreTriggerSamples') + ...
        get(ps5000aDeviceObj, 'numPostTriggerSamples');

    % Take into account the downsampling ratio mode - required if collecting
    % data without a trigger and using the autoStop flag.

    finalBufferLength = round(1.5 * maxSamples / downSampleRatio);

    pBufferChAFinal     = libpointer('int16Ptr', zeros(finalBufferLength, 1, 'int16'));
    pBufferChBFinal     = libpointer('int16Ptr', zeros(finalBufferLength, 1, 'int16'));
    pBufferDPort0Final  = libpointer('int16Ptr', zeros(finalBufferLength, 1, 'int16'));

    % Prompt User to indicate if they wish to plot live streaming data.
    plotLiveData = questionDialog('Plot live streaming data?', 'Streaming Data Plot');

    if (plotLiveData == PicoConstants.TRUE)

        disp('Live streaming data collection with second plot on completion.');

    else

        disp('Streaming data plot on completion.');

    end

    originalPowerSource = invoke(ps5000aDeviceObj, 'ps5000aCurrentPowerSource');

    % Start streaming data collection.
    [status.runStreaming, sampleInterval, sampleIntervalTimeUnitsStr] = ...
        invoke(streamingGroupObj, 'ps5000aRunStreaming', downSampleRatio, ...
        downSampleRatioMode, overviewBufferSize);

    disp('Streaming data...');
    fprintf('Click the STOP button to stop capture or wait for auto stop if enabled.\n')

    % Variables to be used when collecting the data:

    hasAutoStopOccurred = PicoConstants.FALSE;  % Indicates if the device has stopped automatically.
    powerChange         = PicoConstants.FALSE;  % If the device power status has changed.
    newSamples          = 0; % Number of new samples returned from the driver.
    previousTotal       = 0; % The previous total number of samples.
    totalSamples        = 0; % Total samples captured by the device.
    startIndex          = 0; % Start index of data in the buffer returned.
    hasTriggered        = 0; % To indicate if trigger has occurred.
    triggeredAtIndex    = 0; % The index in the overall buffer where the trigger occurred.

    time = zeros(overviewBufferSize / downSampleRatio, 1);	% Array to hold time values

    status.getStreamingLatestValuesStatus = PicoStatus.PICO_OK; % OK

    % Display a 'Stop' button.
    [stopFig.h, stopFig.h] = stopButton();

    flag = 1; % Use flag variable to indicate if stop button has been clicked (0).
    setappdata(gcf, 'run', flag);

    % Plot Properties - these are for displaying data as it is collected.

    if (plotLiveData == PicoConstants.TRUE)

        % Plot on a single figure.
        figure1 = figure('Name','PicoScope 5000 Series (A API) Example - MSO Streaming Mode Capture', ...
             'NumberTitle','off');

        analogAxes = subplot(2, 1, 1);
        digitalAxes = subplot(2, 1, 2);

        % Estimate x-axis limit to try and avoid using too much CPU resources
        % when drawing - use max voltage range selected if plotting multiple
        % channels on the same graph.
        xlim(analogAxes, [0 (sampleInterval * finalBufferLength)]);
        xlim(digitalAxes, [0 (sampleInterval * finalBufferLength)]);

        yRange = max(channelARangeMv, channelBRangeMv);
        ylim(analogAxes, [(-1 * yRange) yRange]);

        hold(analogAxes,'on');
        hold(digitalAxes, 'on');

        grid(analogAxes, 'on');
        grid(digitalAxes, 'on');

        title(analogAxes, 'Analog Channel Data Acquisition');
        title(digitalAxes, 'Digital Channel Data Acquisition');

        if (strcmp(sampleIntervalTimeUnitsStr, 'us'))

            xLabelStr = 'Time (\mus)';

        else

            xLabelStr = strcat('Time (', sampleIntervalTimeUnitsStr, ')');

        end

        xlabel(analogAxes, xLabelStr);
        ylabel(analogAxes, 'Voltage (mV)');

        xlabel(digitalAxes, xLabelStr);
        ylabel(digitalAxes, 'Level (Counts)');

    end

    Streaming data plot on completion.
    ps5000aRunStreaming:- Sample interval 1 us
    Streaming data...
    Click the STOP button to stop capture or wait for auto stop if enabled.

Collect samples as long as the `hasAutoStopOccurred` flag has not been set or the call to `getStreamingLatestValues()` does not return an error code (check for STOP button push inside loop).

    while(hasAutoStopOccurred == PicoConstants.FALSE && status.getStreamingLatestValuesStatus == PicoStatus.PICO_OK)

        ready = PicoConstants.FALSE;

        while (ready == PicoConstants.FALSE)

           status.getStreamingLatestValuesStatus = invoke(streamingGroupObj, 'getStreamingLatestValues');

           ready = invoke(streamingGroupObj, 'isReady');

           % Give option to abort from here
           flag = getappdata(gcf, 'run');
           drawnow;

           if (flag == 0)

                disp('STOP button clicked - aborting data collection.')
                break;

           end

           drawnow;

        end

        % Check for data
        [newSamples, startIndex] = invoke(streamingGroupObj, 'availableData');

        if (newSamples > 0)

            % Check if the scope has triggered.
            [triggered, triggeredAt] = invoke(streamingGroupObj, 'isTriggerReady');

            if (triggered == PicoConstants.TRUE)

                % Adjust trigger position as MATLAB does not use zero-based
                % indexing.
                bufferTriggerPosition = triggeredAt + 1;

                fprintf('Triggered - index in buffer: %d\n', bufferTriggerPosition);

                hasTriggered = triggered;

                % Set the total number of samples at which the device
                % triggered.
                triggeredAtIndex = totalSamples + bufferTriggerPosition;

            end

            previousTotal   = totalSamples;
            totalSamples    = totalSamples + newSamples;

            % Printing to console can slow down acquisition - use for
            % demonstration.
            fprintf('Collected %d samples, startIndex: %d total: %d.\n', newSamples, startIndex, totalSamples);

            % Position indices of data in the buffer(s).
            firstValuePosn = startIndex + 1;
            lastValuePosn = startIndex + newSamples;

            % Convert data values to millivolts from the application buffer(s).
            bufferChAmV     = adc2mv(pAppBufferChA.Value(firstValuePosn:lastValuePosn), channelARangeMv, maxADCCount);
            bufferChBmV     = adc2mv(pAppBufferChB.Value(firstValuePosn:lastValuePosn), channelBRangeMv, maxADCCount);

            bufferDPort0    = pAppBufferDPort0.Value(firstValuePosn:lastValuePosn);

            % Process collected data further if required - this example plots
            % the data if the User has selected 'Yes' at the prompt.

            % Copy data into the final buffer(s).
            pBufferChAFinal.Value(previousTotal + 1:totalSamples)       = bufferChAmV;
            pBufferChBFinal.Value(previousTotal + 1:totalSamples)       = bufferChBmV;
            pBufferDPort0Final.Value(previousTotal + 1:totalSamples)    = bufferDPort0;

            if (plotLiveData == PicoConstants.TRUE)

                % Time axis.
                % Multiply by ratio mode as samples get reduced
                time = (double(sampleInterval) * double(downSampleRatio)) * (previousTotal:(totalSamples - 1));

                plot(analogAxes, time, bufferChAmV, time, bufferChBmV);
                plot(digitalAxes, time, bufferDPort0);

            end

            % Clear variables for use again
            clear bufferChAmV;
            clear bufferChBmV;
            clear bufferDPort0;
            clear firstValuePosn;
            clear lastValuePosn;
            clear startIndex;
            clear triggered;
            clear triggerAt;

       end

        % Check if auto stop has occurred.
        hasAutoStopOccurred = invoke(streamingGroupObj, 'autoStopped');

        if (hasAutoStopOccurred == PicoConstants.TRUE)

           disp('AutoStop: TRUE - exiting data collection loop.');
           break;

        end

        % Check if 'STOP' button has been clicked.
        flag = getappdata(gcf, 'run');
        drawnow;

        if (flag == 0)

            disp('STOP button clicked - aborting data collection.')
            break;

        end

    end

    % Close the STOP button window.
    if (exist('stopFig', 'var'))

        close('Stop Button');
        clear stopFig;

    end

    if (plotLiveData == PicoConstants.TRUE)

        drawnow;

        % Take hold off the axes.
        hold(analogAxes, 'off');
        hold(digitalAxes, 'off');

    end

    if (hasTriggered == PicoConstants.TRUE)

        fprintf('Triggered at overall index: %d\n\n', triggeredAtIndex);

    end

    fprintf('\n');

    Collected 68268 samples, startIndex: 0 total: 68268.
    Collected 31732 samples, startIndex: 68268 total: 100000.
    Collected 37034 samples, startIndex: 0 total: 137034.
    Collected 62966 samples, startIndex: 37034 total: 200000.
    Collected 73068 samples, startIndex: 0 total: 273068.
    Triggered - index in buffer: 8873
    Collected 26932 samples, startIndex: 73068 total: 300000.
    Collected 41834 samples, startIndex: 0 total: 341834.
    Collected 58166 samples, startIndex: 41834 total: 400000.
    Collected 77868 samples, startIndex: 0 total: 477868.
    Collected 22132 samples, startIndex: 77868 total: 500000.
    Collected 46634 samples, startIndex: 0 total: 546634.
    Collected 53366 samples, startIndex: 46634 total: 600000.
    Collected 82668 samples, startIndex: 0 total: 682668.
    Collected 17332 samples, startIndex: 82668 total: 700000.
    Collected 51434 samples, startIndex: 0 total: 751434.
    Collected 48566 samples, startIndex: 51434 total: 800000.
    Collected 87468 samples, startIndex: 0 total: 887468.
    Collected 12532 samples, startIndex: 87468 total: 900000.
    Collected 56234 samples, startIndex: 0 total: 956234.
    Collected 43766 samples, startIndex: 56234 total: 1000000.
    Collected 92268 samples, startIndex: 0 total: 1092268.
    Collected 7732 samples, startIndex: 92268 total: 1100000.
    Collected 61034 samples, startIndex: 0 total: 1161034.
    Collected 38966 samples, startIndex: 61034 total: 1200000.
    Collected 97068 samples, startIndex: 0 total: 1297068.
    Collected 2932 samples, startIndex: 97068 total: 1300000.
    Collected 65834 samples, startIndex: 0 total: 1365834.
    Collected 34166 samples, startIndex: 65834 total: 1400000.
    Collected 34100 samples, startIndex: 0 total: 1434100.
    Collected 65900 samples, startIndex: 34100 total: 1500000.
    Collected 70134 samples, startIndex: 0 total: 1570134.
    Collected 29866 samples, startIndex: 70134 total: 1600000.
    Collected 38900 samples, startIndex: 0 total: 1638900.
    Collected 61100 samples, startIndex: 38900 total: 1700000.
    Collected 74934 samples, startIndex: 0 total: 1774934.
    Collected 25066 samples, startIndex: 74934 total: 1800000.
    Collected 43700 samples, startIndex: 0 total: 1843700.
    Collected 56300 samples, startIndex: 43700 total: 1900000.
    Collected 79734 samples, startIndex: 0 total: 1979734.
    Collected 20266 samples, startIndex: 79734 total: 2000000.
    Collected 48500 samples, startIndex: 0 total: 2048500.
    Collected 51500 samples, startIndex: 48500 total: 2100000.
    Collected 84534 samples, startIndex: 0 total: 2184534.
    Collected 15466 samples, startIndex: 84534 total: 2200000.
    Collected 53300 samples, startIndex: 0 total: 2253300.
    Collected 46700 samples, startIndex: 53300 total: 2300000.
    Collected 89334 samples, startIndex: 0 total: 2389334.
    Collected 10666 samples, startIndex: 89334 total: 2400000.
    Collected 58100 samples, startIndex: 0 total: 2458100.
    Collected 41900 samples, startIndex: 58100 total: 2500000.
    Collected 94134 samples, startIndex: 0 total: 2594134.
    Collected 5866 samples, startIndex: 94134 total: 2600000.
    Collected 62900 samples, startIndex: 0 total: 2662900.
    Collected 37100 samples, startIndex: 62900 total: 2700000.
    Collected 98934 samples, startIndex: 0 total: 2798934.
    Collected 1066 samples, startIndex: 98934 total: 2800000.
    Collected 67700 samples, startIndex: 0 total: 2867700.
    Collected 32300 samples, startIndex: 67700 total: 2900000.
    Collected 35968 samples, startIndex: 0 total: 2935968.
    Collected 64032 samples, startIndex: 35968 total: 3000000.
    Collected 72000 samples, startIndex: 0 total: 3072000.
    Collected 28000 samples, startIndex: 72000 total: 3100000.
    Collected 40768 samples, startIndex: 0 total: 3140768.
    Collected 59232 samples, startIndex: 40768 total: 3200000.
    Collected 76800 samples, startIndex: 0 total: 3276800.
    Collected 23200 samples, startIndex: 76800 total: 3300000.
    Collected 45568 samples, startIndex: 0 total: 3345568.
    Collected 54432 samples, startIndex: 45568 total: 3400000.
    Collected 81600 samples, startIndex: 0 total: 3481600.
    Collected 18400 samples, startIndex: 81600 total: 3500000.
    Collected 50368 samples, startIndex: 0 total: 3550368.
    Collected 49632 samples, startIndex: 50368 total: 3600000.
    Collected 86400 samples, startIndex: 0 total: 3686400.
    Collected 13600 samples, startIndex: 86400 total: 3700000.
    Collected 55168 samples, startIndex: 0 total: 3755168.
    Collected 44832 samples, startIndex: 55168 total: 3800000.
    Collected 91200 samples, startIndex: 0 total: 3891200.
    Collected 8800 samples, startIndex: 91200 total: 3900000.
    Collected 59968 samples, startIndex: 0 total: 3959968.
    Collected 40032 samples, startIndex: 59968 total: 4000000.
    Collected 96000 samples, startIndex: 0 total: 4096000.
    Collected 4000 samples, startIndex: 96000 total: 4100000.
    Collected 64768 samples, startIndex: 0 total: 4164768.
    Collected 35232 samples, startIndex: 64768 total: 4200000.
    Collected 33034 samples, startIndex: 0 total: 4233034.
    Collected 66966 samples, startIndex: 33034 total: 4300000.
    Collected 69068 samples, startIndex: 0 total: 4369068.
    Collected 30932 samples, startIndex: 69068 total: 4400000.
    Collected 37834 samples, startIndex: 0 total: 4437834.
    Collected 62166 samples, startIndex: 37834 total: 4500000.
    Collected 73868 samples, startIndex: 0 total: 4573868.
    Collected 26132 samples, startIndex: 73868 total: 4600000.
    Collected 42634 samples, startIndex: 0 total: 4642634.
    Collected 57366 samples, startIndex: 42634 total: 4700000.
    Collected 78668 samples, startIndex: 0 total: 4778668.
    Collected 21332 samples, startIndex: 78668 total: 4800000.
    Collected 47434 samples, startIndex: 0 total: 4847434.
    Collected 52566 samples, startIndex: 47434 total: 4900000.
    Collected 83468 samples, startIndex: 0 total: 4983468.
    Collected 16532 samples, startIndex: 83468 total: 5000000.
    Collected 52234 samples, startIndex: 0 total: 5052234.
    Collected 47766 samples, startIndex: 52234 total: 5100000.
    Collected 88268 samples, startIndex: 0 total: 5188268.
    Collected 11732 samples, startIndex: 88268 total: 5200000.
    Collected 81940 samples, startIndex: 0 total: 5281940.
    AutoStop: TRUE - exiting data collection loop.
    Triggered at overall index: 281941

## Stop the device

This function should be called regardless of whether the autoStop property is enabled or not.

    [status.stop] = invoke(ps5000aDeviceObj, 'ps5000aStop');

## Find the number of samples

This is the number of samples held in the shared library itself. The actual number of samples collected when using a trigger is likely to be greater.

    [status.noOfStreamingValues, numStreamingValues] = invoke(streamingGroupObj, 'ps5000aNoOfStreamingValues');

    fprintf('Number of samples available after data collection: %u\n', numStreamingValues);

    Number of samples available after data collection: 5000000

## Process data

Process data post-capture if required - here the data will be plotted.

    % Reduce size of arrays if required.

    if (totalSamples < finalBufferLength)

        pBufferChAFinal.Value(totalSamples + 1:end) = [];
        pBufferChBFinal.Value(totalSamples + 1:end) = [];
        pBufferDPort0Final.Value(totalSamples + 1:end)  = [];

    end

    % Retrieve data for the channels.
    channelAFinal = pBufferChAFinal.Value();
    channelBFinal = pBufferChBFinal.Value();
    dPort0Final   = pBufferDPort0Final.Value();

    % Plot total analog and digital data collected on separate figures.

Analog data

    scrsz = get(groot,'ScreenSize');

    analogFinalFigure = figure('Name','PicoScope 5000 Series (A API) Example - MSO Streaming Mode Capture', ...
        'NumberTitle', 'off', 'Position', [1 scrsz(4)/4 scrsz(3)/2 scrsz(4)/2]);

    movegui(analogFinalFigure, 'west');

    analogFinalAxes = axes('Parent', analogFinalFigure);
    hold(analogFinalAxes, 'on');

    title(analogFinalAxes, 'Analog Data Acquisition (Final)');

    if (strcmp(sampleIntervalTimeUnitsStr, 'us'))

        xLabelStr = 'Time (\mus)';

    else

        xLabelStr = strcat('Time (', sampleIntervalTimeUnitsStr, ')');

    end

    xlabel(analogFinalAxes, xLabelStr);
    ylabel(analogFinalAxes, 'Voltage (mV)');

    % Find the maximum voltage range.
    maxYRange = max(channelARangeMv, channelBRangeMv);
    ylim(analogFinalAxes,[(-1 * maxYRange) maxYRange]);

    time = (double(sampleInterval) * double(downSampleRatio)) * (0:length(channelAFinal) - 1);

    plot(analogFinalAxes, time, channelAFinal, time, channelBFinal);

    grid(analogFinalAxes, 'on');
    legend(analogFinalAxes, 'Channel A', 'Channel B');

    hold(analogFinalAxes, 'off');

Digital data

    digitalFinalFigure = figure('Name','PicoScope 5000 Series (A API) Example - MSO Streaming Mode Capture', ...
        'NumberTitle', 'off', 'Position', [scrsz(3)/2 + 1 scrsz(4)/4 scrsz(3)/2 scrsz(4)/2]);

    movegui(digitalFinalFigure, 'east');

    disp('Converting digital integer data to binary...');

    dPort0Binary = zeros(length(dPort0Final), 8);

    % Retrieve the bit values from the lower 8 bits of the 16-bit values
    % returned for dPort0 - each bit corresponds to a digital channel. Channel
    % D0 data will be in column 8 and D7 data will be in column 1.
    for sample = 1:length(dPort0Final)

        dPort0Binary(sample,:)= bitget(dPort0Final(sample), 8:-1:1, 'int16');

    end

    % Specify colours to use for the plots - the colour to use will be selected
    % according to the digital channel.
    digiPlotColours = ['m', 'b', 'r', 'g'];

    % Display digital data in a 4 x 2 grid
    for i = 1:8

        subplot(4, 2, i);
        plot(time, dPort0Binary(:, (8 - (i - 1))), digiPlotColours(rem(i, length(digiPlotColours)) + 1));
        title(strcat('Digital Channel D', num2str(i - 1)));
        xlabel(strcat('Time (', sampleIntervalTimeUnitsStr, ')'));
        ylabel('Logic Level');
        axis([-inf, inf, -0.5, 1.5])
        grid on;

    end

    Converting digital integer data to binary...

## Disconnect device

Disconnect device object from hardware.

    disconnect(ps5000aDeviceObj);
    delete(ps5000aDeviceObj);

    Connection to PicoScope 5444DMSO with serial number FY971/0003 closed successfully.
    Libraries unloaded successfully.