Exemple #1
0
class HWSPI(SPI):
    """ Hardware SPI
    """
    def __init__(self, device, ce, config):
        """
        Args:
            device (int): the number of SPI device
            ce (int): the number of chip select of SPI device
            config (SPIConfig):
        """
        self._device = device
        self._ce = ce
        self._config = config
        self._spi = SpiDev()

    def open(self):
        logger.info("Open SPI(%d,%d)", self._device, self._ce)
        self._spi.open(self._device, self._ce)
        self._spi.mode = self._config.mode
        self._spi.max_speed_hz = self._config.speed

    def close(self):
        logger.info("Close SPI(%d,%d)", self._device, self._ce)
        self._spi.close()

    def transfer(self, writedata, readsize):
        buf = self._spi.xfer(writedata + [0] * readsize)
        return buf[len(writedata):]
Exemple #2
0
def read_touch_screen(channel):
    """Read the HackPack touchscreen coordinates."""
    spi = SpiDev()
    spi.open(1, 0)
    spi.no_cs = True
    spi.max_speed_hz = 2000000

    # Manual chip select
    GPIO.output(CS_TOUCH, 1)
    GPIO.output(CS_TOUCH, 0)
    responseData = spi.xfer([channel, 0, 0])
    GPIO.output(CS_TOUCH, 1)
    spi.close()
    return (responseData[1] << 5) | (responseData[2] >> 3)
Exemple #3
0
class MCP3008:
    def __init__(self, bus=0, device=0):
        self.bus, self.device = bus, device
        self.spi = SpiDev()
        self.open()

    def open(self):
        self.spi.open(self.bus, self.device)
        self.spi.max_speed_hz = 1350000

    def read(self, channel=0):
        adc = self.spi.xfer([1, (8 + channel) << 4, 0])
        #print (adc)
        data = ((adc[1] & 3) << 8) + adc[2]
        return data

    def close(self):
        self.spi.close()
class SPI2ADC:
	def __init__(self, bus=0, device=0):
		self.bus = bus
		self.device = device
		self.spi = SpiDev()
		self.open()

	def open(self):
		self.spi.open(self.bus, self.device)
		self.spi.max_speed_hz = 1000000

	def read(self, channel = 0):
		adc = self.spi.xfer([0xbe, 0xef])
		#adc = self.spi.xfer2([0x01, 0x08, 0])
		#data = ((adc[1] & 3) << 8) + adc[2]
		return adc
		#return data

	def close(self):
		self.spi.close()
Exemple #5
0
class PiFaceGpioDigital(PiFaceGPIO):
    """PiFace GPIO pin implementing SPI."""

    ADDR_0 = 0x01000000  # 0x40 [0100 0000]
    ADDR_1 = 0x01000010  # 0x42 [0100 0010]
    ADDR_2 = 0x01000100  # 0x44 [0100 0100]
    ADDR_3 = 0x01000110  # 0x46 [0100 0110]
    DEF_ADDR = ADDR_0

    REGISTER_IODIR_A = 0x00
    REGISTER_IODIR_B = 0x01
    REGISTER_GPINTEN_A = 0x04
    REGISTER_GPINTEN_B = 0x05
    REGISTER_DEFVAL_A = 0x06
    REGISTER_DEFVAL_B = 0x07
    REGISTER_INTCON_A = 0x08
    REGISTER_INTCON_B = 0x09
    REGISTER_IOCON_A = 0x0A
    REGISTER_IOCON_B = 0x0B
    REGISTER_GPPU_A = 0x0C
    REGISTER_GPPU_B = 0x0D
    REGISTER_INTF_A = 0x0E
    REGISTER_INTF_B = 0x0F
    REGISTER_INTCAP_A = 0x10
    REGISTER_INTCAP_B = 0x11
    REGISTER_GPIO_A = 0x12
    REGISTER_GPIO_B = 0x13

    GPIO_A_OFFSET = 0
    GPIO_B_OFFSET = 1000

    IOCON_UNUSED = 0x01
    IOCON_INTPOL = 0x02
    IOCON_ODR = 0x04
    IOCON_HAEN = 0x08
    IOCON_DISSLW = 0x10
    IOCON_SEQOP = 0x20
    IOCON_MIRROR = 0x40
    IOCON_BANK_MODE = 0x80

    BUS_SPEED = 1000000
    WRT_FLAG = 0x00
    RD_FLAG = 0x01

    def __init__(self, pn, initial_val, spi_address, spi_speed):
        """Initialize a new instance of the raspy.io.pi_face_gpio_digital.PiFaceGpioDigital class.

        :param raspy.io.pi_face_pins.PiFacePin pn: The PiFace pin to control.
        :param int initial_val: The initial value (state) to set the pin to.
        Default is PinState.LOW.
        :param int spi_address: The SPI address to use. (Should be ADDRESS_0,
        ADDRESS_1, ADDRESS_2, or ADDRESS_3).
        :param int spi_speed: The clock speed to set the bus to. Can be powers
        of 2 (500KHz minimum up to 32MHz maximum). If not specified, the
        default of SPI_SPEED (1MHz) will be used.
        :raises: raspy.io.io_exception.IOException if unable to read or write
        to the SPI bus.
        """
        PiFaceGPIO.__init__(self, pn, initial_val, pn.name)

        if spi_speed is None or not isinstance(spi_speed, (int, long)):
            spi_speed = self.BUS_SPEED

        self.__speed = spi_speed
        self.__spi = SpiDev()
        try:
            self.__spi.open(0, 0)
        except Exception:
            raise IOException("Unable to open SPI device 0 on bus 0.")

        self.__spi.max_speed_hz = self.__speed
        self.__address = self.DEF_ADDR
        if spi_address is not None:
            self.__address = spi_address

        self.__currentStatesA = 0x00000000
        self.__currentStatesB = 0x11111111
        self.__currentDirectionA = 0x00000000
        self.__currentDirectionB = 0x11111111
        self.__currentPullupA = 0x00000000
        self.__currentPullupB = 0x11111111
        self.__oldState = pin_state.LOW
        self.__pullResistance = pin_pull_resistance.Off
        self.__pollThread = None
        self.__pollRunning = False
        self.__stopEvent = threading.Event()
        self.__stopEvent.set()

        # IOCON - I/O EXPANDER CONFIGURATION REGISTER
        #
        # bit 7 BANK: Controls how the registers are addressed
        #     1 = The registers associated with each port are separated into
        # different banks
        # 0 = The registers are in the same bank (addresses are sequential)
        # bit 6 MIRROR: INT Pins Mirror bit
        # 1 = The INT pins are internally connected
        # 0 = The INT pins are not connected. INTA is associated with PortA and
        # INTB is associated with PortB
        # bit 5 SEQOP: Sequential Operation mode bit.
        # 1 = Sequential operation disabled, address pointer does not
        # increment.
        # 0 = Sequential operation enabled, address pointer increments.
        # bit 4 DISSLW: Slew Rate control bit for SDA output.
        # 1 = Slew rate disabled.
        # 0 = Slew rate enabled.
        # bit 3 HAEN: Hardware Address Enable bit (MCP23S17 only).
        # Address pins are always enabled on MCP23017.
        # 1 = Enables the MCP23S17 address pins.
        # 0 = Disables the MCP23S17 address pins.
        # bit 2 ODR: This bit configures the INT pin as an open-drain output.
        # 1 = Open-drain output (overrides the INTPOL bit).
        # 0 = Active driver output (INTPOL bit sets the polarity).
        # bit 1 INTPOL: This bit sets the polarity of the INT output pin.
        # 1 = Active-high.
        # 0 = Active-low.
        # bit 0 Unimplemented: Read as '0'.
        #

        # write io configuration. enable hardware address.
        self.__write(self.REGISTER_IOCON_A, self.IOCON_SEQOP | self.IOCON_HAEN)
        self.__write(self.REGISTER_IOCON_B, self.IOCON_SEQOP | self.IOCON_HAEN)

        # read initial GPIO pin states
        self.__currentStatesA = self.__read(self.REGISTER_GPIO_A)
        self.__currentStatesB = self.__read(self.REGISTER_GPIO_B)

        # set all default pin pull up resistors
        # (1 = Pull-up enabled.)
        # (0 = Pull-up disabled.)
        self.__write(self.REGISTER_IODIR_A, self.__currentDirectionA)
        self.__write(self.REGISTER_IODIR_B, self.__currentDirectionB)

        # set all default pin states
        self.__write(self.REGISTER_GPIO_A, self.__currentStatesA)
        self.__write(self.REGISTER_GPIO_B, self.__currentStatesB)

        # set all default pin pull up resistors
        # (1 = Pull-up enabled.)
        # (0 = Pull-up disabled.)
        self.__write(self.REGISTER_GPPU_A, self.__currentPullupA)
        self.__write(self.REGISTER_GPPU_B, self.__currentPullupB)

        # set all default pin interrupts
        # (if pin direction is input (1), then enable interrupt for pin)
        # (1 = Enable GPIO input pin for interrupt-on-change event.)
        # (0 = Disable GPIO input pin for interrupt-on-change event.)
        self.__write(self.REGISTER_GPINTEN_A, self.__currentDirectionA)
        self.__write(self.REGISTER_GPINTEN_B, self.__currentDirectionB)

        # set all default pin interrupt default values
        # (comparison value registers are not used in this implementation)
        self.__write(self.REGISTER_DEFVAL_A, 0x00)
        self.__write(self.REGISTER_DEFVAL_B, 0x00)

        # set all default pin interrupt comparison behaviors
        # (1 = Controls how the associated pin value is compared for
        # interrupt-on-change.)
        # (0 = Pin value is compared against the previous pin value.)
        self.__write(self.REGISTER_INTCON_A, 0x00)
        self.__write(self.REGISTER_INTCON_B, 0x00)

        # reset/clear interrupt flags
        if self.__currentDirectionA > 0:
            self.__read(self.REGISTER_INTCAP_A)

        if self.__currentDirectionB > 0:
            self.__read(self.REGISTER_INTCAP_B)

    def __write(self, register, data):
        """Write the specified byte to the specified register.

        :param int register: The register to write to. This should be one of
        the register constants.
        :param int data: A single byte to write to the register.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI bus.
        """
        # create packet in data buffer.
        packet = [
            self.__address | self.WRT_FLAG,  # address byte
            register,  # register byte
            data  # data byte
        ]

        try:
            self.__spi.writebytes(packet)
        except (IOError, SystemError, RuntimeError) as ex:
            err_msg = "Failed to write to SPI bus device at address "
            err_msg += str(self.__address) + " on channel /dev/spidev0.0"
            err_msg += str(ex)
            raise IOException(err_msg)

    def __read(self, register):
        """Read a single byte from the specified register.

        :param int register: The register to write to. This should be one of
        the register constants.
        :returns: The byte read.
        :rtype: int
        :raises: raspy.io.io_exception.IOException if unable to read from
        the SPI bus.
        """
        # create packet in data buffer.
        packet = [
            self.__address | self.RD_FLAG,  # address byte
            register,  # register byte
            0x00000000  # data byte
        ]

        result = 0
        try:
            temp = self.__spi.xfer(packet, self.__speed)
            if temp is not None:
                result = temp[2] & 0xFF
        except (IOError, SystemError, RuntimeError) as ex:
            err_msg = "Failed to write to SPI bus device at address "
            err_msg += str(self.__address) + " on channel /dev/spidev0.0"
            err_msg += str(ex)
            raise IOException(err_msg)

        return result

    def __set_state_a(self, state):
        """Set the state of this pin if on Port A (outputs).

        :param int state: The state to set.
        :raises: raspy.io.io_exception.IOException if unable to write to
        the SPI port.
        """
        # determine pin address.
        pin_address = self.inner_pin.value - self.GPIO_A_OFFSET

        # determine state value for pin bit
        if state == pin_state.HIGH:
            self.__currentStatesA |= pin_address
        else:
            self.__currentStatesA &= ~pin_address

        # update state value.
        self.__write(self.REGISTER_GPIO_A, self.__currentStatesA)

    def __set_state_b(self, state):
        """Set the state of this pin if on Port B (inputs).

        :param int state: The state to set.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        # determine pin address
        pin_address = self.inner_pin.value - self.GPIO_B_OFFSET

        # determine state value for pin bit
        if state == pin_state.HIGH:
            self.__currentStatesB |= pin_address
        else:
            self.__currentStatesB &= ~pin_address

        # update state value.
        self.__write(self.REGISTER_GPIO_B, self.__currentStatesB)

    def __set_state(self, state):
        """Set the state of this pin.

        :param int state: The state to set.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        if self.state == state:
            return

        self.__oldState = self.state
        PiFaceGPIO.write(self, state)

        # determine A or B port based on pin address.
        if self.inner_pin.value == self.GPIO_B_OFFSET:
            self.__set_state_a(state)
        else:
            self.__set_state_b(state)

    def write(self, state):
        """Write a value to the pin.

        :param int state: The pin state value to write to the pin.
        :raises: raspy.ObjectDisposedException if this instance has been
        disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiFaceGpioDigital")

        PiFaceGPIO.write(self, state)
        self.__set_state(state)

    def __evaluate_pin_for_change_a(self, state):
        """Evaluate Port A for pin change.

        If the state is different compared to the specified state, then emits
        a raspy.io.gpio.EVENT_GPIO_STATE_CHANGED event.

        :param int state: The state to check against.
        """
        # determine pin address.
        pin_address = self.inner_pin.value - self.GPIO_A_OFFSET

        # determine if state changed.
        if (state & pin_address) != (self.__currentStatesA & pin_address):
            # Determine new state value for pin bit.
            new_state = pin_state.LOW
            if (state & pin_address) == pin_address:
                new_state = pin_state.HIGH

            if new_state == pin_state.HIGH:
                self.__currentStatesA |= pin_address
            else:
                self.__currentStatesA &= ~pin_address

            # change detected for pin.
            evt = PinStateChangeEvent(self.__oldState, new_state, pin_address)
            self.on_pin_state_change(evt)

    def __evaluate_pin_for_change_b(self, state):
        """Evaluate Port B for pin change.

        If the state is different compared to the specified state, then emits
        a raspy.io.Gpio.EVENT_GPIO_STATE_CHANGED event.

        :param int state: The state to check against.
        """
        # determine pin address.
        pin_address = self.inner_pin.value - self.GPIO_B_OFFSET

        # determine if state changed.
        if (state & pin_address) != (self.__currentStatesB & pin_address):
            # Determine new state value for pin bit.
            new_state = pin_state.LOW
            if (state & pin_address) == pin_address:
                new_state = pin_state.HIGH

            if new_state == pin_state.HIGH:
                self.__currentStatesB |= pin_address
            else:
                self.__currentStatesB &= ~pin_address

            # change detected for pin.
            evt = PinStateChangeEvent(self.__oldState, new_state, pin_address)
            self.on_pin_state_change(evt)

    def __set_mode_a(self, mode):
        """Set the mode of this pin on Port A.

        :param int mode: The pin mode to set.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI bus.
        """
        pin_address = self.inner_pin.value - self.GPIO_A_OFFSET

        if mode == pin_mode.IN:
            self.__currentDirectionA |= pin_address
        elif mode == pin_mode.OUT:
            self.__currentDirectionA &= ~pin_address

        self.__write(self.REGISTER_IODIR_A, self.__currentDirectionA)
        self.__write(self.REGISTER_GPINTEN_A, self.__currentDirectionA)

    def __set_mode_b(self, mode):
        """Set the mode of this pin on Port B.

        :param int mode: The pin mode to set.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI bus.
        """
        pin_address = self.inner_pin.value - self.GPIO_B_OFFSET

        if mode == pin_mode.IN:
            self.__currentDirectionB |= pin_address
        elif mode == pin_mode.OUT:
            self.__currentDirectionB &= ~pin_address

        self.__write(self.REGISTER_IODIR_B, self.__currentDirectionB)
        self.__write(self.REGISTER_GPINTEN_B, self.__currentDirectionB)

    def __background_poll(self):
        """The background (asynchronous) poll cycle routine.

        This is the callback executed by the poll thread.

        :raises: raspy.io.IOException if unable to write to the SPI bus.
        """
        while not self.__stopEvent.is_set():
            # only process for interrupts if a pin on port A is configured as
            # an input pin.
            pin_interrupt_state = -1
            if self.__currentDirectionA > 0:
                # process interrupts for port A.
                pin_interrupt_a = self.__read(self.REGISTER_INTF_A)

                # validate that there is at least one interrupt active on port
                # A.
                if pin_interrupt_a > 0:
                    # read the current pin states on port A.
                    pin_interrupt_state = self.__read(self.REGISTER_GPIO_A)

                    # is there an interrupt flag on this pin?
                    self.__evaluate_pin_for_change_a(pin_interrupt_state)

            # only process for interrupts if a pin on port B is configured as
            # an input pin.
            if self.__currentDirectionB > 0:
                # process interrupts for port B.
                pin_interrupt_b = self.__read(self.REGISTER_INTF_B)

                # validate that there is at least one interrupt active on port
                # B.
                if pin_interrupt_b > 0:
                    # read the current pin states on port B.
                    pin_interrupt_state = self.__read(self.REGISTER_GPIO_B)

                    # is there an interrupt flag on this pin?
                    self.__evaluate_pin_for_change_b(pin_interrupt_state)

    def cancel_poll(self):
        """Cancel an input poll cycle (if running) started by poll()."""
        if self.is_disposed:
            return

        if self.__stopEvent.is_set() or self.__pollThread is None:
            return

        self.__stopEvent.set()
        self.__pollRunning = False

    def poll(self):
        """Start a pin poll cycle.

        This will monitor the pin and check for state changes. If a state
        change is detected, the raspy.io.Gpio.EVENT_GPIO_STATE_CHANGED event
        will be emitted. The poll cycle runs asynchronously until stopped by
        the cancel_poll() method or when this object instance is disposed.

        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.
        :raises: raspy.invalid_operation_exception.InvalidOperationException
        if the poll thread is already running.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiFaceGpioDigital")

        if self.__pollRunning:
            raise InvalidOperationException("Poll thread already running.")

        self.__stopEvent.clear()
        self.__pollThread = threading.Thread(target=self.__background_poll)
        self.__pollThread.name = "PiFaceGpioPoller"
        self.__pollThread.daemon = True
        self.__pollThread.start()
        self.__pollRunning = True

    @property
    def mode(self):
        """Get the pin mode.

        :returns: The pin mode.
        :rtype: int
        """
        return super(PiFaceGPIO, self).mode

    @mode.setter
    def mode(self, p_mode):
        """Set the pin mode.

        :param int p_mode: The pin mode to set.
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiFaceGpioDigital")

        if p_mode is None:
            p_mode = p_mode.TRI

        PiFaceGPIO.mode.fset(self, p_mode)

        # determine A or B port based on pin address
        if self.inner_pin.value < self.GPIO_B_OFFSET:
            self.__set_mode_a(p_mode)
        else:
            self.__set_mode_b(p_mode)

        # if any pins are configured as input pins, then we need to start the
        # interrupt monitoring poll timer.
        if self.__currentDirectionA > 0 or self.__currentDirectionB > 0:
            self.poll()
        else:
            self.cancel_poll()

    def provision(self):
        """Provision this pin.

        :raises: raspy.ObjectDisposedException if this instance has been
        disposed.
        """
        self.write(PiFaceGPIO.get_initial_pin_value(self))

    def __set_pull_resistance_a(self, resistance):
        """Set the pin pull-up/down resistance for port A.

        :param raspy.io.pin_pull_resistance.PinPullResistance resistance: The
        pin pull resistance flag to set. Can enable the internal pull-up or
        pull-down resistor, or disable it.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        pin_address = self.inner_pin.value - self.GPIO_A_OFFSET

        if resistance.value == pin_pull_resistance.PullUp.value:
            self.__currentPullupA |= pin_address
        else:
            self.__currentPullupA &= ~pin_address

        self.__write(self.REGISTER_GPPU_A, self.__currentPullupA)

    def __set_pull_resistance_b(self, resistance):
        """Set the pin pull-up/down resistance for port B.

        :param raspy.io.pin_pull_resistance.PinPullResistance resistance: The
        pin pull resistance flag to set. Can enable the internal pull-up or
        pull-down resistor, or disable it.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        pin_address = self.inner_pin.value - self.GPIO_B_OFFSET

        if resistance.value == pin_pull_resistance.PullUp.value:
            self.__currentPullupB |= pin_address
        else:
            self.__currentPullupB &= ~pin_address

        self.__write(self.REGISTER_GPPU_B, self.__currentPullupB)

    @property
    def pull_resistance(self):
        """Get the pin pull-up/down resistance.

        :returns: The pin pull resistance.
        :rtype: raspy.io.pin_pull_resistance.PinPullResistance
        """
        return self.__pullResistance

    @pull_resistance.setter
    def pull_resistance(self, resistance):
        """Set the pin pull-up/down resistance.

        :param raspy.io.pin_pull_resistance.PinPullResistance resistance: The
        pin pull resistance.
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        if self.__pullResistance.value == resistance.value:
            return

        if self.is_disposed:
            raise ObjectDisposedException("PiFaceGpioDigital")

        self.__pullResistance = resistance
        if self.inner_pin.value > self.GPIO_B_OFFSET:
            self.__set_pull_resistance_a(resistance)
        else:
            self.__set_pull_resistance_b(resistance)

    def read(self):
        """Read a value from the pin.

        :returns: The state (value) of the pin.
        :rtype: int
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.
        :raises: raspy.io.io_exception.IOException if unable to read from the
        SPI port.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiFaceGpioDigital")

        if self.inner_pin.value < self.GPIO_B_OFFSET:
            return self.__read(self.REGISTER_GPIO_A)

        return self.__read(self.REGISTER_GPIO_B)

    def __get_state_a(self):
        """Get the state of the pin if on Port A.

        :returns: The state of the pin.
        :rtype: int
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        pin_address = self.inner_pin.value - self.GPIO_A_OFFSET
        temp_state = (self.__currentStatesA & pin_address)
        my_state = pin_state.LOW
        if temp_state == pin_address:
            my_state = pin_state.HIGH

        super(PiFaceGPIO, self).write(my_state)
        return my_state

    def __get_state_b(self):
        """Get the state of the pin if on Port B.

        :returns: The state of the pin.
        :rtype: int
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI port.
        """
        pin_address = self.inner_pin.value - self.GPIO_B_OFFSET
        temp_state = (self.__currentStatesB & pin_address)
        my_state = pin_state.LOW
        if temp_state == pin_address:
            my_state = pin_state.HIGH

        super(PiFaceGPIO, self).write(my_state)
        return my_state

    @property
    def state(self):
        """Get the state of the pin.

        :returns: The pin state.
        :rtype: int
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.
        :raises: raspy.io.io_exception.IOException if unable to read from the
        SPI port.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiFaceGpioDigital")

        if self.inner_pin.value < self.GPIO_B_OFFSET:
            result = self.__get_state_a()
        else:
            result = self.__get_state_b()

        return result

    def dispose(self):
        """Dispose managed resources.

        Performs application-defined tasks associated with freeing, releasing,
        or resetting resources.
        """
        if self.is_disposed:
            return

        self.cancel_poll()
        self.__spi = None
        super(PiFaceGPIO, self).dispose()
Exemple #6
0
class Lora:
    def __init__(self, reset_pin, spi_channel=0):
        gpio.setmode(gpio.BCM)
        gpio.setup(reset_pin, gpio.OUT)
        self.reset_pin = reset_pin

        self.reset()
        self.spi = SpiDev()
        self.spi.open(0, spi_channel)
        self.spi.max_speed_hz = 1000000

        atexit.register(self.cleanup)

        self.settings_cache = {}
        self.mode = 'SLEEP'
        self.long_range_mode = 'LoRa'
        self.fifo_tx_base_addr = 0
        self.fifo_rx_base_addr = 0
        self.mode = 'STDBY'
        self.clear_irqs()

    def cleanup(self):
        gpio.cleanup()
        self.spi.close()

    def connected(self):
        return self.long_range_mode == 'LoRa'

    def reset(self):
        gpio.output(self.reset_pin, 0)
        time.sleep(0.001)
        gpio.output(self.reset_pin, 1)
        time.sleep(0.005)

    def xfer(self, reg, data=[0]):
        if type(data) is not list:
            data = [data]
        output = self.spi.xfer([reg] + data)
        time.sleep(0.001)
        return output

    def read_reg(self, reg):
        return self.xfer(reg)[1]

    def write_reg(self, reg, value):
        self.xfer(reg | WRITE_BIT, value)

    def read_data(self, reg, n):
        return self.xfer(reg, [0] * n)[1:]

    def _get_setting(self, setting):
        if setting.num_bytes == 1:
            reg_value = self.read_reg(setting.reg)
            v = (reg_value & setting.mask) >> setting.shift
        else:
            data = self.read_data(setting.reg, setting.num_bytes)
            v = int.from_bytes(data, 'big')
        return setting.decode(v)

    def _write_setting(self, setting, value):
        v = setting.encode(value)
        self.settings_cache[setting.id()] = v

        if setting.mask != 0xff:
            r = self.read_reg(setting.reg) & (setting.mask ^ 0xff)
            self.write_reg(setting.reg, r | v << setting.shift)
        elif setting.num_bytes == 1:
            self.write_reg(setting.reg, v)
        elif setting.num_bytes > 1:
            vs = list(v.to_bytes(setting.num_bytes, 'big'))
            self.write_reg(setting.reg, vs)

    def __getattr__(self, name):
        setting_class = settings.options.get(name)
        if setting_class:
            return self._get_setting(setting_class)
        return self.__dict__[name]

    def __setattr__(self, name, value):
        setting_class = settings.options.get(name)
        if setting_class:
            return self._write_setting(setting_class, value)

        self.__dict__[name] = value

    @property
    def irq_flags(self):
        return IrqFlags(self.read_reg(regs.IRQ_FLAGS))

    def clear_irqs(self, flags=IrqFlags(0xff)):
        self.write_reg(regs.IRQ_FLAGS, flags)

    def adjust_rssi(self, v):
        # default freq is 434MHz
        freq = self.settings_cache.get('carrier_frequency', 434e6)
        adj = 157 if freq >= 779e6 else 164
        return v - adj

    @property
    def rx_ready(self):
        return IrqFlags.RX_DONE in self.irq_flags

    def read_rx(self):
        rx_addr = self.read_reg(regs.FIFO_RX_CURRENT_ADDR)
        self.fifo_addr_ptr = rx_addr
        n_bytes = self.read_reg(regs.RX_NB_BYTES)
        payload = self.read_data(regs.FIFO, n_bytes)
        rssi = self.adjust_rssi(self.read_reg(regs.PKT_RSSI_VALUE))
        self.clear_irqs(IrqFlags.RX_DONE)
        return list(payload), rssi

    def on_rx(self, pin, func):
        def callback(*args):
            data, rssi = self.read_rx()
            func(data, rssi)

        gpio.setup(pin, gpio.IN)
        gpio.add_event_detect(pin, gpio.RISING, callback=callback)

        # if we're ready now, go for it!
        if gpio.input(pin):
            callback()

    def send(self, data):
        if not data:
            return

        mode_before = self.mode
        self.mode = 'STDBY'

        self.fifo_addr_ptr = 0
        self.write_reg(regs.FIFO, data)
        self.write_reg(regs.PAYLOAD_LENGTH, len(data))
        self.mode = 'TX'

        while True:
            if IrqFlags.TX_DONE in self.irq_flags:
                self.clear_irqs(IrqFlags.TX_DONE)
                break
            time.sleep(0.01)

        self.mode = mode_before

    def __repr__(self):
        lines = []
        for name, cls in settings.options.items():
            lines.append(f'{cls.__name__}: {getattr(self, name)}')
        return '\n'.join(lines)
Exemple #7
0
class InputsOutputs:
    def __init__(self, _HandleShotmachine, _ToMainQueue, _ToIOQueue):

        # Start logger
        self.logger = logging.getLogger(__name__)
        self.logger.info('Starting IO program')

        # store given variables
        self.HandleShotmachine = _HandleShotmachine
        self.ToMainQueue = _ToMainQueue
        self.ToIOQueue = _ToIOQueue
        
        # Get needed settings from settings struct
        self.HendelSwitch = self.HandleShotmachine["Hardware"]["HendelSwitch"]
        self.FotoSwitch = self.HandleShotmachine["Hardware"]["FotoSwitch"]
        self.EnableI2COutputPin = self.HandleShotmachine["Hardware"]["EnableI2COutput"]
        self.EnableI2COutput = self.HandleShotmachine["Settings"]["EnableI2C"]
        self.EnableBarcodeScanner = self.HandleShotmachine["Settings"]["EnableBarcodeScanner"]
        self.EnableSPI = self.HandleShotmachine["Settings"]["EnableSPI"]
        self.ConfigSwitchPin = self.HandleShotmachine["Hardware"]["ConfigSwitch"]
        self.ResetArduinoPin = self.HandleShotmachine["Hardware"]["ResetArduino"]
        self.SPISSPin = self.HandleShotmachine["Hardware"]["SPISSPin"]
        #self.party_id = self.HandleShotmachine["Settings"]["PartyId"]

        # import required libraries depending on the current platform
        if self.HandleShotmachine["Settings"]["OnRaspberry"]:
            from Functions.MCP230XX.MCP230XX import MCP230XX
            import RPi.GPIO as GPIO
            from spidev import SpiDev
            from smbus import SMBus
            self.OnRaspberry = True
        else:
            from Functions.GPIOEmulator.ShotmachineIOEmulator import GPIO
            from Functions.GPIOEmulator.ShotmachineIOEmulator import MCP230XX
            from Functions.GPIOEmulator.ShotmachineIOEmulator import SpiDev
            from Functions.GPIOEmulator.ShotmachineIOEmulator import SMBus
            from Functions.GPIOEmulator.ShotmachineIOEmulator import usb_core_emu
            self.OnRaspberry = False
            
        # prepare general variables
        self.makeshot = False
        self.shotnumber = 0
        self.shotglass = False
        self.CheckShotglass = True
        self.ShotHendelState = False
        self.ShotHendelSend = False
        self.FotoKnopState = False
        self.FotoKnopSend = False
        self.ConfigSwitchState = False
        self.ConfigSwitchStateSend = False
        self.flashlightState = 1
        self.setflashlight = True
        self.SetShotLeds = True
        self.shotLedsState = 0
        self.FlushPump = False
        self.flushnumber = 0
        self.busy = False
        self.run = True
        self.recievebuffer = ''

        #Barcode scanner settings
        self.barcode_vencor_id = 0xac90
        self.barcode_product_id = 0x3003


        # init GPIO
        GPIO.setmode(GPIO.BCM)
        self.GPIO = GPIO
        self.GPIO.setwarnings(False)
        self.GPIO.setup(self.EnableI2COutputPin, GPIO.OUT)
        self.GPIO.setup(self.ResetArduinoPin, GPIO.OUT)
        self.GPIO.setup(self.SPISSPin, GPIO.OUT)
        self.GPIO.setup(self.HendelSwitch, GPIO.IN)
        self.GPIO.setup(self.FotoSwitch, GPIO.IN)
        self.GPIO.setup(self.ConfigSwitchPin, GPIO.IN)
        
        # set GPIO pins
        self.GPIO.output(self.EnableI2COutputPin, 0)
        self.GPIO.output(self.ResetArduinoPin, 0)
        self.GPIO.output(self.SPISSPin, 0)
        time.sleep(0.1)

        # init MCP IO extender
        if self.EnableI2COutput:
            i2cAddress = 0x20
            self.MCP = MCP230XX('MCP23017', i2cAddress, '16bit')
            self.MCP.set_mode(0, 'output')
            self.MCP.output(0, 1)
            time.sleep(0.1)
            self.MCP.set_mode(1, 'output')
            self.MCP.output(1, 1)
            time.sleep(0.1)
            self.MCP.set_mode(2, 'output')
            self.MCP.output(2, 1)
            time.sleep(0.1)
            self.MCP.set_mode(3, 'output')
            self.MCP.output(3, 1)
            time.sleep(0.1)
            self.MCP.set_mode(4, 'output')
            self.MCP.output(4, 1)

        # init I2C bus
        if self.EnableI2COutput:
            self.bus = SMBus(1)
            self.shotdetectorAddress = 0x70

        # init SPI
        if self.EnableSPI:
            self.spi = SpiDev()
            self.spi.open(0, 0)
            self.spi.max_speed_hz = 390000

        # start threads
        self.mainThread = threading.Thread(target=self.main_IO_interface, name='IO_main')
        self.mainThread.start()
        #self.queueThread = threading.Thread(target=self.queue_watcher, name='IO_watcher')
        #self.queueThread.start()
        self.queueThread = threading.Thread(target=self.checkshotglas, name='Shotglass_watcher')
        self.queueThread.start()

        if self.EnableBarcodeScanner:
            self.queueThread = threading.Thread(target=self.barcodeReaderThreat, name='Barcode_reader')
            self.queueThread.start()

        # wrap up init
        self.logger.info('Input Output program started')


    def queue_watcher(self):
        # Watch queue from interface and process commands
        #self.run = True
        #while self.run:
            #if self.recievebuffer == '':
                try:
                    self.recievebuffer = self.ToIOQueue.get(block=True, timeout=0.1)
                    if self.recievebuffer == "Quit":
                        self.run = False
                        self.logger.info("IO quit")
                    elif "MakeShot" in self.recievebuffer:
                        self.shotnumber = int(self.recievebuffer[-1:])
                        self.makeshot = True
                    elif "ShotLeds" in self.recievebuffer:
                        self.shotLedsState = int(self.recievebuffer[-1:])
                        self.SetShotLeds = True
                    elif "Flush" in self.recievebuffer:
                        self.flushnumber = int(self.recievebuffer[-1:])
                        self.FlushPump = True
                    elif "Flashlight" in self.recievebuffer:
                        self.flashlightState = int(self.recievebuffer[-1:])
                        self.setflashlight = True
                    elif "Ready" in self.recievebuffer:
                        self.busy = False
                        self.logger.info('Machine ready, checking inputs')
                    self.recievebuffer = ''
                except queue.Empty:
                    pass
            #time.sleep(0.1)


    def main_IO_interface(self):
        # Main loop that executes the commands
        while self.run:
            # Check queue from main program
            self.queue_watcher()
            
            # Make shot
            if self.makeshot:
                self.logger.info('Making shot: ' + str(self.shotnumber))
                if self.EnableI2COutput:
                    self.MCP.output(self.shotnumber, 0)
                    if self.shotnumber == 0:
                        time.sleep(5)  # 8
                    elif self.shotnumber == 1:
                        time.sleep(6)  # 4
                    elif self.shotnumber == 2:
                        time.sleep(6)  # 5
                    elif self.shotnumber == 3:
                        time.sleep(5)  # 5
                    elif self.shotnumber == 4:
                        time.sleep(6)  # 4
                    self.MCP.output(self.shotnumber, 1)
                self.makeshot = False
                time.sleep(1)
                self.ToMainQueue.put("Done with shot")

            # Flush pump
            if self.FlushPump:
                self.logger.info('Spoelen van pomp: ' + str(self.flushnumber))
                if self.EnableI2COutput:
                    self.MCP.output(self.flushnumber, 0)
                    time.sleep(10)
                    #TODO add possibility to stop on command
                    self.MCP.output(self.flushnumber, 1)
                self.FlushPump = False
                time.sleep(1)
                self.ToMainQueue.put("Klaar met spoelen")

            # Change flashlight state
            if self.setflashlight:
                self.setflashlightfunc(self.flashlightState)
                self.setflashlight = False
                
            # Change shot leds state
            if self.SetShotLeds:
                self.setShotLedsfunc(self.shotLedsState)
                self.SetShotLeds = False

            # Check inputs
            if not self.busy:
                self.checkshothandle()
                self.checkfotoknop()
                #self.checkArduinoReset()
        
        # cleanup GPIO and pumps and close program 
        if self.EnableI2COutput:
            del self.MCP
            time.sleep(1)
        self.GPIO.cleanup()


    def barcodeReaderThreat(self):
        # import required libraries for barcode scanner
        if self.OnRaspberry:
            from usb import core as usb_core
            from usb import util as usb_util
        else:
            from Functions.GPIOEmulator.ShotmachineIOEmulator import usb_core_emu
            usb_core = usb_core_emu()

        # make usb connection to scanner
        #if self.EnableBarcodeScanner:
        self.device = usb_core.find(idVendor=self.barcode_vencor_id, idProduct=self.barcode_product_id)
        self.usbEndpointEmu = namedtuple("usbEndpointEmu", "bEndpointAddress wMaxPacketSize")

        try:
            while self.run:
                # on raspberry, find actual scanner
                if self.OnRaspberry:
                    if self.device is None:
                        # No scanner found
                        self.logger.error("No barcode scanner found, is it connected and turned on?")
                        connected = False
                        break
                    else:
                        # Found scanner, give it some time to start
                        connected = True
                        time.sleep(5)
                    if connected:
                        # claim the device and it's interface
                        configuration = self.device.get_active_configuration()
                        if self.device.is_kernel_driver_active(0):
                            # fisrt detach scanner from os before it can be claimed
                            self.device.detach_kernel_driver(0)
                        endpoint = self.device[0][(1, 0)][0]
                        self.device.set_configuration()
                        self.logger.info("Barcode reader ready, start scanning")
                else:
                    # Barcode scanner in emulator mode
                    self.logger.info("Barcode scanner in emulation mode")
                    connected = True
                    endpoint = self.usbEndpointEmu(bEndpointAddress = None, wMaxPacketSize=None)

                while self.run and connected and self.OnRaspberry:
                    # check usb connection for messages and convert to barcode
                    try:
                        data = self.device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize)
                        read_string = ''.join(chr(e) for e in data)
                        try:
                            read_number = int(read_string)
                        except:
                            read_number = None
                        if read_number != None:
                            self.logger.info("Barcode scanned: " + str(read_number))
                            self.ToMainQueue.put("Barcode:" + str(read_number))

                    except usb_core.USBError as e:
                        # error in checking messsages from scanner
                        data = None
                        if e.errno == 110: 
                            # timeout, just keep checking
                            continue
                        if e.errno == 19:
                            # Connection lost, try to reconnect 
                            self.logger.warning("Connection to barode scanner lost, closed connection if software")
                            connected = False
                            break
                            
                while self.run and connected and not self.OnRaspberry:
                    # Emulator barcode scanner
                    try:
                        data = self.device.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize)
                        read_string = ''.join(chr(e) for e in data)
                        try:
                            read_number = int(read_string)
                        except:
                            read_number = None
                        if read_number != None:
                            self.logger.info("Barcode scanned: " + str(read_number))
                            self.ToMainQueue.put("Barcode:" + str(read_number))
                    except Exception as e:
                        if str(e) == 'Timeout':
                            continue
                        else:
                            self.logger.error("Warning in barcode reader: " + e)
                            raise
        finally:
            # close connection to barcode scanner on closing
            if connected and self.OnRaspberry:
                usb_util.release_interface(self.device, 0)
            self.logger.info("Closed barcode scanner reader")


    def checkshothandle(self):
        # Controleer de sensor van de hendel
        self.ShotHendelState = self.GPIO.input(self.HendelSwitch)
        if not self.ShotHendelSend and self.ShotHendelState:
            self.logger.info('shothendel pulled')
            self.ToMainQueue.put("Shothendel")
            self.ShotHendelSend = True
            self.busy = True
        if not self.ShotHendelState:
            self.ShotHendelSend = False


    def checkArduinoReset(self):
        # reset function fro arduino, work in progress
        self.ConfigSwitchState = self.GPIO.input(self.ConfigSwitchPin)
        if self.ConfigSwitchState:
            time.sleep(0.5)
            self.ConfigSwitchState = self.GPIO.input(self.ConfigSwitchPin)
            if not self.ConfigSwitchStateSend and self.ConfigSwitchState:
                self.logger.info('Config button pressed, resetting arduino')
                self.ConfigSwitchStateSend = True
                self.GPIO.output(self.ResetArduinoPin, 1)
                time.sleep(1)
                self.GPIO.output(self.ResetArduinoPin, 0)
            if not self.ConfigSwitchState:
                self.ConfigSwitchStateSend = False


    def checkfotoknop(self):
        # Controleer fotoknop
        if self.HandleShotmachine["Settings"]["OnRaspberry"]:
            self.FotoKnopState = not self.GPIO.input(self.FotoSwitch)
        else:
            # in emulation mode the input is inverted
            self.FotoKnopState = self.GPIO.input(self.FotoSwitch)
        if not self.FotoKnopSend and self.FotoKnopState:
            self.logger.info('fotoknop pressed')
            self.ToMainQueue.put("Fotoknop")
            self.FotoKnopSend = True
            self.busy = True
        if not self.FotoKnopState:
            self.FotoKnopSend = False


    def checkshotglas(self):
        # check Ultrasonic sensor for shotglass detector, takes some time therefore in a separate thread
        while self.run:
            if self.EnableI2COutput:
                try:
                    self.bus.write_byte_data(self.shotdetectorAddress, 0, 0x51)
                    time.sleep(0.3)
                    msb = self.bus.read_byte_data(self.shotdetectorAddress, 2)
                    lsb = self.bus.read_byte_data(self.shotdetectorAddress, 3)
                    measuredRange = (msb << 8) + lsb
                except:
                    # print("error in i2c")
                    measuredRange = 23
                if (measuredRange != 7) or (measuredRange != 110):
                    #print(measuredRange)
                    if measuredRange < 26: #25:
                        self.CheckShotglass = True
                    else:
                        self.CheckShotglass = False
                    if self.shotglass != self.CheckShotglass:
                        self.logger.info('shotglas status changed to: ' + str(int(self.CheckShotglass)))
                        self.ToMainQueue.put("ShotglassState " + str(int(self.CheckShotglass)))
                        self.shotglass = self.CheckShotglass
            else:
                if self.shotglass != self.CheckShotglass:
                    self.logger.info('shotglas status changed to: ' + str(int(self.CheckShotglass)))
                    self.ToMainQueue.put("ShotglassState " + str(int(self.CheckShotglass)))
                    self.shotglass = self.CheckShotglass
                    

    def setflashlightfunc(self, state):
        # change flashlight mode by sending mode to arduino that controls the leds
        self.logger.info('changing flashlight state to: ' + str(state))
        string_to_send = "state;"+ str(state) + "\n"
        string_to_bytes = str.encode(string_to_send)
        self.GPIO.output(self.SPISSPin, 1)
        time.sleep(0.03)
        if self.EnableSPI:
            self.spi.xfer(string_to_bytes)
        self.GPIO.output(self.SPISSPin, 0)
        
        
    def setShotLedsfunc(self, state):
        # change leds in shothok by sensing mode to arduino that controls the leds
        self.logger.info('changing shot leds state to: ' + str(state))
        string_to_send = "shot;"+ str(state) + "\n"
        string_to_bytes = str.encode(string_to_send)
        self.GPIO.output(self.SPISSPin, 1)
        time.sleep(0.03)
        if self.EnableSPI:
            self.spi.xfer(string_to_bytes)
        self.GPIO.output(self.SPISSPin, 0)
Exemple #8
0
class LightController(object):
	def __init__(self, bus = 0, device = 0, pins = 24):
		self.bus = bus
		self.device = device
		self.spi = SpiDev()
		self.spi.open(bus, device)

		self.MAX = 0xfff
		self.MIN = 0x000
		self.pins = pins
		self.light_values = [0 for _ in range(36)]
		self.send()
		self.scanning = 0
		self.map = {0:1, 1:2, 2:4, 3:5, 4:7, 5:8, 6:10, 7:11, 8:13, 9:14, 10:16, 11:17, 12:19, 13:20, 14:22, 15:23, 16:25, 17:26, 18:28, 19:29, 20:31, 21:32, 22:34, 23:35}
	
		self.clear()
			

	def set(self, pin, val):
		assert(pin < self.pins and pin >= 0)
		if (val >= self.MAX): val = self.MAX
		if (val < self.MIN): val = self.MIN	
		actual = self.map[pin]
		self.light_values[actual] = val
 
	def send(self):
		self.spi.xfer(self.light_values[::-1])

	def pic_countdown(self, init_delay = 1, delay = 1):
		time.sleep(init_delay)	
		for i in range(0, 4):
			self.set(i, self.MAX)
		self.send()
		time.sleep(delay)	
		for i in range(4, 8):
			self.set(i, self.MAX)
		self.send()
		time.sleep(delay)	
		for i in range(8, 12):
			self.set(i, self.MAX)
		self.send()
		time.sleep(delay)	
		for i in range(12, 16):
			self.set(i, self.MAX)
		self.send()
		time.sleep(3)
		self.clear()
	
	def scan(self):
		self.clear()
		for i in range(0, 10, 2):
			self.set(i, self.MAX)
			self.set(i + 1, self.MAX)
			self.send()
			time.sleep(0.2)
			self.clear()

		for i in range(11, -1, -2):
			self.set(i, self.MAX)
			self.set(i - 1, self.MAX)
			self.send()
			time.sleep(0.2)
			self.clear()

	def scan_success(self):
		self.clear()
		self.set(12, self.MAX)
		self.set(13, self.MAX)
		self.set(14, self.MAX)
		self.set(15, self.MAX)
		self.send()
		time.sleep(3)
		self.clear()
			
	def cycle(self):
		for i in range(len(self.light_values)):
			self.set(i, self.MAX)
			self.send()
			print('Light ' + str(i) + " is on")
			time.sleep(1)	
			self.set(i, self.MIN)
			self.send()
		
	def test(self):
		num = ""
		while num != "quit":
			num = int(input("which light to get lit? "))
			self.clear()
			self.set(num, self.MAX)
			self.send()


	def clear(self):
		for i in range(0, self.pins):
			self.set(i, self.MIN)
		self.send()

	def __del__(self):
		self.spi.close()
class Dspin_motor(object):
	
	__has_toggled_reset_pin = False
	__spi_lock = None
	@classmethod
	def init_toggle_reset_pin(cls, reset_pin):
		if not cls.__has_toggled_reset_pin:
			cls.__has_toggled_reset_pin = True
			#cls.reset_gpio = LED(reset_pin)
			#cls.reset_gpio.on()
			#time.sleep(0.1)
			#cls.reset_gpio.off()
			#time.sleep(0.1)
			#cls.reset_gpio.on()
			#time.sleep(0.1)
			Dspin_motor.__spi_lock = threading.Lock()


	def __init__(self, bus, cs_pin, slave_select_pin, reset_pin):
                print('setting up dspin interface on pins: ', bus, cs_pin, slave_select_pin, reset_pin)
                Dspin_motor.init_toggle_reset_pin(reset_pin)

                self.reset_gpio = LED(reset_pin)
                self.reset_gpio.on()
                time.sleep(0.1)
                self.reset_gpio.off()
                time.sleep(0.1)
                self.reset_gpio.on()
                time.sleep(0.1)



                self.slave_select_gpio = LED(slave_select_pin)
                self.spi = SpiDev()

                self.slave_select_gpio.on()

                self.spi.open(bus, cs_pin)
                self.spi.max_speed_hz = 10000
                self.spi.mode = 3
                self.spi.lsbfirst = False
                #spi.no_cs = True
                #spi.loop = False

                self.connect_l6470()
                self.last_steps_count_time = datetime.datetime.now()
                self.current_speed = 0
                self.absolute_pos_manual_count = 0

	def dspin_xfer(self, data):
		data = data & 0xFF
		self.slave_select_gpio.off()

		result = self.spi.xfer([data])
		
		#spi.writebytes([data])
		#result = spi.readbytes(1)

		#print('xfering ' + hex(data))
		self.slave_select_gpio.on()
		return result[0]

	def dspin_GetParam(self, param):
		self.dspin_xfer(dSPIN_GET_PARAM | param)
		return self.dspin_ParamHandler(param, 0)

	def dspin_SetParam(self, param, value):
		self.dspin_xfer(dSPIN_SET_PARAM | param)
		self.dspin_ParamHandler(param, value)

	def dspin_ParamHandler(self, param, value):
		if param == dSPIN_CONFIG:
			return self.dspin_param(value, 16)	
		elif param == dSPIN_STATUS:
			return self.dspin_param(0, 16)
		elif param == dSPIN_STEP_MODE:
			return self.dspin_xfer(value)
		elif param in [dSPIN_KVAL_RUN, dSPIN_KVAL_ACC, dSPIN_KVAL_DEC]:
			return self.dspin_xfer(value)
		elif param == dSPIN_ACC:
			return self.dspin_param(value, 12)
		elif param == dSPIN_MAX_SPEED:
			return self.dspin_param(value, 10)
		elif param == dSPIN_MIN_SPEED:
			return self.dspin_param(value, 12)
		elif param == dSPIN_FS_SPD:
			return self.dspin_param(value, 10)
		elif param == dSPIN_OCD_TH:
			return self.dspin_xfer(value & 0x0F)
		elif param == dSPIN_ABS_POS:
			return self.dspin_param(value, 22)

		else:
			raise Exception('not implemented: ' + str(param))

	def dspin_param(self, value, bit_length):
		byte_len = int(math.ceil(bit_length / 8.))
		
		mask = 0xffffffff >> (32 - bit_length)
		if value > mask: value = mask
		
		result = 0

		if byte_len == 3:
			result = result | (self.dspin_xfer(value>>16) << 16)
		if byte_len >= 2:
			result = result | (self.dspin_xfer(value>>8) << 8)
		if byte_len >= 1:
			result = result | (self.dspin_xfer(value))
		
		return result & mask
			
	def dspin_GetStatus(self):
		Dspin_motor.__spi_lock.acquire()
		temp = 0
		self.dspin_xfer(dSPIN_GET_STATUS)
		temp = self.dspin_xfer(0) << 8
		temp |= self.dspin_xfer(0)
		Dspin_motor.__spi_lock.release()
		return temp

	def dspin_Run(self, dir, speed):
                speed = int(speed)
                # print('speed: ', speed)
                Dspin_motor.__spi_lock.acquire()
                self.dspin_xfer(dSPIN_RUN | dir)
                if speed > 0xFFFFF: speed = 0xFFFFF

                self.dspin_xfer(speed >> 16)
                self.dspin_xfer(speed >> 8)
                self.dspin_xfer(speed)
                Dspin_motor.__spi_lock.release()
                
                self.current_speed = speed * (1 if dir == FWD else -1)

	def dspin_SoftStop(self):
		Dspin_motor.__spi_lock.acquire()
		self.dspin_xfer(dSPIN_SOFT_STOP)
		Dspin_motor.__spi_lock.release()

	def dspin_SpdCalc(self, stepsPerSec):
		result = stepsPerSec * 67.106
		#if result > 0x3FFF:
		#	result = 0x3FFF
		# print('speed result: ', int(result))
		return int(result)

	def dspin_GetPositionSteps(self):
                
                Dspin_motor.__spi_lock.acquire()
                result = self.dspin_GetParam(dSPIN_ABS_POS)
                Dspin_motor.__spi_lock.release()
                #print(result)
                result = twos_comp(result, 22)
                #result &= 0xFF80
                result /= 16
                #print(result)
                return result





                now = datetime.datetime.now()
                elapsed_seconds = (now - self.last_steps_count_time).total_seconds()
                self.last_steps_count_time = now
                
                steps_change = elapsed_seconds * self.current_speed/67.106
                self.absolute_pos_manual_count += steps_change
                #print(result, self.absolute_pos_manual_count)
                return self.absolute_pos_manual_count

                return result

	def connect_l6470(self):
		
		config_result = self.dspin_GetParam(dSPIN_CONFIG)
		print('config result: ', hex(config_result))
		
		config_result = self.dspin_GetParam(dSPIN_CONFIG)
		print('config result: ', hex(config_result))
		
		status = self.dspin_GetStatus()
		print('status: ', hex(status))
		
		self.dspin_SetParam(dSPIN_STEP_MODE, 
                           (0xFF - dSPIN_SYNC_EN) | dSPIN_STEP_SEL_1_128 | dSPIN_SYNC_SEL_64)
		
		status = self.dspin_GetStatus()
		print('status: ', hex(status))
		
		self.dspin_SetParam(dSPIN_MIN_SPEED, 1)
		#self.dspin_SetParam(dSPIN_MAX_SPEED, 2000)
		print('min speed: ', self.dspin_GetParam(dSPIN_MIN_SPEED))
		print('max speed: ', self.dspin_GetParam(dSPIN_MAX_SPEED))
		#max speed?
		
		self.dspin_SetParam(dSPIN_FS_SPD, 0x3FF)
		
		self.dspin_SetParam(dSPIN_ACC, 0xFF)
		
		self.dspin_SetParam(dSPIN_OCD_TH, dSPIN_OCD_TH_6000mA)
		
		self.dspin_SetParam(dSPIN_CONFIG,
				dSPIN_CONFIG_PWM_DIV_1 |
				dSPIN_CONFIG_PWM_MUL_2 |
				dSPIN_CONFIG_SR_180V_us |
				dSPIN_CONFIG_OC_SD_DISABLE |
				dSPIN_CONFIG_VS_COMP_DISABLE |
				dSPIN_CONFIG_SW_HARD_STOP |
				dSPIN_CONFIG_INT_16MHZ)
		
		self.dspin_SetParam(dSPIN_KVAL_RUN, 0x7F);
		self.dspin_SetParam(dSPIN_KVAL_ACC, 0x0F);
		self.dspin_SetParam(dSPIN_KVAL_DEC, 0x0F);
		
		status = self.dspin_GetStatus()
		print('status: ', hex(status))

	def disconnect_l6470(self):
		self.dspin_SoftStop()
		self.spi.close()
Exemple #10
0
from spidev import SpiDev

dev = SpiDev(0, 0)
dev.max_speed_hz = 7800000

resp = dev.xfer([0xA3])

time_sec = 0x74749054

while True:
    resp = dev.xfer([0xA3])
    if resp == [0xA0] or resp == [0xA5]:
        print "%s" % ''.join(["0x%02X " % x for x in resp]).strip()

        resp = dev.xfer([0xA2])
        print "%s" % ''.join(["0x%02X " % x for x in resp]).strip()

        # first_stage_hash - 256 bits
        resp = dev.xfer([
            0x09, 0xA0, 0xD1, 0x91, 0x92, 0xEF, 0x77, 0xC3, 0x04, 0xFE, 0x44,
            0x78, 0x88, 0xF9, 0xEF, 0x50, 0x69, 0xD6, 0x48, 0x46, 0x5A, 0x19,
            0x14, 0x6F, 0xB7, 0x70, 0x61, 0x97, 0x14, 0xD0, 0x89, 0x04
        ])
        print "%s" % ''.join(["0x%02X " % x for x in resp]).strip()

        # input_M - 96 bits
        #resp = dev.xfer([0x45, 0xF4, 0x99, 0x2E, 0x74, 0x74, 0x90, 0x54, 0x74, 0x7B, 0x1B, 0x18]);
        resp = dev.xfer([0x45, 0xF4, 0x99, 0x2E])
        print "%s" % ''.join(["0x%02X " % x for x in resp]).strip()

        # time
Exemple #11
0
class Matrix(object):
    '''
        The class which models the operation of the Olimex 8x8 RGB LED matrix.
        The numbering scheme used when defining the pins are with respect to
        the BCM numbering scheme.

        Wiring:
            - VCC = driving voltage for the matrix. 5 volts.
            - GND = ground connection from the matrix.
            - DIN = data in for the matrix, GPIO pin 10 (SPI MOSI).
            - CS = chip select, depending on SPI channel selection.
            - CLK = serial clock, GPIO pin 11 (SPI SCK).

    '''
    def __init__(self, spidevice=0):
        '''
            Basic constructor for our driver class.

            @param: spidevice - the SPI device to be used.
                Acts as a chip-enable. The Raspberry PI B+ has two such device
                output pins in-built.
                Defaults to 0.

            @return: None
        '''
        if spidevice != 1:
            spidevice = 0

        self.__spi = SpiDev()
        self.__spi.mode = 0b01
        self.__spi.open(0, spidevice)

        self.__buffer = [0] * 24

    def drawpixel(self, pixel):
        '''
            Draws a given Pixel object to the internal buffer.
            The buffer is formed of 24 bytes.
            Each byte represents a single color, the n'th bit being whether
            that particular color is active in the n'th led of that row.
            The colors are ordered in reverse. (BGR).

            @param: pixel - a Pixel object.

            @return: the Pixel encoded as a byte.
        '''
        # current row we're on:
        row = 3 * pixel.y

        # clear currently present color by unsetting the corresponding bit from
        # the three color bytes:
        self.__buffer[row] &= ~(1 << pixel.x)       # clear red.
        self.__buffer[row + 1] &= ~(1 << pixel.x)   # clear green.
        self.__buffer[row + 2] &= ~(1 << pixel.x)   # clear blue.

        # set red bit for this pixel, if necessary:
        if pixel.color in [Color.red, Color.white, Color.brown, Color.purple]:
            self.__buffer[row] |= 1 << pixel.x
        # set green bit:
        if pixel.color in [Color.green, Color.white, Color.turquoise, Color.brown]:
            self.__buffer[row + 1] |= 1 << pixel.x
        # set blue bit:
        if pixel.color in [Color.blue, Color.white, Color.turquoise, Color.purple]:
            self.__buffer[row + 2] |= 1 << pixel.x

    def write(self):
        '''
            Serially writes the whole of the video buffer to the matrix.
        '''
        self.__spi.xfer(self.__buffer)

    def clear(self):
        '''
            Clears both the internal buffer and the matrix.
        '''
        self.__buffer = [0] * 24
        self.write()

    def cleanup(self):
        '''
            Clears all registers and terminates the SPI connection.
        '''
        self.clear()
        self.__spi.close()
Exemple #12
0
class MFRC522:
    NRSTPD = 22

    MAX_LEN = 16

    PCD_IDLE = 0x00
    PCD_AUTHENT = 0x0E
    PCD_RECEIVE = 0x08
    PCD_TRANSMIT = 0x04
    PCD_TRANSCEIVE = 0x0C
    PCD_RESETPHASE = 0x0F
    PCD_CALCCRC = 0x03

    PICC_REQIDL = 0x26
    PICC_REQALL = 0x52
    PICC_ANTICOLL = 0x93
    PICC_SElECTTAG = 0x93
    PICC_AUTHENT1A = 0x60
    PICC_AUTHENT1B = 0x61
    PICC_READ = 0x30
    PICC_WRITE = 0xA0
    PICC_DECREMENT = 0xC0
    PICC_INCREMENT = 0xC1
    PICC_RESTORE = 0xC2
    PICC_TRANSFER = 0xB0
    PICC_HALT = 0x50

    Reserved00 = 0x00
    CommandReg = 0x01
    CommIEnReg = 0x02
    DivlEnReg = 0x03
    CommIrqReg = 0x04
    DivIrqReg = 0x05
    ErrorReg = 0x06
    Status1Reg = 0x07
    Status2Reg = 0x08
    FIFODataReg = 0x09
    FIFOLevelReg = 0x0A
    WaterLevelReg = 0x0B
    ControlReg = 0x0C
    BitFramingReg = 0x0D
    CollReg = 0x0E
    Reserved01 = 0x0F

    Reserved10 = 0x10
    ModeReg = 0x11
    TxModeReg = 0x12
    RxModeReg = 0x13
    TxControlReg = 0x14
    TxAutoReg = 0x15
    TxSelReg = 0x16
    RxSelReg = 0x17
    RxThresholdReg = 0x18
    DemodReg = 0x19
    Reserved11 = 0x1A
    Reserved12 = 0x1B
    MifareReg = 0x1C
    Reserved13 = 0x1D
    Reserved14 = 0x1E
    SerialSpeedReg = 0x1F

    Reserved20 = 0x20
    CRCResultRegM = 0x21
    CRCResultRegL = 0x22
    Reserved21 = 0x23
    ModWidthReg = 0x24
    Reserved22 = 0x25
    RFCfgReg = 0x26
    GsNReg = 0x27
    CWGsPReg = 0x28
    ModGsPReg = 0x29
    TModeReg = 0x2A
    TPrescalerReg = 0x2B
    TReloadRegH = 0x2C
    TReloadRegL = 0x2D
    TCounterValueRegH = 0x2E
    TCounterValueRegL = 0x2F

    Reserved30 = 0x30
    TestSel1Reg = 0x31
    TestSel2Reg = 0x32
    TestPinEnReg = 0x33
    TestPinValueReg = 0x34
    TestBusReg = 0x35
    AutoTestReg = 0x36
    VersionReg = 0x37
    AnalogTestReg = 0x38
    TestDAC1Reg = 0x39
    TestDAC2Reg = 0x3A
    TestADCReg = 0x3B
    Reserved31 = 0x3C
    Reserved32 = 0x3D
    Reserved33 = 0x3E
    Reserved34 = 0x3F

    serNum = []

    def __init__(self, port=0, device=0):
        self.spi = SpiDev()
        self.spi.open(port, device)
        self.MFRC522_Init()

    def MFRC522_Reset(self):
        self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE)

    def Write_MFRC522(self, addr, val):
        self.spi.xfer([(addr << 1) & 0x7E, val])

    def Read_MFRC522(self, addr):
        val = self.spi.xfer([((addr << 1) & 0x7E) | 0x80, 0])
        return val[1]

    def SetBitMask(self, reg, mask):
        tmp = self.Read_MFRC522(reg)
        self.Write_MFRC522(reg, tmp | mask)

    def ClearBitMask(self, reg, mask):
        tmp = self.Read_MFRC522(reg)
        self.Write_MFRC522(reg, tmp & (~mask))

    def AntennaOn(self):
        temp = self.Read_MFRC522(self.TxControlReg)
        if(~(temp & 0x03)):
            self.SetBitMask(self.TxControlReg, 0x03)

    def AntennaOff(self):
        self.ClearBitMask(self.TxControlReg, 0x03)

    def MFRC522_ToCard(self, command, send_data):
        irqEn = 0x00
        waitIRq = 0x00

        if command == self.PCD_AUTHENT:
            irqEn = 0x12
            waitIRq = 0x10
        if command == self.PCD_TRANSCEIVE:
            irqEn = 0x77
            waitIRq = 0x30

        self.Write_MFRC522(self.CommIEnReg, irqEn | 0x80)
        self.ClearBitMask(self.CommIrqReg, 0x80)
        self.SetBitMask(self.FIFOLevelReg, 0x80)

        self.Write_MFRC522(self.CommandReg, self.PCD_IDLE)

        for value in send_data:
            self.Write_MFRC522(self.FIFODataReg, value)

        self.Write_MFRC522(self.CommandReg, command)

        if command == self.PCD_TRANSCEIVE:
            self.SetBitMask(self.BitFramingReg, 0x80)

        def await_interrupt(retry_count=100, delay=0.01):
            for _ in range(retry_count):
                sleep(delay)
                interrupts = self.Read_MFRC522(self.CommIrqReg)
                if (interrupts & 0x01) or (interrupts & waitIRq):
                    return interrupts
            raise MifareError("No response within waiting period.")

        try:
            interrupts = await_interrupt()
        finally:
            self.ClearBitMask(self.BitFramingReg, 0x80)

        if (self.Read_MFRC522(self.ErrorReg) & 0x1B):
            raise MifareError()

        if interrupts & irqEn & 0x01:
            raise NoCardInField()

        if command == self.PCD_TRANSCEIVE:
            count = self.Read_MFRC522(self.FIFOLevelReg)
            last_bits = self.Read_MFRC522(self.ControlReg) & 0x07
            if last_bits:
                length_in_bits = (count - 1) * 8 + last_bits
            else:
                length_in_bits = count * 8

            count = min(self.MAX_LEN, max(1, count))

            returned_data = [
                self.Read_MFRC522(self.FIFODataReg) for _ in range(count)
            ]

            return (returned_data, length_in_bits)
        else:
            return ([], 0)

    def MFRC522_Request(self, req_mode):
        tag_type = [req_mode]

        self.Write_MFRC522(self.BitFramingReg, 0x07)

        (backData, backBits) = self.MFRC522_ToCard(
            self.PCD_TRANSCEIVE, tag_type
        )

        if (backBits != 0x10):
            raise MifareError()

        return backData

    def MFRC522_Anticoll(self):  # Anticollision
        serial = [self.PICC_ANTICOLL, 0x20]

        self.Write_MFRC522(self.BitFramingReg, 0x00)

        serial_number, _ = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, serial)

        if len(serial_number) != 5:
            raise InvalidCard("Serial number had invalid length")

        checksum = 0
        for byte in serial_number:
            checksum ^= byte
        if checksum:
            raise InvalidCard("Serial number checksum failed")

        return serial_number

    def CalulateCRC(self, data):
        self.ClearBitMask(self.DivIrqReg, 0x04)
        self.SetBitMask(self.FIFOLevelReg, 0x80)
        for byte in data:
            self.Write_MFRC522(self.FIFODataReg, byte)
        self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC)
        for _ in range(0xFF):
            if self.Read_MFRC522(self.DivIrqReg) & 0x04:
                break
        pOutData = [
            self.Read_MFRC522(self.CRCResultRegL),
            self.Read_MFRC522(self.CRCResultRegM)
        ]
        return pOutData

    def MFRC522_SelectTag(self, serial_number):
        backData = []
        buf = [self.PICC_SElECTTAG, 0x70]
        buf.extend(serial_number)
        buf.extend(self.CalulateCRC(buf))
        try:
            backData, backLen = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
        except MifareError:
            return 0  # No idea why, but the original code did this

        if backLen == 0x18:
            print("Size: {}".format(backData[0]))
            return backData[0]
        else:
            return 0

    def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
        buf = [
            authMode,  # First byte should be the authMode (A or B)
            BlockAddr  # Second byte is the trailerBlock (usually 7)
        ]

        # Now we need to append the authKey which usually is 6 bytes of 0xFF
        buf.extend(Sectorkey)

        # Next we append the first 4 bytes of the UID
        buf.extend(serNum[:4])

        # Now we start the authentication itself
        try:
            backData, backLen = self.MFRC522_ToCard(self.PCD_AUTHENT, buf)
        except NoCardInField:
            raise
        except MifareError:
            raise MifareAuthError()

        # Check if crypto1 unit is switched on
        if not (self.Read_MFRC522(self.Status2Reg) & 0x08):
            MifareAuthError("MFCrypto1On bit not enabled")

    def MFRC522_StopCrypto1(self):
        self.ClearBitMask(self.Status2Reg, 0x08)

    def MFRC522_Read(self, block_address):
        recv_data = [self.PICC_READ, block_address]
        recv_data.extend(self.CalulateCRC(recv_data))
        returned_data, _ = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recv_data)
        if len(returned_data) == 16:
            print("Sector {} {}".format(block_address, returned_data))
        return returned_data

    def MFRC522_Write(self, block_address, data):
        buf = [self.PICC_WRITE, block_address]
        buf.extend(self.CalulateCRC(buf))
        returned_data, length = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
        if length != 4 or (returned_data[0] & 0x0F) != 0x0A:
            raise MifareError()

        buf = []
        buf.extend(data)
        buf.extend(self.CalulateCRC(buf))
        returned_data, length = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
        if length != 4 or (returned_data[0] & 0x0F) != 0x0A:
            raise MifareError()

    def MFRC522_DumpClassic1K(self, key, uid):
        for i in range(64):
            self.MFRC522_Auth(self.PICC_AUTHENT1A, i, key, uid)
            print(self.MFRC522_Read(i))

    def MFRC522_Init(self):
        self.MFRC522_Reset()

        self.Write_MFRC522(self.TModeReg, 0x8D)
        self.Write_MFRC522(self.TPrescalerReg, 0x3E)
        self.Write_MFRC522(self.TReloadRegL, 30)
        self.Write_MFRC522(self.TReloadRegH, 0)

        self.Write_MFRC522(self.TxAutoReg, 0x40)
        self.Write_MFRC522(self.ModeReg, 0x3D)
        self.AntennaOn()
Exemple #13
0
class Matrix(object):
    '''
        The class which models the operation of the Olimex 8x8 RGB LED matrix.
        The numbering scheme used when defining the pins are with respect to
        the BCM numbering scheme.

        Wiring:
            - VCC = driving voltage for the matrix. 5 volts.
            - GND = ground connection from the matrix.
            - DIN = data in for the matrix, GPIO pin 10 (SPI MOSI).
            - CS = chip select, depending on SPI channel selection.
            - CLK = serial clock, GPIO pin 11 (SPI SCK).

    '''
    def __init__(self, spidevice=0):
        '''
            Basic constructor for our driver class.

            @param: spidevice - the SPI device to be used.
                Acts as a chip-enable. The Raspberry PI B+ has two such device
                output pins in-built.
                Defaults to 0.

            @return: None
        '''
        if spidevice != 1:
            spidevice = 0

        self.__spi = SpiDev()
        self.__spi.mode = 0b01
        self.__spi.open(0, spidevice)

        self.__buffer = [0] * 24

    def drawpixel(self, pixel):
        '''
            Draws a given Pixel object to the internal buffer.
            The buffer is formed of 24 bytes.
            Each byte represents a single color, the n'th bit being whether
            that particular color is active in the n'th led of that row.
            The colors are ordered in reverse. (BGR).

            @param: pixel - a Pixel object.

            @return: the Pixel encoded as a byte.
        '''
        # current row we're on:
        row = 3 * pixel.y

        # clear currently present color by unsetting the corresponding bit from
        # the three color bytes:
        self.__buffer[row] &= ~(1 << pixel.x)  # clear red.
        self.__buffer[row + 1] &= ~(1 << pixel.x)  # clear green.
        self.__buffer[row + 2] &= ~(1 << pixel.x)  # clear blue.

        # set red bit for this pixel, if necessary:
        if pixel.color in [Color.red, Color.white, Color.brown, Color.purple]:
            self.__buffer[row] |= 1 << pixel.x
        # set green bit:
        if pixel.color in [
                Color.green, Color.white, Color.turquoise, Color.brown
        ]:
            self.__buffer[row + 1] |= 1 << pixel.x
        # set blue bit:
        if pixel.color in [
                Color.blue, Color.white, Color.turquoise, Color.purple
        ]:
            self.__buffer[row + 2] |= 1 << pixel.x

    def write(self):
        '''
            Serially writes the whole of the video buffer to the matrix.
        '''
        self.__spi.xfer(self.__buffer)

    def clear(self):
        '''
            Clears both the internal buffer and the matrix.
        '''
        self.__buffer = [0] * 24
        self.write()

    def cleanup(self):
        '''
            Clears all registers and terminates the SPI connection.
        '''
        self.clear()
        self.__spi.close()
Exemple #14
0
class AMT20():
    def __init__(self, address, direction, bitrate=976000, theta_max=0.15):
        """
        Initialize and open an SPI connection with a CUI AMT20 encoder.
        :param bus: SPI address in the bus (e.g. 0 or 1).
        :type bus: int
        :param direction: Direction of rotation of the encoder, must be either
            'ccw' or 'cw'.
        :type direction: string
        :param bitrate: Frequency of the SPI bus. The encoder defaults to 
            976[kHz].
        :type bitrate: int
        :param theta_max: Max angle variation between samples, in radians. 
            Defaults to 0.15[rad/sample].
        :type theta_max: float
        """
        assert address == 0 or address == 1, "SPI address must be 0 or 1"
        assert direction == "ccw" or direction == "cw", "Direction must be either 'ccw' or 'cw'"
        self.RESOLUTION = 4096
        self.direction = direction
        self.theta_max = theta_max

        self.encoder = SpiDev()
        self.encoder.open(0, address)
        self.encoder.max_speed_hz = bitrate

        self._warm_up()
        self.last = {"angle": self.angle(), "time": datetime.now()}

    def _warm_up(self):
        """
        Send a RD_POS and enough NOP_A5 commands until the enoder starts
            responding as expected.
        """
        resp = self.encoder.xfer([NOP_A5], 0, 20)[0]

        while resp != 0xA5:
            resp = self.encoder.xfer([NOP_A5], 0, 20)[0]

        return True

    def read_position(self):
        """
        Perform a series of SPI transactions, sending the 'RD_POS' command
        and waiting for the response. Then concatenates both bytes received.
        """
        resp = self.encoder.xfer([RD_POS], 0, 20)[0]
        if resp == 0:
            raise IOError("Remote I/O error")

        while resp != RD_POS:
            resp = self.encoder.xfer([NOP_A5], 0, 20)[0]

        MSB = self.encoder.xfer([NOP_A5], 0, 20)[0]  # Most Significant Byte
        LSB = self.encoder.xfer([NOP_A5], 0, 20)[0]  # Least Significant Byte

        position = (MSB << 8) | LSB

        if self.direction == "ccw":
            return position
        else:
            return self.RESOLUTION - position

    def set_zero(self):
        """
        Perform a series of SPI transactions to set the current position
        as zero and save this setting in the EEPROM. 

        The encoder must be power cycled. Otherwise the position values will
        not be calculated off the latest zero position. When the encoder is
        powered on next the new offset will be used for the position calculation.
        """
        resp = self.encoder.xfer([SET_ZERO_POINT], 0, 20)[0]
        if resp == 0:
            raise IOError("Remote I/O error")

        while resp != 0x80:
            resp = self.encoder.xfer([NOP_A5], 0, 20)[0]

        return True

    def angle(self):
        """
        This command converts the reading of the encoder to a angle in the range [0, 2*pi]
        """
        count = self.read_position()
        return (count * 2 * pi / self.RESOLUTION)

    def angular_speed(self):
        """
        This command calculates the speed using the difference between the 
        last and current angle and their corresponding timestamps 
        """
        # Get current time and angle
        angle = self.angle()
        time = datetime.now()
        # Get angle and time differences
        dTheta = angle - self.last["angle"]
        dTime = time - self.last["time"]
        # Update angle and time for future calls
        self.last["angle"] = angle
        self.last["time"] = time

        # When the encoder crosses zero, the difference will spike,
        # unless we add (or substract) 2pi
        if dTheta > self.theta_max:
            dTheta -= 2 * pi
        elif dTheta < -self.theta_max:
            dTheta += 2 * pi
        # Convert timedelta object to float (seconds)
        dt = dTime.seconds + dTime.microseconds * 1E-6

        return dTheta / dt

    def __del__(self):
        """
        Do a cleanup of the opened resources.
        """
        self.encoder.close()
Exemple #15
0
from spidev import SpiDev
import time
import RPi.GPIO as GPIO


GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(6, GPIO.OUT)

spi = SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 390000

print("Flashlight to waitstate")
#string_to_send = "state;1\n"
string_to_send = "shot;1\n"
string_to_bytes = str.encode(string_to_send)
GPIO.output(6, 1)
time.sleep(0.01)
spi.xfer(string_to_bytes)
GPIO.output(6, 0)
time.sleep(1)
GPIO.cleanup()
class SPI(object):
    """
    classdocs
    """
    __LOCK_TIMEOUT = 10.0

    # ----------------------------------------------------------------------------------------------------------------

    def __init__(self, bus, device, mode, max_speed):
        """
        Constructor
        """

        self.__bus = bus
        self.__device = device
        self.__mode = mode
        self.__max_speed = max_speed

        self.__connection = None

    # ----------------------------------------------------------------------------------------------------------------

    def open(self):
        if self.__connection:
            return

        self.acquire_lock()

        self.__connection = SpiDev()
        self.__connection.open(self.__bus, self.__device)

        self.__connection.mode = self.__mode
        self.__connection.max_speed_hz = self.__max_speed

    def close(self):
        if self.__connection is None:
            return

        self.__connection.close()
        self.__connection = None

        self.release_lock()

    # ----------------------------------------------------------------------------------------------------------------

    def acquire_lock(self):
        Lock.acquire(self.__lock_name, SPI.__LOCK_TIMEOUT)

    def release_lock(self):
        Lock.release(self.__lock_name)

    @property
    def __lock_name(self):
        return "%s-%s" % (self.__class__.__name__, self.__bus)

    # ----------------------------------------------------------------------------------------------------------------

    def xfer(self, args):
        return self.__connection.xfer(args)

    def read_bytes(self, count):
        return self.__connection.readbytes(count)

    # ----------------------------------------------------------------------------------------------------------------

    @property
    def bus(self):
        return self.__bus

    @property
    def device(self):
        return self.__device

    # ----------------------------------------------------------------------------------------------------------------

    def __str__(self, *args, **kwargs):
        return "SPI:{bus:%d, device:%s, mode:%d, max_speed:%d, connection:%s}" % \
               (self.__bus, self.__device, self.__mode, self.__max_speed, self.__connection)