Exemple #1
0
    def firmware_version(self):
        """
        Read the board firmware and bootloader versions.

        Returns:
            namedtuple: a namedtuple containing the following field names

            * **version** (string): The firmware version, i.e "1.03".
            * **bootloader_version** (string): The bootloader version,
              i.e "1.01".

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        version = c_ushort()
        boot_version = c_ushort()
        if (self._lib.mcc118_firmware_version(self._address, byref(version),
                                              byref(boot_version)) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        version_str = "{0:X}.{1:02X}".format(version.value >> 8,
                                             version.value & 0x00FF)
        boot_str = "{0:X}.{1:02X}".format(boot_version.value >> 8,
                                          boot_version.value & 0x00FF)
        version_info = namedtuple('MCC118VersionInfo',
                                  ['version', 'bootloader_version'])
        return version_info(version=version_str, bootloader_version=boot_str)
Exemple #2
0
    def tc_type_read(self, channel):
        """
        Read the thermocouple type for a channel.

        Reads the current thermocouple type for the specified channel. The type
        is one of :py:class:`TcTypes` and the board will default to all channels
        disable (set to :py:const:`TcTypes.DISABLED`) when it is first opened.

        Args:
            channel (int): The analog input channel number, 0-3.

        Returns
            int: The thermocouple type.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        type_value = c_ubyte()
        if (self._lib.mcc134_tc_type_read(self._address, channel,
                                          byref(type_value)) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return type_value.value
Exemple #3
0
    def calibration_coefficient_read(self, a_in_range):
        """
        Read the calibration coefficients for a specified input range.

        The coefficients are applied in the library as: ::

            calibrated_ADC_code = (raw_ADC_code * slope) + offset

        Args:
            a_in_range (:py:class:`AnalogInputRange`): The input range.

        Returns:
            namedtuple: A namedtuple containing the following field names:

            * **slope** (float): The slope.
            * **offset** (float): The offset.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        slope = c_double()
        offset = c_double()
        if (self._lib.mcc128_calibration_coefficient_read(
                self._address, a_in_range, byref(slope),
                byref(offset)) != self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        cal_info = namedtuple('MCC128CalInfo', ['slope', 'offset'])
        return cal_info(
            slope=slope.value,
            offset=offset.value)
Exemple #4
0
    def calibration_coefficient_write(self, channel, slope, offset):
        """
        Temporarily write the calibration coefficients for a single channel.

        The user can apply their own calibration coefficients by writing to
        these values. The values will reset to the factory values from the
        EEPROM whenever the class is initialized.  This function will fail and
        raise a HatError exception if a scan is active when it is called.

        The coefficients are applied in the library as: ::

            calibrated_ADC_code = (raw_ADC_code * slope) + offset

        Args:
            slope (float): The new slope value.
            offset (float): The new offset value.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        if (self._lib.mcc118_calibration_coefficient_write(
                self._address, channel, slope, offset) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return
Exemple #5
0
    def calibration_coefficient_read(self, channel):
        """
        Read the calibration coefficients for a single channel.

        The coefficients are applied in the library as: ::

            calibrated_ADC_code = (raw_ADC_code * slope) + offset

        Returns:
            namedtuple: a namedtuple containing the following field names

            * **slope** (float): The slope.
            * **offset** (float): The offset.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        slope = c_double()
        offset = c_double()
        if (self._lib.mcc118_calibration_coefficient_read(
                self._address, channel, byref(slope), byref(offset)) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        cal_info = namedtuple('MCC118CalInfo', ['slope', 'offset'])
        return cal_info(slope=slope.value, offset=offset.value)
Exemple #6
0
    def trigger_mode(self, mode):
        """
        Set the external trigger input mode.

        The available modes are:

        * :py:const:`TriggerModes.RISING_EDGE`: Start the scan when the TRIG
          input transitions from low to high.
        * :py:const:`TriggerModes.FALLING_EDGE`: Start the scan when the TRIG
          input transitions from high to low.
        * :py:const:`TriggerModes.ACTIVE_HIGH`: Start the scan when the TRIG
          input is high.
        * :py:const:`TriggerModes.ACTIVE_LOW`: Start the scan when the TRIG
          input is low.

        Args:
            mode (:py:class:`TriggerModes`): The trigger mode.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        if (self._lib.mcc118_trigger_mode(self._address, mode) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return
Exemple #7
0
    def a_in_range_write(self, a_in_range):
        """
        This sets the analog input range to one of the valid values:

        * :py:const:`AnalogInputRange.BIP_10V`: +/- 10V range
        * :py:const:`AnalogInputRange.BIP_5V`: +/- 5V range
        * :py:const:`AnalogInputRange.BIP_2V`: +/- 2V range
        * :py:const:`AnalogInputRange.BIP_1V`: +/- 1V range

        Args:
            a_in_range (:py:class:`AnalogInputRange`): The input range.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        result = self._lib.mcc128_a_in_range_write(self._address, a_in_range)

        if result == self._RESULT_BAD_PARAMETER:
            raise ValueError("Invalid mode argument.")
        elif result == self._RESULT_BUSY:
            raise HatError(self._address,
                           "The range cannot be changed while a scan is "
                           "running.")
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response {}.".format(
                result))
        return
Exemple #8
0
    def a_in_mode_write(self, a_in_mode):
        """
        This sets the analog input mode to one of the valid values:

        * :py:const:`AnalogInputMode.SE`: Single-ended (8 inputs relative to
          ground.)
        * :py:const:`AnalogInputMode.DIFF`: Differential (4 channels with
          positive and negative inputs.)

        Args:
            a_in_mode (:py:class:`AnalogInputMode`): The input mode.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        result = self._lib.mcc128_a_in_mode_write(self._address, a_in_mode)

        if result == self._RESULT_BAD_PARAMETER:
            raise ValueError("Invalid mode argument.")
        elif result == self._RESULT_BUSY:
            raise HatError(self._address,
                           "The mode cannot be changed while "
                           "a scan is running.")
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response {}.".format(
                result))
        return
Exemple #9
0
    def cjc_read(self, channel):
        """
        Read the cold junction compensation temperature for a specified channel.

        Reads the cold junction sensor temperature for the specified
        thermocouple terminal. The library automatically performs cold junction
        compensation, so this function is only needed for informational use or
        if you want to perform your own compensation. The temperature is
        returned in degress C.

        Args:
            channel (int): The analog input channel number, 0-3.

        Returns:
            float: The read value.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
            ValueError: the channel number is invalid.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if channel not in range(self._AIN_NUM_CHANNELS):
            raise ValueError("Invalid channel {0}. Must be 0-{1}.".format(
                channel, self._AIN_NUM_CHANNELS - 1))

        data_value = c_double()

        if (self._lib.mcc134_cjc_read(self._address, channel,
                                      byref(data_value)) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return data_value.value
Exemple #10
0
    def a_in_scan_buffer_size(self):
        """
        Read the internal scan data buffer size.

        An internal data buffer is allocated for the scan when
        :py:func:`a_in_scan_start` is called. This function returns the total
        size of that buffer in samples.

        Returns:
            int: the buffer size in samples

        Raises:
            HatError: the board is not initialized or no scan buffer is
                allocated (a scan is not active).
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        data_value = c_ulong()

        result = self._lib.mcc118_a_in_scan_buffer_size(
            self._address, byref(data_value))

        if result == self._RESULT_RESOURCE_UNAVAIL:
            raise HatError(self._address, "No scan is active.")
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address,
                           "Incorrect response {}.".format(result))
        return data_value.value
Exemple #11
0
    def t_in_read(self, channel):
        """
        Read a thermocouple input channel temperature.

        The channel must be enabled with :py:func:`tc_type_write` or the
        method will raise a ValueError exception.

        This method returns immediately with the most recent temperature reading
        for the specified channel. When a board is open, the library will read
        each channel approximately once per second. There will be a delay when
        the board is first opened because the read thread has to read the cold
        junction compensation sensors and thermocouple inputs before it can
        return the first value.

        The method returns the value as degrees Celsius. The temperature value
        can have some special values for abnormal conditions:

            - :py:const:`mcc134.OPEN_TC_VALUE` if an open thermocouple is
              detected.
            - :py:const:`mcc134.OVERRANGE_TC_VALUE` if a value outside valid
              thermocouple voltage is detected.
            - :py:const:`mcc134.COMMON_MODE_TC_VALUE` if a common-mode voltage
              error is detected. This occurs when thermocouples on the same MCC
              134 are at different voltages.

        Args:
            channel (int): The analog input channel number, 0-3.

        Returns:
            float: The thermocouple temperature.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
            ValueError: the channel number is invalid or the channel is
                disabled.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if channel not in range(self._AIN_NUM_CHANNELS):
            raise ValueError("Invalid channel {0}. Must be 0-{1}.".format(
                channel, self._AIN_NUM_CHANNELS - 1))

        temp = c_double()

        result = self._lib.mcc134_t_in_read(self._address, channel,
                                            byref(temp))
        if result == self._RESULT_BAD_PARAMETER:
            raise ValueError(
                "Invalid channel {}, the channel must be enabled.".format(
                    channel))
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response.")
        return temp.value
Exemple #12
0
    def a_in_read(self, channel, options=OptionFlags.DEFAULT):
        """
        Read an analog input channel and return the value.

        The channel must be enabled with :py:func:`tc_type_write` or the
        method will raise a ValueError exception.

        The returned voltage can have a special value to indicate abnormal
        conditions:

        * :py:const:`mcc134.COMMON_MODE_TC_VALUE` if a common-mode voltage
          error is detected. This occurs when thermocouples on the same MCC
          134 are at different voltages.

        **options** is an ORed combination of OptionFlags. Valid flags for this
        method are:

        * :py:const:`OptionFlags.DEFAULT`: Return a calibrated voltage value.
          Any other flags will override DEFAULT behavior.
        * :py:const:`OptionFlags.NOSCALEDATA`: Return an ADC code (a value
          between -8,388,608 and 8,388,607) rather than voltage.
        * :py:const:`OptionFlags.NOCALIBRATEDATA`: Return data without the
          calibration factors applied.

        Args:
            channel (int): The analog input channel number, 0-3.
            options (int): ORed combination of :py:class:`OptionFlags`,
                :py:const:`OptionFlags.DEFAULT` if unspecified.

        Returns:
            float: The read value.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
            ValueError: the channel number is invalid.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if channel not in range(self._AIN_NUM_CHANNELS):
            raise ValueError("Invalid channel {0}. Must be 0-{1}.".format(
                channel, self._AIN_NUM_CHANNELS - 1))

        data_value = c_double()

        result = self._lib.mcc134_a_in_read(self._address, channel, options,
                                            byref(data_value))
        if result == self._RESULT_BAD_PARAMETER:
            raise ValueError(
                "Invalid channel {}, the channel must be enabled.".format(
                    channel))
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response.")
        return data_value.value
Exemple #13
0
    def a_in_scan_status(self):
        """
        Read scan status and number of available samples per channel.

        The analog input scan is started with :py:func:`a_in_scan_start` and
        runs in the background.  This function reads the status of that
        background scan and the number of samples per channel available in
        the scan thread buffer.

        Returns:
            namedtuple: a namedtuple containing the following field names:

            * **running** (bool): True if the scan is running, False if it has
              stopped or completed.
            * **hardware_overrun** (bool): True if the hardware could not
              acquire and unload samples fast enough and data was lost.
            * **buffer_overrun** (bool): True if the background scan buffer was
              not read fast enough and data was lost.
            * **triggered** (bool): True if the trigger conditions have been met
              and data acquisition started.
            * **samples_available** (int): The number of samples per channel
              currently in the scan buffer.

        Raises:
            HatError: A scan is not active, the board is not initialized, does
                not respond, or responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        status = c_ushort(0)
        samples_available = c_ulong(0)

        result = self._lib.mcc118_a_in_scan_status(self._address,
                                                   byref(status),
                                                   byref(samples_available))

        if result == self._RESULT_RESOURCE_UNAVAIL:
            raise HatError(self._address, "Scan not active.")
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address,
                           "Incorrect response {}.".format(result))

        scan_status = namedtuple('MCC118ScanStatus', [
            'running', 'hardware_overrun', 'buffer_overrun', 'triggered',
            'samples_available'
        ])
        return scan_status(
            running=(status.value & self._STATUS_RUNNING) != 0,
            hardware_overrun=(status.value & self._STATUS_HW_OVERRUN) != 0,
            buffer_overrun=(status.value & self._STATUS_BUFFER_OVERRUN) != 0,
            triggered=(status.value & self._STATUS_TRIGGERED) != 0,
            samples_available=samples_available.value)
Exemple #14
0
    def a_in_scan_actual_rate(self, channel_count, sample_rate_per_channel):
        """
        Read the actual sample rate per channel for a requested sample rate.

        The internal scan clock is generated from a 16 MHz clock source so only
        discrete frequency steps can be achieved.  This function will return the
        actual rate for a requested channel count and rate setting.

        This function does not perform any actions with a board, it simply
        calculates the rate.

        Args:
            channel_count (int): The number of channels in the scan, 1-8.
            sample_rate_per_channel (float): The desired per-channel rate of the
                internal sampling clock, max 100,000.0.

        Returns:
            float: the actual sample rate

        Raises:
            ValueError: a scan argument is invalid.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        data_value = c_double()

        if (self._lib.mcc118_a_in_scan_actual_rate(
                channel_count, sample_rate_per_channel, byref(data_value)) !=
                self._RESULT_SUCCESS):
            raise ValueError(
                "The specified parameters are invalid or outside the device "
                "capabilities.")
        return data_value.value
Exemple #15
0
    def a_in_read(self, channel, options=OptionFlags.DEFAULT):
        """
        Perform a single reading of an analog input channel and return the
        value.

        **options** is an ORed combination of OptionFlags. Valid flags for this
        method are:

        * :py:const:`OptionFlags.DEFAULT`: Return a calibrated voltage value.
          Any other flags will override DEFAULT behavior.
        * :py:const:`OptionFlags.NOSCALEDATA`: Return an ADC code (a value
          between 0 and 4095) rather than voltage.
        * :py:const:`OptionFlags.NOCALIBRATEDATA`: Return data without the
          calibration factors applied.

        Args:
            channel (int): The analog input channel number, 0-7.
            options (int): ORed combination of :py:class:`OptionFlags`,
                :py:const:`OptionFlags.DEFAULT` if unspecified.

        Returns:
            float: the read value

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
            ValueError: the channel number is invalid.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if channel not in range(self._AIN_NUM_CHANNELS):
            raise ValueError("Invalid channel {0}. Must be 0-{1}.".format(
                channel, self._AIN_NUM_CHANNELS - 1))

        data_value = c_double()

        if (self._lib.mcc118_a_in_read(self._address, channel, options,
                                       byref(data_value)) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return data_value.value
Exemple #16
0
    def a_in_read(self, channel, options=OptionFlags.DEFAULT):
        """
        Perform a single reading of an analog input channel and return the
        value.

        **options** is an ORed combination of OptionFlags. Valid flags for this
        method are:

        * :py:const:`OptionFlags.DEFAULT`: Return a calibrated voltage value.
          Any other flags will override DEFAULT behavior.
        * :py:const:`OptionFlags.NOSCALEDATA`: Return an ADC code (a value
          between 0 and 65535) rather than voltage.
        * :py:const:`OptionFlags.NOCALIBRATEDATA`: Return data without the
          calibration factors applied.

        Args:
            channel (int): The analog input channel number, 0-7.
            options (int): ORed combination of :py:class:`OptionFlags`,
                :py:const:`OptionFlags.DEFAULT` if unspecified.

        Returns:
            float: The read value.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        data_value = c_double()

        result = self._lib.mcc128_a_in_read(
            self._address, channel, options, byref(data_value))
        if result == self._RESULT_BUSY:
            raise HatError(self._address,
                           "The input cannot be read during a scan.")
        elif result == self._RESULT_BAD_PARAMETER:
            raise HatError(self._address, "Invalid argument.")
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response.")
        return data_value.value
Exemple #17
0
    def blink_led(self, count):
        """
        Blink the MCC 118 LED.

        Setting count to 0 will cause the LED to blink continuously until
        blink_led() is called again with a non-zero count.

        Args:
            count (int): The number of times to blink (max 255).

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        if (self._lib.mcc118_blink_led(self._address, count) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return
Exemple #18
0
    def a_in_range_read(self):
        """
        Read the analog input range.

        Reads the current analog input range.

        Returns:
            :py:class:`AnalogInputRange`: The current analog input range.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        a_in_range = c_ubyte()
        if (self._lib.mcc128_a_in_range_read(self._address, byref(a_in_range))
                != self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return a_in_range.value
Exemple #19
0
    def a_in_scan_cleanup(self):
        """
        Free analog input scan resources after the scan is complete.

        This will free the scan buffer and other resources used by the
        background scan and make it possible to start another scan with
        :py:func:`a_in_scan_start`.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if (self._lib.mcc118_a_in_scan_cleanup(self._address) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")

        return
Exemple #20
0
    def calibration_date(self):
        """
        Read the calibration date.

        Returns:
            string: The calibration date in the format "YYYY-MM-DD".

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        # create string to hold the result
        my_buffer = create_string_buffer(11)
        if (self._lib.mcc118_calibration_date(self._address, my_buffer) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        my_date = my_buffer.value.decode('ascii')
        return my_date
Exemple #21
0
    def a_in_scan_stop(self):
        """
        Stops an analog input scan.

        The device stops acquiring data immediately. The scan data that has been
        read into the scan buffer is available until
        :py:func:`a_in_scan_cleanup` is called.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if (self._lib.mcc118_a_in_scan_stop(self._address) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")

        return
Exemple #22
0
    def serial(self):
        """
        Read the serial number.

        Returns:
            string: The serial number.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        # create string to hold the result
        my_buffer = create_string_buffer(9)
        if (self._lib.mcc118_serial(self._address, my_buffer) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        my_serial = my_buffer.value.decode('ascii')
        return my_serial
Exemple #23
0
    def update_interval_read(self):
        """
        Read the temperature update interval.

        Reads the library temperature update rate in seconds.

        Returns
            int: The update interval.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        interval = c_ubyte()
        if (self._lib.mcc134_update_interval_read(
                self._address, byref(interval)) != self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return interval.value
Exemple #24
0
    def test_trigger(self):
        """
        Test the external trigger pin (TRIG).

        This value read at the pin for input testing.

        Returns:
            int: The value read at the TRIG pin (0 or 1.)

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        data_value = c_ubyte()
        result = self._lib.mcc128_test_trigger(self._address, byref(data_value))
        if result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response.")
        return data_value.value
Exemple #25
0
    def test_clock(self, mode):
        """
        Test the sample clock pin (CLK).

        This function exercises the CLK pin in output mode and returns the value
        read at the pin for input testing.  Return the mode to input after
        testing the pin.

        Args:
            mode (int): The CLK pin mode

                * 0 = input
                * 1 = output low
                * 2 = output high
                * 3 = output 1 kHz square wave

        Returns:
            int: the value read at the CLK pin after applying the mode (0 or 1).

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
            ValueError: the mode is invalid.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        if mode not in range(4):
            raise ValueError("Invalid mode. Must be 0-3.")

        data_value = c_ubyte()
        result = self._lib.mcc118_test_clock(self._address, mode,
                                             byref(data_value))
        if result == self._RESULT_BUSY:
            raise HatError(self._address,
                           "Cannot test the CLK pin while a scan is running.")
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address, "Incorrect response.")
        return data_value.value
Exemple #26
0
    def update_interval_write(self, interval):
        """
        Write the temperature update interval.

        Tells the MCC 134 library how often to update temperatures, with the
        interval specified in seconds.  The library defaults to updating every
        second, but you may increase this interval if you do not plan to call
        :py:func:`t_in_read` very often. This will reduce the load on shared
        resources for other DAQ HATs.

        Args:
            interval (int): The interval in seconds, 1 - 255.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        if (self._lib.mcc134_update_interval_write(self._address, interval) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return
Exemple #27
0
    def tc_type_write(self, channel, tc_type):
        """
        Write the thermocouple type for a channel.

        Enables a channel and tells the library what thermocouple type is
        connected to the channel. This is needed for correct temperature
        calculations. The type is one of :py:class:`TcTypes` and the board will
        default to all channels disabled (set to :py:const:`TcTypes.DISABLED`)
        when it is first opened.

        Args:
            channel (int): The analog input channel number, 0-3.
            tc_type (:py:class:`TcTypes`): The thermocouple type.

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")
        if (self._lib.mcc134_tc_type_write(self._address, channel, tc_type) !=
                self._RESULT_SUCCESS):
            raise HatError(self._address, "Incorrect response.")
        return
Exemple #28
0
    def a_in_scan_channel_count(self):
        """
        Read the number of channels in the current analog input scan.

        Returns:
            int: the number of channels (0 if no scan is active, 1-8 otherwise)

        Raises:
            HatError: the board is not initialized, does not respond, or
                responds incorrectly.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        num_channels = self._lib.mcc118_a_in_scan_channel_count(self._address)
        return num_channels
Exemple #29
0
    def a_in_scan_read_numpy(self, samples_per_channel, timeout):
        # pylint: disable=too-many-locals
        """
        Read scan status and data (as a NumPy array).

        This function is similar to :py:func:`a_in_scan_read` except that the
        *data* key in the returned namedtuple is a NumPy array of float64 values
        and may be used directly with NumPy functions.

        Args:
            samples_per_channel (int): The number of samples per channel to read
                from the scan buffer.  Specify a negative number to read all
                available samples or 0 to only read the scan status and return
                no data.
            timeout (float): The amount of time in seconds to wait for the
                samples to be read.  Specify a negative number to wait
                indefinitely, or 0 to return immediately with the samples that
                are already in the scan buffer.  If the timeout is met and the
                specified number of samples have not been read, then the
                function will return with the amount that has been read and the
                timeout status set.

        Returns:
            namedtuple: a namedtuple containing the following field names:

            * **running** (bool): True if the scan is running, False if it has
              stopped or completed.
            * **hardware_overrun** (bool): True if the hardware could not
              acquire and unload samples fast enough and data was lost.
            * **buffer_overrun** (bool): True if the background scan buffer was
              not read fast enough and data was lost.
            * **triggered** (bool): True if the trigger conditions have been met
              and data acquisition started.
            * **timeout** (bool): True if the timeout time expired before the
              specified number of samples were read.
            * **data** (NumPy array of float64): The data that was read from the
              scan buffer.

        Raises:
            HatError: A scan is not active, the board is not initialized, does
                not respond, or responds incorrectly.
            ValueError: Incorrect argument.
        """
        try:
            import numpy
            from numpy.ctypeslib import ndpointer
        except ImportError:
            raise

        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        self._lib.mcc118_a_in_scan_read.argtypes = [
            c_ubyte,
            POINTER(c_ushort), c_long, c_double,
            ndpointer(c_double, flags="C_CONTIGUOUS"), c_ulong,
            POINTER(c_ulong)
        ]

        num_channels = self._lib.mcc118_a_in_scan_channel_count(self._address)
        samples_read_per_channel = c_ulong()
        status = c_ushort()
        timed_out = False
        samples_to_read = 0

        if samples_per_channel < 0:
            # read all available data

            # first, get the number of available samples
            samples_available = c_ulong(0)
            result = self._lib.mcc118_a_in_scan_status(
                self._address, byref(status), byref(samples_available))

            if result != self._RESULT_SUCCESS:
                raise HatError(self._address,
                               "Incorrect response {}.".format(result))

            # allocate a buffer large enough for all the data
            samples_to_read = samples_available.value
            buffer_size = samples_available.value * num_channels
            data_buffer = numpy.empty(buffer_size, dtype=numpy.float64)
        elif samples_per_channel == 0:
            # only read the status
            samples_to_read = 0
            buffer_size = 0
            data_buffer = None
        elif samples_per_channel > 0:
            # read the specified number of samples
            samples_to_read = samples_per_channel
            # create a C buffer for the read
            buffer_size = samples_per_channel * num_channels
            data_buffer = numpy.empty(buffer_size, dtype=numpy.float64)
        else:
            # invalid samples_per_channel
            raise ValueError(
                "Invalid samples_per_channel {}.".format(samples_per_channel))

        result = self._lib.mcc118_a_in_scan_read(
            self._address, byref(status), samples_to_read, timeout,
            data_buffer, buffer_size, byref(samples_read_per_channel))

        if result == self._RESULT_BAD_PARAMETER:
            raise ValueError("Invalid parameter.")
        elif result == self._RESULT_RESOURCE_UNAVAIL:
            raise HatError(self._address, "Scan not active.")
        elif result == self._RESULT_TIMEOUT:
            timed_out = True
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address,
                           "Incorrect response {}.".format(result))

        total_read = samples_read_per_channel.value * num_channels

        if total_read < buffer_size:
            data_buffer = numpy.resize(data_buffer, (total_read, ))

        scan_status = namedtuple('MCC118ScanRead', [
            'running', 'hardware_overrun', 'buffer_overrun', 'triggered',
            'timeout', 'data'
        ])
        return scan_status(
            running=(status.value & self._STATUS_RUNNING) != 0,
            hardware_overrun=(status.value & self._STATUS_HW_OVERRUN) != 0,
            buffer_overrun=(status.value & self._STATUS_BUFFER_OVERRUN) != 0,
            triggered=(status.value & self._STATUS_TRIGGERED) != 0,
            timeout=timed_out,
            data=data_buffer)
Exemple #30
0
    def a_in_scan_read(self, samples_per_channel, timeout):
        # pylint: disable=too-many-locals
        """
        Read scan status and data (as a list).

        The analog input scan is started with :py:func:`a_in_scan_start` and
        runs in the background.  This function reads the status of that
        background scan and optionally reads sampled data from the scan buffer.

        Args:
            samples_per_channel (int): The number of samples per channel to read
                from the scan buffer. Specify a negative number to return all
                available samples immediately and ignore **timeout** or 0 to
                only read the scan status and return no data.
            timeout (float): The amount of time in seconds to wait for the
                samples to be read. Specify a negative number to wait
                indefinitely, or 0 to return immediately with the samples that
                are already in the scan buffer (up to **samples_per_channel**.)
                If the timeout is met and the specified number of samples have
                not been read, then the function will return all the available
                samples and the timeout status set.

        Returns:
            namedtuple: a namedtuple containing the following field names:

            * **running** (bool): True if the scan is running, False if it has
              stopped or completed.
            * **hardware_overrun** (bool): True if the hardware could not
              acquire and unload samples fast enough and data was lost.
            * **buffer_overrun** (bool): True if the background scan buffer was
              not read fast enough and data was lost.
            * **triggered** (bool): True if the trigger conditions have been met
              and data acquisition started.
            * **timeout** (bool): True if the timeout time expired before the
              specified number of samples were read.
            * **data** (list of float): The data that was read from the scan
              buffer.

        Raises:
            HatError: A scan is not active, the board is not initialized, does
                not respond, or responds incorrectly.
            ValueError: Incorrect argument.
        """
        if not self._initialized:
            raise HatError(self._address, "Not initialized.")

        num_channels = self._lib.mcc118_a_in_scan_channel_count(self._address)

        self._lib.mcc118_a_in_scan_read.argtypes = [
            c_ubyte,
            POINTER(c_ushort), c_long, c_double,
            POINTER(c_double), c_ulong,
            POINTER(c_ulong)
        ]

        samples_read_per_channel = c_ulong(0)
        samples_to_read = 0
        status = c_ushort(0)
        timed_out = False

        if samples_per_channel < 0:
            # read all available data

            # first, get the number of available samples
            samples_available = c_ulong(0)
            result = self._lib.mcc118_a_in_scan_status(
                self._address, byref(status), byref(samples_available))

            if result != self._RESULT_SUCCESS:
                raise HatError(self._address,
                               "Incorrect response {}.".format(result))

            # allocate a buffer large enough for all the data
            samples_to_read = samples_available.value
            buffer_size = samples_available.value * num_channels
            data_buffer = (c_double * buffer_size)()
        elif samples_per_channel == 0:
            # only read the status
            samples_to_read = 0
            buffer_size = 0
            data_buffer = None
        elif samples_per_channel > 0:
            # read the specified number of samples
            samples_to_read = samples_per_channel
            # create a C buffer for the read
            buffer_size = samples_per_channel * num_channels
            data_buffer = (c_double * buffer_size)()
        else:
            # invalid samples_per_channel
            raise ValueError(
                "Invalid samples_per_channel {}.".format(samples_per_channel))

        result = self._lib.mcc118_a_in_scan_read(
            self._address, byref(status), samples_to_read, timeout,
            data_buffer, buffer_size, byref(samples_read_per_channel))

        if result == self._RESULT_BAD_PARAMETER:
            raise ValueError("Invalid parameter.")
        elif result == self._RESULT_RESOURCE_UNAVAIL:
            raise HatError(self._address, "Scan not active.")
        elif result == self._RESULT_TIMEOUT:
            timed_out = True
        elif result != self._RESULT_SUCCESS:
            raise HatError(self._address,
                           "Incorrect response {}.".format(result))

        total_read = samples_read_per_channel.value * num_channels

        # python 2 / 3 workaround for xrange
        if sys.version_info.major > 2:
            data_list = [data_buffer[i] for i in range(total_read)]
        else:
            data_list = [data_buffer[i] for i in xrange(total_read)]

        scan_status = namedtuple('MCC118ScanRead', [
            'running', 'hardware_overrun', 'buffer_overrun', 'triggered',
            'timeout', 'data'
        ])
        return scan_status(
            running=(status.value & self._STATUS_RUNNING) != 0,
            hardware_overrun=(status.value & self._STATUS_HW_OVERRUN) != 0,
            buffer_overrun=(status.value & self._STATUS_BUFFER_OVERRUN) != 0,
            triggered=(status.value & self._STATUS_TRIGGERED) != 0,
            timeout=timed_out,
            data=data_list)