mccdaq / mcculw

MCC Universal Library Python API for Windows
MIT License
78 stars 30 forks source link

Not able to set bit wise on port FIRSTPORTB/C/CH with ul.d_bit_out() #26

Closed mennodoor closed 3 years ago

mennodoor commented 3 years ago

I have a USB-DIO24/37 and tried out the example code mcculw/examples/console/digital_out.py. It works fine and values are set on pins of FIRSTPORTA. The example code automatically chooses FIRSTPORTA. If I now choose FIRSTPORTB or C (or CH) and try to set a specific bit with the function ul.d_bit_out(), I get the following error:

Traceback (most recent call last):
  File "e:/test_digitalIO_MCC/digital_out_test.py", line 169, in <module>
    TTL_devices[0].on(8)
  File "e:/test_digitalIO_MCC/digital_out_test.py", line 146, in on
    return self.set(channel, 1)
  File "e:/test_digitalIO_MCC/digital_out_test.py", line 132, in set
    ul.d_bit_out(self.board_number, port_obj.type, bit_num, bit_value)
  File "C:\Program Files\Python37\lib\site-packages\mcculw\ul.py", line 2546, in d_bit_out
    _check_err(_cbw.cbDBitOut(board_num, port_type, bit_num, bit_value))
  File "C:\Program Files\Python37\lib\site-packages\mcculw\ul.py", line 6128, in _check_err
    raise ULError(errcode)
mcculw.ul.ULError: Error 11: Invalid digital port number.

Supprisingly, if I use the ul.d_out() function to set the whole byte-array of a port, it works fine for all ports and I measured the pin-values and everything is fine. The ul.d_bit_out() function would be far more convinient though...

jeffreyg3 commented 3 years ago

when using the d_bit_in() or d_bit_out() functions, you MUST always use FIRSTPORTA. Set the bit_num parameter to a value between 0 and 23.

You do need to use the correct port name to configure the port using d_config_port() such as: d_config_port(board_num, DigitalPortType.FIRSTPORTA, DigitalIODirection.Out) d_config_port(board_num, DigitalPortType.FIRSTPORTB, DigitalIODirection.Out) d_config_port(board_num, DigitalPortType.FIRSTPORTCL, DigitalIODirection.Out) d_config_port(board_num, DigitalPortType.FIRSTPORTCH, DigitalIODirection.Out)

When you want to write out to any of the DIO of your USB-DIO24, you would use: d_bit_out(board_num, DigitalPortType.FIRSTPORTA, bit_num, bit_value) where: bit_num is an integer between 0 and 23, bit_value = 0 (off) or 1 (on).

Yes, d_out() works as you stated above.

Notes:

  1. if you want to have a combination of digital inputs and outputs, you still can, just configure the port as needed using d_config_port() with the correct DigitalPortType of FIRSTPORTA/B/CL/CH for input or output. Then when you want to read or write to a bit, you use an integer between 0 and 23 with d_bit_in() or d_bit_out().
  2. For users of other MCC devices having an AUXPORT instead of FIRSTPORTA/B/... the same is true, but you will need to use the AUXPORT (these are normally bit configurable.
  3. if you have a device such as USB-DIO96 series, the same is true for d_bit_in/out() where you exclusively use FIRSTPORTA, but there are many port DigitalPortTypes, and so many more options for bit numbers (0 to 95)
  4. For more information on this please see https://www.mccdaq.com/pdfs/manuals/Mcculw_WebHelp/ULStart.htm
    • select Contents Tab,
    • Hardware Reference
    • Digital Input/Output Hardware (see the table shown here)
    • USB-1024 Series and USB-DIO24 Series
mennodoor commented 3 years ago

Thank you for your fast and helpfull response. I modified the test script to try that, see attachment.

"""
File:                       digital_out.py

Library Call Demonstrated:  mcculw.ul.d_out() and mcculw.d_bit_out()

Purpose:                    Writes to a digital output port.

Demonstration:              Configures the first digital port for output
                            (if necessary) and writes a value to the port and
                            the first bit.

Other Library Calls:        mcculw.ul.d_config_port()
                            mcculw.ul.release_daq_device()

Special Requirements:       Device must have a digital output port
                            or have digital ports programmable as output.
"""
from __future__ import absolute_import, division, print_function
from builtins import *  # @UnusedWildImport

from mcculw import ul
from mcculw.enums import DigitalIODirection
from mcculw.device_info import DaqDeviceInfo

try:
    from console_examples_util import config_first_detected_device
except ImportError:
    from .console_examples_util import config_first_detected_device

def run_example():
    # By default, the example detects and displays all available devices and
    # selects the first device listed. Use the dev_id_list variable to filter
    # detected devices by device ID (see UL documentation for dev ice IDs).
    # If use_device_detection is set to False, the board_num variable needs to
    # match the desired board number configured with Instacal.
    use_device_detection = True
    dev_id_list = []
    board_num = 0

    try:
        if use_device_detection:
            config_first_detected_device(board_num, dev_id_list)

        daq_dev_info = DaqDeviceInfo(board_num)
        if not daq_dev_info.supports_digital_io:
            raise Exception('Error: The DAQ device does not support '
                            'digital I/O')

        print('\nActive DAQ device: ', daq_dev_info.product_name, ' (',
              daq_dev_info.unique_id, ')\n', sep='')

        dio_info = daq_dev_info.get_dio_info()

        # get all ports
        ports = [port for port in dio_info.port_info if port.supports_output]

        # If the port is configurable, configure it for output.
        for port in ports:
            if port.is_port_configurable:
                ul.d_config_port(board_num, port.type, DigitalIODirection.OUT)

        port = ports[0] # get FIRSTPORTA

        # set it to all 0 via byte set
        port_value = 0b00000000

        print('Setting', port.type.name, 'to', port_value)

        # Output the value to the port
        ul.d_out(board_num, port.type, port_value)

        # set it to all 0 via bit set
        for i in range(24):
            bit_num = i
            bit_value = 0
            print('Setting', port.type.name, 'bit', bit_num, 'to', bit_value)

            # Output the value to the bit
            ul.d_bit_out(board_num, port.type, bit_num, bit_value)

        # set every second pin to high
        for i in range(0, 24, 2):
            bit_num = i
            bit_value = 1
            print('Setting', port.type.name, 'bit', bit_num, 'to', bit_value)

            # Output the value to the bit
            ul.d_bit_out(board_num, port.type, bit_num, bit_value)

    except Exception as e:
        print('\n', e)
    finally:
        if use_device_detection:
            ul.release_daq_device(board_num)

if __name__ == '__main__':
    run_example()

The code runs without error, this results in every second pin on LOW and the other ones on HIGH. EXCEPT: The first 4 bits of FIRSTPORTA are all HIGH.

mennodoor commented 3 years ago

Nevermind my last message, all works fine :) Thank you!