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

Python for Windows USB-CTR04 Simultaneous Operation

Expand / Collapse
 

Python for Windows USB-CTR04 Simultaneous Operation


The following Python for Windows example demonstrates device discovery and the ability for the USB-CTR04 to sample the digital port at the same rate as the counter channels. 

This is a one-shot acquisition not continuous that uses ul.daq_in_scan() instead of ul.c_in_scan(). Using One-shot or finite mode (default), the ul.daq_in_scan() function will block until the data has been capture to the buffer.

The program configures two counter channels, the first counter is set to range counting. The output line is enabled and is control by the output registers. The second counter is configured to measure period. The idea is that the first counter divides the incoming frequency by 100 and the second counter measures it. For a test signal, the TMR0 line (frequency pulse output) is use. Recommended connection are TMR0-->C0IN and C0O-->C1IN

To install the Python for Windows support, copy the following URL into your browser and follow the instructions provided.
https://github.com/mccdaq/mcculw

This example was built using Python 3.8.5 and PyCharm. The code module is provided via a download link at the end of this article.





"""
File:                       daq_in_scan_usb_1800.py

Library Call Demonstrated:  mcculw.ul.daq_in_scan()

Purpose:                    Synchronously scans digital port and counters
                            in the foreground using USB-CTR04 64-bit support.

Demonstration:              Collects data from digital port, and two counter inputs.

Other Library Calls:        mcculw.ul.ignore_instacal()
                            mcculw.ul.get_daq_device_inventory()
                            mcculw.ul.create_daq_device()
                            mcculw.ul.win_buf_alloc_64()
                            mcculw.ul.c_config_scan()
                            mcculw.ul.pulse_out_start()
                            mcculw.ul.daq_in_scan()
                            mcculw.ul.pulse_out_stop()
                            mcculw.ul.win_buf_free()
                            mcculw.ul.release_daq_device()

Special Requirements:       This examples filters on the USB-1808 Series.
"""
from __future__ import absolute_import, division, print_function
from builtins import *  # @UnusedWildImport

from ctypes import cast, POINTER, c_double, c_ulonglong, c_ubyte, c_ushort

from mcculw import ul
from mcculw.enums import ScanOptions, ChannelType, ULRange, DigitalPortType
from mcculw.enums import InterfaceType, FunctionType
from mcculw.enums import CounterMode, CounterDebounceMode, CounterDebounceTime
from mcculw.enums import CounterEdgeDetection, CounterTickSize, CounterRegister
import ctypes


def run_example():
    use_device_detection = True

    memhandle = None

    try:
        # **********Begin Device Discovery************
        board_num = 0
        board_index = 0
        find_device = "USB-CTR04"
        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)
                        break
                    board_index = board_index + 1
                if board_num == -1:
                    print(f"Device {find_device} not found")
            else:
                print("No devices detected")

        # **********End of Device Discovery************

        # configure counter to count from x to x+n with active output
        ctr0_mode = CounterMode.TOTALIZE | CounterMode.RANGE_LIMIT_ON | CounterMode.OUTPUT_ON
        if board_num > -1:
            ul.c_config_scan(board_num,
                             0,
                             ctr0_mode,
                             CounterDebounceTime.DEBOUNCE_NONE,
                             CounterDebounceMode.TRIGGER_AFTER_STABLE,
                             CounterEdgeDetection.RISING_EDGE,
                             CounterTickSize.TICK20PT83ns,
                             0)
            # divide by 100
            ul.c_load_32(board_num, CounterRegister.MINLIMITREG0, 0)
            ul.c_load_32(board_num, CounterRegister.MAXLIMITREG0, 99)

            # Output will toggle high at zero and low at 49 50% duty cycle
            ul.c_load_32(board_num, CounterRegister.OUTPUTVAL0REG0, 0)
            ul.c_load_32(board_num, CounterRegister.OUTPUTVAL1REG0, 49)

            # measure period of counter 0 output; connect C0O to C1IN.
            ul.c_config_scan(board_num,
                             1,
                             CounterMode.PERIOD,
                             CounterDebounceTime.DEBOUNCE500ns,
                             CounterDebounceMode.TRIGGER_AFTER_STABLE,
                             CounterEdgeDetection.RISING_EDGE,
                             CounterTickSize.TICK20PT83ns,
                             0)

            # tick_size is the amount of time assigned to single count
            tick_size = 0.000000020830

            # Create the daq_in_scan channel configuration lists
            chan_list = []
            chan_type_list = []
            gain_list = []

            chan_list.append(0)
            chan_type_list.append(ChannelType.CTRBANK0)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(0)
            chan_type_list.append(ChannelType.CTRBANK1)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(0)
            chan_type_list.append(ChannelType.CTRBANK2)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(0)
            chan_type_list.append(ChannelType.CTRBANK3)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(1)
            chan_type_list.append(ChannelType.CTRBANK0)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(1)
            chan_type_list.append(ChannelType.CTRBANK1)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(1)
            chan_type_list.append(ChannelType.CTRBANK2)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(1)
            chan_type_list.append(ChannelType.CTRBANK3)
            gain_list.append(ULRange.NOTUSED)

            # The digital port is 8-bits but it's
            # treated as a 16-bit register; use PADZERO as a
            # dummy place holder to for the other 48-bits

            chan_list.append(DigitalPortType.AUXPORT)
            chan_type_list.append(ChannelType.DIGITAL8)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(DigitalPortType.AUXPORT)
            chan_type_list.append(ChannelType.PADZERO)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(DigitalPortType.AUXPORT)
            chan_type_list.append(ChannelType.PADZERO)
            gain_list.append(ULRange.NOTUSED)

            chan_list.append(DigitalPortType.AUXPORT)
            chan_type_list.append(ChannelType.PADZERO)
            gain_list.append(ULRange.NOTUSED)

            timer_num0 = 0
            frequency = 20000
            duty_cycle = 0.5

            # Start the pulse timer output (optional parameters omitted)
            # this is used as a test signal
            # connect TMR0 to the C0IN
            # counter 0 will divide this by its range limit amount
            actual_frequency, actual_duty_cycle, _ = ul.pulse_out_start(
                board_num, timer_num0, frequency, duty_cycle)

            num_channels = len(chan_list)   # num of 16 bit locations
            num_64_bit_channels = 3         # num of 64-bit channel
            rate = 2000
            num_rows = 384   # Scans, must be multiple of num_64_bit_channels
            total_count = num_channels * num_rows   # 12 * 96

            # Allocate memory for the scan and cast it to a ctypes array pointer
            # The default register size is 64 bits
            memhandle = ul.win_buf_alloc_64(total_count)
            # Check if the buffer was successfully allocated
            if not memhandle:
                raise Exception('Error: Failed to allocate memory')
            buffer = cast(memhandle, POINTER(c_ulonglong))

            try:
                # Start the scan
                ul.daq_in_scan(board_num,
                               chan_list,
                               chan_type_list,
                               gain_list,
                               num_channels,
                               rate,
                               0,
                               total_count,
                               memhandle,
                               ScanOptions.DEFAULTIO)

            except Exception as e:
                print('daq_in_scan error >>>', e)
            print('Scan completed successfully.')

            # Start updating the displayed values
            status, curr_count, curr_index = ul.get_status(
                board_num, FunctionType.DAQIFUNCTION)
            print(f"Status {status} Count {curr_count} Index {curr_index}")

            # stop TMR0 and TMR1
            ul.pulse_out_stop(board_num, timer_num0)


            print("Index\tCOIN\tC1IN\tDI")

            # Print the data loop - digital port is only 8-bit so use mask to zero out
            # upper bits
            index = 0
            mask = 0xFF
            for i in range(num_rows):
                if buffer[index + 1] > 0:
                    # if count is not zero calculate frequency
                    f = 1 / (buffer[index + 1] * tick_size)
                else:
                    f = 0.01
                print(f"{i:d}\t{buffer[index]:d}\t{f:5.2f} Hz \t{(buffer[index+2] & mask):d}")
                index += num_64_bit_channels

    except Exception as e:
        print('\n', e)
    finally:
        if memhandle:
            # Free the buffer in a finally block to prevent 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


daq_in_scan_usb_ctr.py daq_in_scan_usb_ctr.py (9.28 KB, 219 views)

Add Your Comments


For comments email [email protected].

Details
Article ID: 50856

Last Modified:10/28/2021 7:54:06 AM

Article has been viewed 2,541 times.

Options