Measurement Computing   Easy to Use | Easy to Integrate | Easy to Support catalog banner

Python for Windows USB-QUAD08 Example

Expand / Collapse
 

Python for Windows USB-QUAD08 Example


This is a product specific USB-QUAD08 Python example for Windows. It configures channel 0 for encoder mode and channel 1 for period mode. It uses a fake distance value so as to display encoder position as a +/- distance in inches. The period mode is used to calculate frequency and RPM. To do this, the counts are multiplied by the tick size (20.83nS) then the inverse is taken and multiplied by 60 for RPM. The Python file is attached below as a download.

from __future__ import absolute_import, division, print_function

import time

from builtins import *  # @UnusedWildImport
from time import sleep
from ctypes import cast, POINTER, c_double, c_ushort, c_ulong
from mcculw import ul
from mcculw.enums import ScanOptions, FunctionType, Status
from mcculw.ul import ULError, a_input_mode
from mcculw.enums import InterfaceType
from mcculw.enums import CounterMode
from mcculw.enums import CounterDebounceMode
from mcculw.enums import CounterDebounceTime
from mcculw.enums import CounterEdgeDetection
from mcculw.enums import CounterTickSize


use_device_detection = True


def run_example():
    board_num = 0
    board_index = 0
    find_device = "USB-QUAD08"
    if use_device_detection:
        board_num = -1
        ul.ignore_instacal()
        dev_list = ul.get_daq_device_inventory(InterfaceType.USB)
        if len(dev_list) > 0:
            for device in dev_list:
                if str(device) == find_device:
                    print(f"Found {find_device} board number = {board_index}")
                    print(f"Serial number: {device.unique_id}")
                    print(f"Product type: {hex(device.product_id)}")
                    board_num = board_index
                    ul.create_daq_device(board_num, device)
                board_index = board_index + 1
            if board_num == -1:
                print(f"Device {find_device} not found")
                return
        else:
            print("No devices detected")
            return
    # **********End of Discovery************

    rate = 200
    points_per_channel = 40
    low_chan = 0
    high_chan = 1
    num_chans = 2

    total_count = points_per_channel * num_chans
    half_count = int(total_count / 2)
    # The SCALEDATA option, returns volts instead of A/D counts
    scan_options = ScanOptions.CONTINUOUS | ScanOptions.BACKGROUND | ScanOptions.CTR32BIT

    memhandle = ul.win_buf_alloc_32(total_count)
    buf_data = cast(memhandle, POINTER(c_ulong))

    # Check if the buffer was successfully allocated
    if not memhandle:
        print("Failed to allocate memory.")
        return


    try:
        ul.c_config_scan(board_num,
                         low_chan,
                         CounterMode.ENCODER | CounterMode.ENCODER_MODE_BIT_32,
                         CounterDebounceTime.DEBOUNCE500ns,
                         CounterDebounceMode.TRIGGER_AFTER_STABLE,
                         CounterEdgeDetection.RISING_EDGE,
                         CounterTickSize.TICK20PT83ns,
                         low_chan)

        ul.c_config_scan(board_num,
                         high_chan,
                         CounterMode.PERIOD | CounterMode.PERIOD_MODE_BIT_32,
                         CounterDebounceTime.DEBOUNCE500ns,
                         CounterDebounceMode.TRIGGER_AFTER_STABLE,
                         CounterEdgeDetection.RISING_EDGE,
                         CounterTickSize.TICK20PT83ns,
                         high_chan)

        # tick_size is the amount of time assigned to single count
        tick_size = 0.00000002083
        # distance_per_tick is a distance assigned to single count (arbitrary value for demonstration)
        distance_per_tick = 0.001


        # Start reading the inputs
        ul.c_in_scan(
            board_num, low_chan, high_chan, total_count,
            rate, memhandle, scan_options)

        # Create a format string that aligns the data in columns

        # plus two for curr_index and curr_count
        row_format = "{:8}" * (num_chans)

        # Print the channel name headers
        labels = []
        for ch_num in range(low_chan, high_chan + 1):
            labels.append("CH" + str(ch_num) + "\t")

        print(row_format.format(*labels))

        # boolean flag used to toggle reading upper and lower buffer
        read_lower = True
        # Start updating the displayed values
        status, curr_count, curr_index = ul.get_status(
            board_num, FunctionType.CTRFUNCTION)

        last = 0
        diff = 0
        while status != Status.IDLE and curr_count < 5000:
            # Make sure a data point is available for display.
            if curr_count > 0:
                # curr_index points to the start of the last completed
                # channel scan that was transferred between the board and
                # the data buffer. Display the latest value for each
                # channel.

                # display_data = []
                if (curr_index > half_count) and (read_lower == True):
                    # tranfer lower half of the buffer to buf_data array
                    ul.win_buf_to_array_32(memhandle, buf_data, 0, int(half_count))
                    if buf_data[1] > 0:
                        # assumes one pulse per revolution
                        period = buf_data[1] * tick_size
                        frequency = 1 / period
                        rpm = frequency * 60
                        distance = buf_data[0] * distance_per_tick
                        print('{:.3f} inches\t\t{:.3f} RPM'.format(distance, rpm))
                    read_lower = False

                elif (curr_index < half_count) and (read_lower == False):
                    # transfer upper half the buffer to buf_data array
                    ul.win_buf_to_array_32(memhandle, buf_data, int(half_count), int(half_count))
                    if buf_data[1] > 0:
                        # assumes one pulse per revolution
                        period = buf_data[1] * tick_size
                        frequency = 1 / period
                        rpm = frequency * 60
                        distance = buf_data[0] * distance_per_tick
                        print('{:.3f} inches\t\t{:.3f} RPM'.format(distance, rpm))
                    read_lower = True

            sleep(0.1)
            status, curr_count, curr_index = ul.get_status(
                board_num, FunctionType.CTRFUNCTION)

        # Stop the background operation (this is required even if the
        # scan completes successfully)
        ul.stop_background(board_num, FunctionType.AIFUNCTION)

        print("Scan completed successfully.")
    except ULError as e:
        print("UL error\n", e)
    finally:
        # Free the buffer in a finally block to prevent errors from causing
        # a memory leak.
        ul.win_buf_free(memhandle)

        if use_device_detection:
            ul.release_daq_device(board_num)


if __name__ == '__main__':
    run_example()



Rate this Article:

Attachments


C_ConfigScanQuad08.py C_ConfigScanQuad08.py (6.53 KB, 11 views)

Add Your Comments


For comments email TechSupport@mccdaq.com.

Details
Article ID: 50848

Last Modified:9/9/2021 10:11:45 AM

Article has been viewed 79 times.

Options