Source code for crappy.inout.phidgets_wheatstone_bridge

# coding: utf-8

from time import time
from typing import Optional, List
import logging
from math import log2

from .meta_inout import InOut
from .._global import OptionalModule

try:
  from Phidget22.Net import Net, PhidgetServerType
  from Phidget22.Devices.VoltageRatioInput import VoltageRatioInput
  from Phidget22.PhidgetException import PhidgetException
except (ImportError, ModuleNotFoundError):
  Net = OptionalModule('Phidget22')
  PhidgetServerType = OptionalModule('Phidget22')
  VoltageRatioInput = OptionalModule('Phidget22')
  PhidgetException = OptionalModule('Phidget22')


[docs] class PhidgetWheatstoneBridge(InOut): """This class can read voltage ratio values from a Phidget Wheatstone Bridge. It relies on the :mod:`Phidget22` module to communicate with the load cell conditioner. It can acquire values up to `50Hz` with possible gain values from `1` to `128`. .. versionadded:: 2.0.4 """
[docs] def __init__(self, channel: int = 0, hardware_gain: int = 1, data_rate: float = 50, gain: float = 1, offset: float = 0, remote: bool = False) -> None: """Sets the args and initializes the parent class. Args: channel: The index of the channel from which to acquire data, as an :obj:`int`. Should be either `0` or `1`. hardware_gain: The gain used by the conditioner for data acquisition. The higher the gain, the better the resolution but the narrower the range. Should be a power of `2` between `1` and `128`. data_rate: The number of samples to acquire per second, as an :obj:`int`. Should be between `0.017` (one sample per minute) and `50`. gain: A gain to apply to the acquired value, following the formula : :math:`returned = gain * acquired + offset` offset: An offset to apply to the acquired value, following the formula : :math:`returned = gain * acquired + offset` remote: Set to :obj:`True` to drive the bridge via a network VINT Hub, or to :obj:`False` to drive it via a USB VINT Hub. """ self._load_cell: Optional[VoltageRatioInput] = None super().__init__() if channel not in (0, 1): raise ValueError("The channel should be 0 or 1 !") self._channel = channel if hardware_gain not in (2 ** i for i in range(8)): raise ValueError("The hardware gain should be either 1, 2, 4, 8, 16, " "32, 64 or 128 !") self._hardware_gain = hardware_gain self._data_rate = data_rate self._gain = gain self._offset = offset self._remote = remote self._last_ratio: Optional[float] = None
[docs] def open(self) -> None: """Sets up the connection to the load cell conditioner as well as the various callbacks, and waits for the load cell conditioner to attach.""" # Setting up the load cell conditioner self.log(logging.DEBUG, "Enabling server discovery") Net.enableServerDiscovery(PhidgetServerType.PHIDGETSERVER_DEVICEREMOTE) self._load_cell = VoltageRatioInput() self._load_cell.setChannel(self._channel) # Setting the remote or local status if self._remote is True: self._load_cell.setIsLocal(False) self._load_cell.setIsRemote(True) else: self._load_cell.setIsLocal(True) self._load_cell.setIsRemote(False) # Setting up the callbacks self._load_cell.setOnAttachHandler(self._on_attach) self._load_cell.setOnVoltageRatioChangeHandler(self._on_ratio_change) # Opening the connection to the load cell conditioner try: self.log(logging.DEBUG, "Trying to attach the load cell conditioner") self._load_cell.openWaitForAttachment(10000) except PhidgetException: raise TimeoutError("Waited too long for the motor to attach !")
[docs] def get_data(self) -> Optional[List[float]]: """Returns the last known voltage ratio value, adjusted with the gain and the offset.""" if self._last_ratio is not None: return [time(), self._gain * self._last_ratio + self._offset]
[docs] def close(self) -> None: """Closes the connection to the load cell conditioner.""" if self._load_cell is not None: self._load_cell.close()
def _on_attach(self, _: VoltageRatioInput) -> None: """Callback called when the load cell conditioner attaches to the program. Sets the data rate and the hardware gain of the conditioner. """ self.log(logging.INFO, "Load cell conditioner successfully attached") # Setting the hardware gain self._load_cell.setBridgeGain(int(round(log2(self._hardware_gain), 0) + 1)) # Setting the data rate min_rate = self._load_cell.getMinDataRate() max_rate = self._load_cell.getMaxDataRate() if not min_rate <= self._data_rate <= max_rate: raise ValueError(f"The data rate should be between {min_rate} and " f"{max_rate}, got {self._data_rate} !") else: self._load_cell.setDataRate(self._data_rate) def _on_ratio_change(self, _: VoltageRatioInput, ratio: float) -> None: """Callback called when the voltage ratio changes.""" self.log(logging.DEBUG, f"Voltage ratio changed to {ratio}") self._last_ratio = ratio def _on_error(self, _: VoltageRatioInput, error_code: int, error: str) -> None: """Callback called when the load cell conditioner returns an error.""" raise RuntimeError(f"Got error with error code {error_code}: {error}")