class NightLight(nonblocking_timer):
    def __init__(self):
        super(NightLight, self).__init__()
        pixels = neopixel.NeoPixel(NEOPIXEL, 10, auto_write=1, brightness=1.0)
        pixels.fill((0, 0, 0))
        pixels.show()
        self._on = False
        self._animator = PixelAnimator(pixels)

        self._irSensor = AnalogIn(IR_PROXIMITY)

        self._irInput = DigitalInOut(REMOTEIN)
        self._irInput.direction = Direction.INPUT

        self._irOutput = DigitalInOut(REMOTEOUT)
        self._irOutput.direction = Direction.OUTPUT

        self._microphone = DigitalInOut(MICROPHONE_DATA)
        self._irOutput.direction = Direction.INPUT

    def stop(self):
        print('stop')
        self._irSensor.deinit()
        self._irInput.deinit()

    def next(self):
        # print("ir: %d mic: %d" % (self._irSensor.value, self._irOutput.value))

        self._animator.next()
Beispiel #2
0
def blink_color(led_ref):
    """
    Function to control the LED and perform a simple blink
    Total delay = 1 second
    This encapsulates activating the pin and de-activating it to avoid color mashing
    :param led_ref:
    """
    led = DigitalInOut(led_ref)
    led.direction = Direction.OUTPUT
    led.value = True
    time.sleep(0.1)
    led.value = False
    time.sleep(0.1)
    led.deinit()
Beispiel #3
0
class DigitalIn(object):
  """Basic digital input."""

  def __init__(self, pin, pull=None):
    self._pin = DigitalInOut(pin)
    if pull == PULL_UP:
      self._pin.switch_to_input(pull=Pull.UP)
    elif pull == PULL_DOWN:
      self._pin.switch_to_input(pull=Pull.DOWN)
    else:
      self._pin.switch_to_input()

  def deinit(self):
    self._pin.deinit()

  @property
  def value(self):
    return self._pin.value
Beispiel #4
0
class Flasher:
    def __init__(self, config=argon_config):
        self.config = config

    def __enter__(self):
        config = self.config
        self.uart = busio.UART(tx=config['tx'],
                               rx=config['rx'],
                               baudrate=115200,
                               timeout=1)
        self.resetpin = DigitalInOut(config['reset'])
        self.gpio0pin = DigitalInOut(config['io0'])
        esptool = miniesptool(self.uart,
                              self.gpio0pin,
                              self.resetpin,
                              flashsize=4 * 1024 * 1024)
        esptool.debug = False
        esptool.debug_check_command = False

        esptool.sync()
        if esptool.chip_name != "ESP32":
            raise RuntimeError("Expected ESP32, got {}".format(
                esptool.chip_name))
        esptool.baudrate = baudrate
        print("MAC ADDR:",
              ":".join("{:02x}".format(x) for x in esptool.mac_addr))
        self.esptool = esptool
        return self

    def __exit__(self):
        self.uart.deinit()
        self.resetpin.deinit()
        self.gpio0pin.deinit()
        esptool.reset()
        time.sleep(0.5)

    def flash_file(self, firmware, md5sum, dry_run=False):
        self.esptool.flash_file(firmware, 0x1000, md5=md5, dry_run=dry_run)

    def erase(self, dry_run=False):
        meg = 1024 * 1024
        for sector in range(4):
            esptool.erase(size=meg, offset=sector * meg)
            print()
Beispiel #5
0
class PiperJoystickZ:
    def __init__(self, joy_z_pin=board.D2):
        self.joy_z_pin = DigitalInOut(joy_z_pin)
        self.joy_z_pin.direction = Direction.INPUT
        self.joy_z_pin.pull = Pull.UP
        self.joy_z = Debouncer(self.joy_z_pin)

    def deinit(self):
        self.joy_z_pin.deinit()

    def update(self):
        self.joy_z.update()

    def zPressed(self):
        return not self.joy_z.value

    def zPressedEvent(self):
        return self.joy_z.fell

    def zReleasedEvent(self):
        return self.joy_z.rose
Beispiel #6
0
class DigitalOut(object):
  """Basic digital output."""

  def __init__(self, pin, value=False):
    self._pin = DigitalInOut(pin)
    self._pin.switch_to_output(value=value)

  def deinit(self):
    self._pin.deinit()

  @property
  def value(self):
    return self._pin.value

  @value.setter
  def value(self, value):
    self._pin.value = value

  def on(self):
    self._pin.value = 1

  def off(self):
    self._pin.value = 0
Beispiel #7
0
class HCSR04:
    """Control a HC-SR04 ultrasonic range sensor.

    Example use:

    ::

        with HCSR04(trig, echo) as sonar:
            try:
                while True:
                    print(sonar.dist_cm())
                    sleep(2)
            except KeyboardInterrupt:
                pass
    """
    def __init__(self, trig_pin, echo_pin, timeout_sec=.1):
        """
        :param trig_pin: The pin on the microcontroller that's connected to the
            ``Trig`` pin on the HC-SR04.
        :type trig_pin: str or microcontroller.Pin
        :param echo_pin: The pin on the microcontroller that's connected to the
            ``Echo`` pin on the HC-SR04.
        :type echo_pin: str or microcontroller.Pin
        :param float timeout_sec: Max seconds to wait for a response from the
            sensor before assuming it isn't going to answer. Should *not* be
            set to less than 0.05 seconds!
        """
        if isinstance(trig_pin, str):
            trig_pin = getattr(board, trig_pin)
        if isinstance(echo_pin, str):
            echo_pin = getattr(board, echo_pin)
        self.dist_cm = self._dist_two_wire
        self.timeout_sec = timeout_sec

        self.trig = DigitalInOut(trig_pin)
        self.trig.switch_to_output(value=False, drive_mode=DriveMode.PUSH_PULL)

        self.echo = PulseIn(echo_pin)
        self.echo.pause()
        self.echo.clear()

    def __enter__(self):
        """Allows for use in context managers."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Automatically de-initialize after a context manager."""
        self.deinit()

    def deinit(self):
        """De-initialize the trigger and echo pins."""
        self.trig.deinit()
        self.echo.deinit()

    def dist_cm(self):
        """Return the distance measured by the sensor in cm.

        This is the function that will be called most often in user code. The
        distance is calculated by timing a pulse from the sensor, indicating
        how long between when the sensor sent out an ultrasonic signal and when
        it bounced back and was received again.

        If no signal is received, the return value will be ``-1``. This means
        either the sensor was moving too fast to be pointing in the right
        direction to pick up the ultrasonic signal when it bounced back (less
        likely), or the object off of which the signal bounced is too far away
        for the sensor to handle. In my experience, the sensor can detect
        objects over 460 cm away.

        :return: Distance in centimeters.
        :rtype: float
        """
        # This method only exists to make it easier to document. See either
        # _dist_one_wire or _dist_two_wire for the actual implementation. One
        # of those two methods will be assigned to be used in place of this
        # method on instantiation.
        pass

    def _dist_two_wire(self):
        self.echo.clear()  # Discard any previous pulse values
        self.trig.value = 1  # Set trig high
        time.sleep(0.00001)  # 10 micro seconds 10/1000/1000
        self.trig.value = 0  # Set trig low
        timeout = time.monotonic()
        self.echo.resume()
        while len(self.echo) == 0:
            # Wait for a pulse
            if (time.monotonic() - timeout) > self.timeout_sec:
                self.echo.pause()
                return -1
        self.echo.pause()
        if self.echo[0] == 65535:
            return -1

        return (self.echo[0] / 2) / (291 / 10)
Beispiel #8
0
class I2C(_BitBangIO):
    """Software-based implementation of the I2C protocol over GPIO pins."""
    def __init__(self, scl, sda, *, frequency=400000, timeout=1):
        """Initialize bitbang (or software) based I2C.  Must provide the I2C
        clock, and data pin numbers.
        """
        super().__init__()

        # Set pins as outputs/inputs.
        self._scl = DigitalInOut(scl)
        self._scl.switch_to_output()
        self._scl.value = 1

        # SDA flips between being input and output
        self._sda = DigitalInOut(sda)
        self._sda.switch_to_output()
        self._sda.value = 1

        self._delay = 1 / frequency / 2
        self._timeout = timeout

    def deinit(self):
        """Free any hardware used by the object."""
        self._sda.deinit()
        self._scl.deinit()

    def scan(self):
        """Perform an I2C Device Scan"""
        found = []
        if self._check_lock():
            for address in range(0, 0x80):
                if self._probe(address):
                    found.append(address)
        return found

    def writeto(self, address, buffer, *, start=0, end=None):
        """Write data from the buffer to an address"""
        if end is None:
            end = len(buffer)
        if self._check_lock():
            self._write(address, buffer[start:end], True)

    def readfrom_into(self, address, buffer, *, start=0, end=None):
        """Read data from an address and into the buffer"""
        if end is None:
            end = len(buffer)

        if self._check_lock():
            readin = self._read(address, end - start)
            for i in range(end - start):
                buffer[i + start] = readin[i]

    def writeto_then_readfrom(self,
                              address,
                              buffer_out,
                              buffer_in,
                              *,
                              out_start=0,
                              out_end=None,
                              in_start=0,
                              in_end=None):
        """Write data from buffer_out to an address and then
        read data from an address and into buffer_in
        """
        if out_end is None:
            out_end = len(buffer_out)
        if in_end is None:
            in_end = len(buffer_in)
        if self._check_lock():
            self.writeto(address, buffer_out, start=out_start, end=out_end)
            self.readfrom_into(address, buffer_in, start=in_start, end=in_end)

    def _scl_low(self):
        self._scl.value = 0

    def _sda_low(self):
        self._sda.value = 0

    def _scl_release(self):
        """Release and let the pullups lift"""
        # Use self._timeout to add clock stretching
        self._scl.value = 1

    def _sda_release(self):
        """Release and let the pullups lift"""
        # Use self._timeout to add clock stretching
        self._sda.value = 1

    def _start(self):
        self._sda_release()
        self._scl_release()
        sleep(self._delay)
        self._sda_low()
        sleep(self._delay)

    def _stop(self):
        self._scl_low()
        sleep(self._delay)
        self._sda_low()
        sleep(self._delay)
        self._scl_release()
        sleep(self._delay)
        self._sda_release()
        sleep(self._delay)

    def _repeated_start(self):
        self._scl_low()
        sleep(self._delay)
        self._sda_release()
        sleep(self._delay)
        self._scl_release()
        sleep(self._delay)
        self._sda_low()
        sleep(self._delay)

    def _write_byte(self, byte):
        for bit_position in range(8):
            self._scl_low()
            sleep(self._delay)
            if byte & (0x80 >> bit_position):
                self._sda_release()
            else:
                self._sda_low()
            sleep(self._delay)
            self._scl_release()
            sleep(self._delay)
        self._scl_low()
        sleep(self._delay * 2)

        self._scl_release()
        sleep(self._delay)

        self._sda.switch_to_input()
        ack = self._sda.value
        self._sda.switch_to_output()
        sleep(self._delay)

        self._scl_low()

        return not ack

    def _read_byte(self, ack=False):
        self._scl_low()
        sleep(self._delay)

        data = 0
        self._sda.switch_to_input()
        for _ in range(8):
            self._scl_release()
            sleep(self._delay)
            data = (data << 1) | int(self._sda.value)
            sleep(self._delay)
            self._scl_low()
            sleep(self._delay)
        self._sda.switch_to_output()

        if ack:
            self._sda_low()
        else:
            self._sda_release()
        sleep(self._delay)
        self._scl_release()
        sleep(self._delay)
        return data & 0xFF

    def _probe(self, address):
        self._start()
        ok = self._write_byte(address << 1)
        self._stop()
        return ok > 0

    def _write(self, address, buffer, transmit_stop):
        self._start()
        if not self._write_byte(address << 1):
            raise RuntimeError(
                "Device not responding at 0x{:02X}".format(address))
        for byte in buffer:
            self._write_byte(byte)
        if transmit_stop:
            self._stop()

    def _read(self, address, length):
        self._start()
        if not self._write_byte(address << 1 | 1):
            raise RuntimeError(
                "Device not responding at 0x{:02X}".format(address))
        buffer = bytearray(length)
        for byte_position in range(length):
            buffer[byte_position] = self._read_byte(
                ack=(byte_position != length - 1))
        self._stop()
        return buffer
Beispiel #9
0
class SPI(_BitBangIO):
    """Software-based implementation of the SPI protocol over GPIO pins."""
    def __init__(self, clock, MOSI=None, MISO=None):
        """Initialize bit bang (or software) based SPI.  Must provide the SPI
        clock, and optionally MOSI and MISO pin numbers. If MOSI is set to None
        then writes will be disabled and fail with an error, likewise for MISO
        reads will be disabled.
        """
        super().__init__()

        while self.try_lock():
            pass

        self._mosi = None
        self._miso = None

        self.configure()
        self.unlock()

        # Set pins as outputs/inputs.
        self._sclk = DigitalInOut(clock)
        self._sclk.switch_to_output()

        if MOSI is not None:
            self._mosi = DigitalInOut(MOSI)
            self._mosi.switch_to_output()

        if MISO is not None:
            self._miso = DigitalInOut(MISO)
            self._miso.switch_to_input()

    def deinit(self):
        """Free any hardware used by the object."""
        self._sclk.deinit()
        if self._miso:
            self._miso.deinit()
        if self._mosi:
            self._mosi.deinit()

    def configure(self, *, baudrate=100000, polarity=0, phase=0, bits=8):
        """Configures the SPI bus. Only valid when locked."""
        if self._check_lock():
            if not isinstance(baudrate, int):
                raise ValueError("baudrate must be an integer")
            if not isinstance(bits, int):
                raise ValueError("bits must be an integer")
            if bits < 1 or bits > 8:
                raise ValueError("bits must be in the range of 1-8")
            if polarity not in (0, 1):
                raise ValueError("polarity must be either 0 or 1")
            if phase not in (0, 1):
                raise ValueError("phase must be either 0 or 1")
            self._baudrate = baudrate
            self._polarity = polarity
            self._phase = phase
            self._bits = bits
            self._half_period = (1 / self._baudrate) / 2  # 50% Duty Cyle delay

    def _wait(self, start=None):
        """Wait for up to one half cycle"""
        while (start + self._half_period) > monotonic():
            pass
        return monotonic()  # Return current time

    def write(self, buffer, start=0, end=None):
        """Write the data contained in buf. Requires the SPI being locked.
        If the buffer is empty, nothing happens.
        """
        # Fail MOSI is not specified.
        if self._mosi is None:
            raise RuntimeError("Write attempted with no MOSI pin specified.")
        if end is None:
            end = len(buffer)

        if self._check_lock():
            start_time = monotonic()
            for byte in buffer[start:end]:
                for bit_position in range(self._bits):
                    bit_value = byte & 0x80 >> bit_position
                    # Set clock to base
                    if not self._phase:  # Mode 0, 2
                        self._mosi.value = bit_value
                    self._sclk.value = self._polarity
                    start_time = self._wait(start_time)

                    # Flip clock off base
                    if self._phase:  # Mode 1, 3
                        self._mosi.value = bit_value
                    self._sclk.value = not self._polarity
                    start_time = self._wait(start_time)

            # Return pins to base positions
            self._mosi.value = 0
            self._sclk.value = self._polarity

    # pylint: disable=too-many-branches
    def readinto(self, buffer, start=0, end=None, write_value=0):
        """Read into the buffer specified by buf while writing zeroes. Requires the SPI being
        locked. If the number of bytes to read is 0, nothing happens.
        """
        if self._miso is None:
            raise RuntimeError("Read attempted with no MISO pin specified.")
        if end is None:
            end = len(buffer)

        if self._check_lock():
            start_time = monotonic()
            for byte_position, _ in enumerate(buffer[start:end]):
                for bit_position in range(self._bits):
                    bit_mask = 0x80 >> bit_position
                    bit_value = write_value & 0x80 >> bit_position
                    # Return clock to base
                    self._sclk.value = self._polarity
                    start_time = self._wait(start_time)
                    # Handle read on leading edge of clock.
                    if not self._phase:  # Mode 0, 2
                        if self._mosi is not None:
                            self._mosi.value = bit_value
                        if self._miso.value:
                            # Set bit to 1 at appropriate location.
                            buffer[byte_position] |= bit_mask
                        else:
                            # Set bit to 0 at appropriate location.
                            buffer[byte_position] &= ~bit_mask
                    # Flip clock off base
                    self._sclk.value = not self._polarity
                    start_time = self._wait(start_time)
                    # Handle read on trailing edge of clock.
                    if self._phase:  # Mode 1, 3
                        if self._mosi is not None:
                            self._mosi.value = bit_value
                        if self._miso.value:
                            # Set bit to 1 at appropriate location.
                            buffer[byte_position] |= bit_mask
                        else:
                            # Set bit to 0 at appropriate location.
                            buffer[byte_position] &= ~bit_mask

            # Return pins to base positions
            self._mosi.value = 0
            self._sclk.value = self._polarity

    def write_readinto(self,
                       buffer_out,
                       buffer_in,
                       *,
                       out_start=0,
                       out_end=None,
                       in_start=0,
                       in_end=None):
        """Write out the data in buffer_out while simultaneously reading data into buffer_in.
        The lengths of the slices defined by buffer_out[out_start:out_end] and
        buffer_in[in_start:in_end] must be equal. If buffer slice lengths are
        both 0, nothing happens.
        """
        if self._mosi is None:
            raise RuntimeError("Write attempted with no MOSI pin specified.")
        if self._miso is None:
            raise RuntimeError("Read attempted with no MISO pin specified.")
        if out_end is None:
            out_end = len(buffer_out)
        if in_end is None:
            in_end = len(buffer_in)
        if len(buffer_out[out_start:out_end]) != len(
                buffer_in[in_start:in_end]):
            raise RuntimeError("Buffer slices must be equal length")

        if self._check_lock():
            start_time = monotonic()
            for byte_position, _ in enumerate(buffer_out[out_start:out_end]):
                for bit_position in range(self._bits):
                    bit_mask = 0x80 >> bit_position
                    bit_value = (buffer_out[byte_position + out_start]
                                 & 0x80 >> bit_position)
                    in_byte_position = byte_position + in_start
                    # Return clock to 0
                    self._sclk.value = self._polarity
                    start_time = self._wait(start_time)
                    # Handle read on leading edge of clock.
                    if not self._phase:  # Mode 0, 2
                        self._mosi.value = bit_value
                        if self._miso.value:
                            # Set bit to 1 at appropriate location.
                            buffer_in[in_byte_position] |= bit_mask
                        else:
                            # Set bit to 0 at appropriate location.
                            buffer_in[in_byte_position] &= ~bit_mask
                    # Flip clock off base
                    self._sclk.value = not self._polarity
                    start_time = self._wait(start_time)
                    # Handle read on trailing edge of clock.
                    if self._phase:  # Mode 1, 3
                        self._mosi.value = bit_value
                        if self._miso.value:
                            # Set bit to 1 at appropriate location.
                            buffer_in[in_byte_position] |= bit_mask
                        else:
                            # Set bit to 0 at appropriate location.
                            buffer_in[in_byte_position] &= ~bit_mask

            # Return pins to base positions
            self._mosi.value = 0
            self._sclk.value = self._polarity

    # pylint: enable=too-many-branches

    @property
    def frequency(self):
        """Return the currently configured baud rate"""
        return self._baudrate
Beispiel #10
0
class PiperCommandCenter:
    def __init__(self,
                 joy_x_pin=board.A4,
                 joy_y_pin=board.A3,
                 joy_z_pin=board.D2,
                 joy_gnd_pin=board.A5,
                 dpad_l_pin=board.D3,
                 dpad_r_pin=board.D4,
                 dpad_u_pin=board.D1,
                 dpad_d_pin=board.D0,
                 outputScale=20.0,
                 deadbandCutoff=0.1,
                 weight=0.2):
        self.x_axis = PiperJoystickAxis(joy_x_pin,
                                        outputScale=outputScale,
                                        deadbandCutoff=deadbandCutoff,
                                        weight=weight)
        self.y_axis = PiperJoystickAxis(joy_y_pin,
                                        outputScale=outputScale,
                                        deadbandCutoff=deadbandCutoff,
                                        weight=weight)
        self.joy_z = PiperJoystickZ(joy_z_pin)
        self.dpad = PiperDpad(dpad_l_pin, dpad_r_pin, dpad_u_pin, dpad_d_pin)

        # Drive pin low if requested for easier joystick wiring
        if joy_gnd_pin is not None:
            # Provide a ground for the joystick - this is to facilitate
            # easier wiring
            self.joystick_gnd = DigitalInOut(joy_gnd_pin)
            self.joystick_gnd.direction = Direction.OUTPUT
            self.joystick_gnd.value = 0

        self.keyboard = Keyboard(usb_hid.devices)
        self.keyboard_layout = KeyboardLayoutUS(
            self.keyboard)  # Change for non-US
        self.mouse = Mouse(usb_hid.devices)

        # State
        #
        self.state = _UNWIRED
        self.timer = time.monotonic()
        self.last_mouse_wheel = time.monotonic()
        self.last_mouse = time.monotonic()
        self.dotstar_led = adafruit_dotstar.DotStar(board.APA102_SCK,
                                                    board.APA102_MOSI, 1)
        self.dotstar_led.brightness = 0.2
        self.up_pressed = False
        self.down_pressed = False
        self.left_pressed = False
        self.right_pressed = False

    def process(self):
        # Call the debouncing library frequently
        self.joy_z.update()
        self.dpad.update()

        dx = self.x_axis.readJoystickAxis()
        dy = self.y_axis.readJoystickAxis()

        # Command Center State Machine
        #
        if self.state == _UNWIRED:
            self.dotstar_led[0] = ((time.monotonic_ns() >> 23) % 256, 0, 0)
            if dx == 0 and dy == 0:
                self.state = _WAITING
                self.timer = time.monotonic()
        elif self.state == _WAITING:
            self.dotstar_led[0] = ((time.monotonic_ns() >> 23) % 256, 0, 0)
            if dx != 0 or dy != 0:
                self.state = _UNWIRED
            else:
                if time.monotonic() - self.timer > 0.5:
                    self.state = _JOYSTICK
        elif self.state == _JOYSTICK:
            self.dotstar_led[0] = (0, 255, 0)
            if self.joy_z.zPressed():
                self.timer = time.monotonic()
                self.state = _JWAITING
        elif self.state == _JWAITING:
            if not self.joy_z.zPressed():
                self.state = _JOYSTICK
            else:
                if time.monotonic() - self.timer > 1.0:
                    self.mouse.release(Mouse.LEFT_BUTTON)
                    self.mouse.release(Mouse.RIGHT_BUTTON)
                    self.state = _USERCODE
        elif self.state == _USERCODE:
            self.dotstar_led[0] = (0, 0, 0)
            self.dotstar_led.deinit()
            self.joystick_gnd.deinit()
            self.x_axis.deinit()
            self.y_axis.deinit()
            self.dpad.deinit()
            self.joy_z.deinit()
            try:
                # Load usercode.py
                __import__("usercode")
            except ImportError:
                print("Missing usercode.py file")
            # If we get here due to an exception or the user code exiting
            # then restart as it's probably going to by the most stable
            # strategy
            #
            supervisor.reload()

        # Command Center Joystick Handling
        #
        if self.state == _JOYSTICK or self.state == _JWAITING:
            # Determine mouse wheel direction
            #
            dwheel = 0
            if self.dpad.upPressed():
                dwheel = -1
            elif self.dpad.downPressed():
                dwheel = 1

            # Initial quick and dirty mouse movement pacing
            #
            if time.monotonic() - self.last_mouse > 0.005:
                self.last_mouse = time.monotonic()
                self.mouse.move(x=dx, y=dy)

            # Initial quick and dirty mouse scroll wheel pacing
            #
            if time.monotonic() - self.last_mouse_wheel > 0.1:
                self.last_mouse_wheel = time.monotonic()
                self.mouse.move(wheel=dwheel)

            if self.dpad.leftPressedEvent():
                self.mouse.press(Mouse.LEFT_BUTTON)
            elif self.dpad.leftReleasedEvent():
                self.mouse.release(Mouse.LEFT_BUTTON)

            if self.dpad.rightPressedEvent():
                self.mouse.press(Mouse.RIGHT_BUTTON)
            elif self.dpad.rightReleasedEvent():
                self.mouse.release(Mouse.RIGHT_BUTTON)
Beispiel #11
0
class PMS5003():
    #def __init__(self, baudrate=9600, pin_enable=board.D10, pin_reset=board.D11):

    MAX_RESET_TIME = 20.0  # 9.2 seconds seen in testing
    MIN_CMD_INTERVAL = 0.1  # mode changes with interval < 50ms break a PMS5003

    @staticmethod
    def _build_cmd_frame(cmd_bytes):
        """
        Builds a valid command frame byte array with checksum for given command bytes
        """
        if len(cmd_bytes) != 3:
            raise RuntimeError("Malformed command frame")
        cmd_frame = bytearray()
        cmd_frame.extend(PMS5003_SOF)
        cmd_frame.extend(cmd_bytes)
        cmd_frame.extend(sum(cmd_frame).to_bytes(2, "big"))
        return cmd_frame

    def __init__(self,
                 serial=None,
                 pin_reset=pimoroni_physical_feather_pins.pin23(),
                 pin_enable=pimoroni_physical_feather_pins.pin22(),
                 mode='active',
                 retries=5,
                 baudrate=9600):
        self._serial = None
        self._mode = 'active'  # device starts up in active mode

        self._baudrate = baudrate
        self._pin_enable = pin_enable
        self._enable = None
        self._pin_reset = pin_reset
        self._reset = None
        self._attempts = retries + 1 if retries else 1

        if mode not in ('active', 'passive'):
            raise ValueError("Invalid mode")

        # Exceptions are caught here as constructor has not
        # raised them in the prior versions
        try:
            self.setup(serial)
            if mode == 'passive':
                self.cmd_mode_passive()
        except RuntimeError:
            pass

    def cmd_mode_passive(self):
        """
        Sends command to device to enable 'passive' mode.
        In passive mode data frames are only sent in response to
        a read command.
        """
        self._mode = 'passive'

        time.sleep(self.MIN_CMD_INTERVAL)
        self._serial.reset_input_buffer()
        self._serial.write(self._build_cmd_frame(PMS5003_CMD_MODE_PASSIVE))
        # In rare cases a single data frame sneaks in giving FrameLengthError
        try:
            resp = self._read_data(PMS5003CmdResponse)
        except FrameLengthError:
            resp = self._read_data(PMS5003CmdResponse)
        time.sleep(self.MIN_CMD_INTERVAL)
        return resp

    def cmd_mode_active(self):
        """
        Sends command to device to enable 'active' mode.
        In active mode data frames are streamed continuously at intervals
        ranging from 200ms to 2.3 seconds.
        """
        self._mode = 'active'
        # mode changes with interval < 50ms break on a PMS5003
        time.sleep(self.MIN_CMD_INTERVAL)
        self._serial.reset_input_buffer()
        self._serial.write(self._build_cmd_frame(PMS5003_CMD_MODE_ACTIVE))
        # In rare cases a single data frame sneaks in giving FrameLengthError
        try:
            resp = self._read_data(PMS5003CmdResponse)
        except FrameLengthError:
            resp = self._read_data(PMS5003CmdResponse)
        time.sleep(self.MIN_CMD_INTERVAL)
        return resp

    def setup(self, serial=None):
        if self._pin_enable:
            self._enable = DigitalInOut(self._pin_enable)
            self._enable.direction = Direction.OUTPUT
            self._enable.value = True

        if self._pin_reset:
            self._reset = DigitalInOut(self._pin_reset)
            self._reset.direction = Direction.OUTPUT
            self._reset.value = True

        if self._serial is not None:
            self._serial.deinit()

        self._serial = busio.UART(
            board.TX, board.RX, baudrate=self._baudrate,
            timeout=4) if serial is None else serial

        self.reset()

    def reset(self):
        """This resets the device via a pin if one is defined.
           It restores passive mode as necessary."""
        if self._reset is None:
            return False

        time.sleep(0.1)
        self._reset.value = False
        self._serial.reset_input_buffer()
        time.sleep(0.1)
        self._reset.value = True

        # Wait for first data frame from the device
        # CircuitPython 6.0.0 on nRF52840 sometimes picks up 2 bogus bytes here
        start = time.monotonic()
        while True:
            if self.data_available():
                break
            elapsed = time.monotonic() - start
            if elapsed > self.MAX_RESET_TIME:
                raise ReadTimeoutError(
                    "PMS5003 Read Timeout: No response after reset")

        # After a reset device will be in active mode, restore passive mode
        if self._mode == "passive":
            _ = self._read_data()  # discard buffered active data frame
            self.cmd_mode_passive()

        return True

    def deinit(self):
        if self._enable is not None:
            self._enable.deinit()

        if self._reset is not None:
            self._reset.deinit()

        if self._serial is not None:
            self._serial.deinit()

    def data_available(self):
        """Returns boolean indicating if one or more data frames are waiting.
           Only for use in active mode."""
        return self._serial.in_waiting >= PMS5003Data.FRAME_LEN

    def read(self):
        """Read a data frame. In passive mode this will transmit a request for one.
           This will make additional attempts based on retries value in constructor
           if there are exceptions and only raise the first exception if all fail."""
        read_ex = None
        for _ in range(self._attempts):
            if self._mode == 'passive':
                self._cmd_passive_read()
            try:
                return self._read_data()
            except RuntimeError as ex:
                if read_ex is None:
                    read_ex = ex
        raise read_ex if read_ex else RuntimeError(
            "read failed - internal error")

    def _read_data(self, response_class=PMS5003Data):
        start = time.monotonic()

        sof_index = 0

        while True:
            elapsed = time.monotonic() - start
            if elapsed > 5:
                raise ReadTimeoutError(
                    "PMS5003 Read Timeout: Could not find start of frame")

            one_byte = self._serial.read(1)
            if one_byte is None or len(one_byte) == 0:
                raise SerialTimeoutError(
                    "PMS5003 Read Timeout: Failed to read start of frame byte")

            if ord(one_byte) == PMS5003_SOF[sof_index]:
                if sof_index == 0:
                    sof_index = 1
                elif sof_index == 1:
                    break
            else:
                sof_index = 0

        len_data = self._serial.read(2)  # Get frame length packet
        if len_data is None or len(len_data) != 2:
            raise SerialTimeoutError(
                "PMS5003 Read Timeout: Could not find length packet")
        frame_length = struct.unpack(">H", len_data)[0]
        response_class.check_data_len(frame_length, desc="Length field")

        raw_data = self._serial.read(frame_length)
        if raw_data is None or len(raw_data) != frame_length:
            read_len = "TIMEOUT" if raw_data is None else len(raw_data)
            raise SerialTimeoutError(
                "PMS5003 Read Timeout: Invalid frame length. "
                "Got {} bytes, expected {}.".format(read_len, frame_length))

        return response_class(raw_data, frame_length_bytes=len_data)

    def _cmd_passive_read(self):
        """
        Sends command to request a data frame while in 'passive'
        mode and immediately reads in frame.
        """
        self._serial.reset_input_buffer()
        self._serial.write(self._build_cmd_frame(PMS5003_CMD_READ))
Beispiel #12
0
if EPD_present:
    display.fill(Adafruit_EPD.WHITE)
    if Battery_Low:
        x = 60
        y = 40
        display.text('LOW', x, y, Adafruit_EPD.BLACK, size=5)
        x = 60
        y = 120
        display.text('BAT', x, y, Adafruit_EPD.BLACK, size=5)
    else:
        x = 60
        y = 80
        display.text('OFF', x, y, Adafruit_EPD.BLACK, size=5)

    display.display()

    display.power_down()

io_pwr.value = False

v33_pwr = DigitalInOut(SOC_GPIO_PIN_3V3_PWR)
v33_pwr.direction = Direction.OUTPUT
v33_pwr.value = False

button.deinit()
import alarm
pin_alarm = alarm.pin.PinAlarm(pin=SOC_GPIO_PIN_BUTTON,
                               value=False,
                               pull=False)
alarm.exit_and_deep_sleep_until_alarms(pin_alarm)
class Peripherals:
    """Peripherals Helper Class for the FunHouse Library"""

    # pylint: disable=too-many-instance-attributes, too-many-locals, too-many-branches, too-many-statements
    def __init__(self):
        # Dotstars
        self.dotstars = adafruit_dotstar.DotStar(board.DOTSTAR_CLOCK,
                                                 board.DOTSTAR_DATA,
                                                 5,
                                                 brightness=0.3)

        # Light Sensor
        self._light = AnalogIn(board.LIGHT)

        # Buttons
        self._buttons = []
        for pin in (board.BUTTON_DOWN, board.BUTTON_SELECT, board.BUTTON_UP):
            switch = DigitalInOut(pin)
            switch.direction = Direction.INPUT
            switch.pull = Pull.DOWN
            self._buttons.append(switch)

        # Cap Tocuh Pads
        self._ctp = []
        for pin in (
                board.CAP6,
                board.CAP7,
                board.CAP8,
                board.CAP13,
                board.CAP12,
                board.CAP11,
                board.CAP10,
                board.CAP9,
        ):
            cap = touchio.TouchIn(pin)
            self._ctp.append(cap)

        # LED
        self._led = DigitalInOut(board.LED)
        self._led.direction = Direction.OUTPUT

        # PIR Sensor
        self._pir = DigitalInOut(board.PIR_SENSE)
        self._pir.direction = Direction.INPUT

    @staticmethod
    def play_tone(frequency, duration):
        """Automatically Enable/Disable the speaker and play
        a tone at the specified frequency for the specified duration
        It will attempt to play the sound up to 3 times in the case of
        an error.
        """
        if frequency <= 0:
            raise ValueError("The frequency has to be greater than 0.")
        attempt = 0
        # Try up to 3 times to play the sound
        while attempt < 3:
            try:
                simpleio.tone(board.SPEAKER, frequency, duration)
                break
            except NameError:
                pass
            attempt += 1

    def set_dotstars(self, *values):
        """Set the dotstar values to the provided values"""
        for i, value in enumerate(values[:len(self.dotstars)]):
            self.dotstars[i] = value

    def deinit(self):
        """Call deinit on all resources to free them"""
        self.dotstars.deinit()
        for button in self._buttons:
            button.deinit()
        for ctp in self._ctp:
            ctp.deinit()
        self._light.deinit()
        self._led.deinit()
        self._pir.deinit()

    @property
    def button_down(self):
        """
        Return whether Down Button is pressed
        """
        return self._buttons[0].value

    @property
    def button_sel(self):
        """
        Return whether Sel Button is pressed
        """
        return self._buttons[1].value

    @property
    def button_up(self):
        """
        Return whether Up Button is pressed
        """
        return self._buttons[2].value

    @property
    def any_button_pressed(self):
        """
        Return whether any button is pressed
        """
        return True in [button.value for button in enumerate(self._buttons)]

    @property
    def captouch6(self):
        """
        Return whether CT6 Touch Pad is touched
        """
        return self._ctp[0].value

    @property
    def captouch7(self):
        """
        Return whether CT7 Touch Pad is touched
        """
        return self._ctp[1].value

    @property
    def captouch8(self):
        """
        Return whether CT8 Touch Pad is touched
        """
        return self._ctp[2].value

    @property
    def slider(self):
        """
        Return the slider position value in the range of 0.0-1.0 or None if not touched
        """
        val = 0
        cap_map = b"\x01\x03\x02\x05\x04\x0c\x08\x18\x10"
        for cap in range(5):
            raw = self._ctp[cap + 3].raw_value
            if raw > 15000:
                val += 1 << (cap)
        for i, pos in enumerate(tuple(cap_map)):
            if val == pos:
                print(i, len(cap_map) - 1)
                return round(i / (len(cap_map) - 1), 1)
        return None

    @property
    def light(self):
        """
        Return the value of the light sensor. The neopixel_disable property
        must be false to get a value.

        .. code-block:: python

            import time
            from adafruit_funhouse import FunHouse

            funhouse = FunHouse()

            while True:
                print(funhouse.peripherals.light)
                time.sleep(0.01)

        """
        return self._light.value

    @property
    def led(self):
        """
        Return or set the value of the LED
        """
        return self._led.value

    @led.setter
    def led(self, value):
        self._led.value = bool(value)

    @property
    def pir_sensor(self):
        """
        Return the value of the PIR Sensor
        """
        return self._pir.value
Beispiel #14
0
class HCSR04:
    """Control a HC-SR04 ultrasonic range sensor.

    Example use:

    ::

        import time
        import board

        import adafruit_hcsr04

        sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.D2, echo_pin=board.D3)


        while True:
            try:
                print((sonar.distance,))
            except RuntimeError:
                print("Retrying!")
                pass
            time.sleep(0.1)
    """
    def __init__(self, trigger_pin, echo_pin, *, timeout=0.1):
        """
        :param trigger_pin: The pin on the microcontroller that's connected to the
            ``Trig`` pin on the HC-SR04.
        :type trig_pin: microcontroller.Pin
        :param echo_pin: The pin on the microcontroller that's connected to the
            ``Echo`` pin on the HC-SR04.
        :type echo_pin: microcontroller.Pin
        :param float timeout: Max seconds to wait for a response from the
            sensor before assuming it isn't going to answer. Should *not* be
            set to less than 0.05 seconds!
        """
        self._timeout = timeout
        self._trig = DigitalInOut(trigger_pin)
        self._trig.direction = Direction.OUTPUT

        if _USE_PULSEIO:
            self._echo = PulseIn(echo_pin)
            self._echo.pause()
            self._echo.clear()
        else:
            self._echo = DigitalInOut(echo_pin)
            self._echo.direction = Direction.INPUT

    def __enter__(self):
        """Allows for use in context managers."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Automatically de-initialize after a context manager."""
        self.deinit()

    def deinit(self):
        """De-initialize the trigger and echo pins."""
        self._trig.deinit()
        self._echo.deinit()

    @property
    def distance(self):
        """Return the distance measured by the sensor in cm.

        This is the function that will be called most often in user code. The
        distance is calculated by timing a pulse from the sensor, indicating
        how long between when the sensor sent out an ultrasonic signal and when
        it bounced back and was received again.

        If no signal is received, we'll throw a RuntimeError exception. This means
        either the sensor was moving too fast to be pointing in the right
        direction to pick up the ultrasonic signal when it bounced back (less
        likely), or the object off of which the signal bounced is too far away
        for the sensor to handle. In my experience, the sensor can detect
        objects over 460 cm away.

        :return: Distance in centimeters.
        :rtype: float
        """
        return self._dist_two_wire()  # at this time we only support 2-wire meausre

    def _dist_two_wire(self):
        if _USE_PULSEIO:
            self._echo.clear()       # Discard any previous pulse values
        self._trig.value = True  # Set trig high
        time.sleep(0.00001)      # 10 micro seconds 10/1000/1000
        self._trig.value = False # Set trig low

        pulselen = None
        timestamp = time.monotonic()
        if _USE_PULSEIO:
            self._echo.resume()
            while not self._echo:
                # Wait for a pulse
                if (time.monotonic() - timestamp) > self._timeout:
                    self._echo.pause()
                    raise RuntimeError("Timed out")
            self._echo.pause()
            pulselen = self._echo[0]
        else:
            # OK no hardware pulse support, we'll just do it by hand!
            # hang out while the pin is low
            while not self._echo.value:
                if time.monotonic() - timestamp > self._timeout:
                    raise RuntimeError("Timed out")
            timestamp = time.monotonic()
            # track how long pin is high
            while self._echo.value:
                if time.monotonic() - timestamp > self._timeout:
                    raise RuntimeError("Timed out")
            pulselen = time.monotonic() - timestamp
            pulselen *= 1000000 # convert to us to match pulseio
        if pulselen >= 65535:
            raise RuntimeError("Timed out")

        # positive pulse time, in seconds, times 340 meters/sec, then
        # divided by 2 gives meters. Multiply by 100 for cm
        # 1/1000000 s/us * 340 m/s * 100 cm/m * 2 = 0.017
        return pulselen * 0.017
Beispiel #15
0
class Peripherals:
    """Peripherals Helper Class for the MagTag Library"""

    # pylint: disable=too-many-instance-attributes, too-many-locals, too-many-branches, too-many-statements
    def __init__(self):
        # Neopixels
        self.neopixels = neopixel.NeoPixel(board.NEOPIXEL, 4, brightness=0.3)
        self._neopixel_disable = DigitalInOut(board.NEOPIXEL_POWER)
        self._neopixel_disable.direction = Direction.OUTPUT
        self._neopixel_disable.value = False

        # Battery Voltage
        self._batt_monitor = AnalogIn(board.BATTERY)

        # Speaker Enable
        self._speaker_enable = DigitalInOut(board.SPEAKER_ENABLE)
        self._speaker_enable.direction = Direction.OUTPUT
        self._speaker_enable.value = False

        # Light Sensor
        self._light = AnalogIn(board.LIGHT)

        # Buttons
        self.buttons = []
        for pin in (board.BUTTON_A, board.BUTTON_B, board.BUTTON_C, board.BUTTON_D):
            switch = DigitalInOut(pin)
            switch.direction = Direction.INPUT
            switch.pull = Pull.UP
            self.buttons.append(switch)

    def play_tone(self, frequency, duration):
        """Automatically Enable/Disable the speaker and play
        a tone at the specified frequency for the specified duration
        It will attempt to play the sound up to 3 times in the case of
        an error.
        """
        if frequency <= 0:
            raise ValueError("The frequency has to be greater than 0.")
        self._speaker_enable.value = True
        attempt = 0
        # Try up to 3 times to play the sound
        while attempt < 3:
            try:
                simpleio.tone(board.SPEAKER, frequency, duration)
                break
            except NameError:
                pass
            attempt += 1
        self._speaker_enable.value = False

    def deinit(self):
        """Call deinit on all resources to free them"""
        self.neopixels.deinit()
        self._neopixel_disable.deinit()
        self._speaker_enable.deinit()
        for button in self.buttons:
            button.deinit()
        self._batt_monitor.deinit()
        self._light.deinit()

    @property
    def battery(self):
        """Return the voltage of the battery"""
        return (self._batt_monitor.value / 65535.0) * 3.3 * 2

    @property
    def neopixel_disable(self):
        """
        Enable or disable the neopixels for power savings
        """
        return self._neopixel_disable.value

    @neopixel_disable.setter
    def neopixel_disable(self, value):
        self._neopixel_disable.value = value

    @property
    def speaker_disable(self):
        """
        Enable or disable the speaker for power savings
        """
        return not self._speaker_enable.value

    @speaker_disable.setter
    def speaker_disable(self, value):
        self._speaker_enable.value = not value

    @property
    def button_a_pressed(self):
        """
        Return whether Button A is pressed
        """
        return not self.buttons[0].value

    @property
    def button_b_pressed(self):
        """
        Return whether Button B is pressed
        """
        return not self.buttons[1].value

    @property
    def button_c_pressed(self):
        """
        Return whether Button C is pressed
        """
        return not self.buttons[2].value

    @property
    def button_d_pressed(self):
        """
        Return whether Button D is pressed
        """
        return not self.buttons[3].value

    @property
    def any_button_pressed(self):
        """
        Return whether any button is pressed
        """
        return False in [self.buttons[i].value for i in range(0, 4)]

    @property
    def light(self):
        """
        Return the value of the light sensor. The neopixel_disable property
        must be false to get a value.

        .. code-block:: python

            import time
            from adafruit_magtag.magtag import MagTag

            magtag = MagTag()

            while True:
                print(magtag.peripherals.light)
                time.sleep(0.01)

        """
        return self._light.value
class Ohmite:
    """
    Types: 0 = round, 1 = long , 2 = short
    """

    # expect _wiper, _ref, _v_1, _v_2, _v_3, _type=0):
    # or _wiper, _ref, _v_1, _v_2,  _type=(1/2):
    #
    def __init__(self, *args, **kwargs):
        if "type" in kwargs:
            self._type = kwargs["type"]
        else:
            self._type = 0

        self._ref = DigitalInOut(args[1])
        self._ANALOG_RESOLUTION = 65536
        self._VOLTAGE = 3.3
        if self._type == 0:  # this is a round sensor
            self._ZERO_OFFSET = 800
            self._READ_RANGE = 1450
            self._wiper = AnalogIn(args[0])
            self._d0 = DigitalInOut(args[2])
            self._d120 = DigitalInOut(args[3])
            self._d240 = DigitalInOut(args[4])
            self._ZERO_OFFSET = 800
            self._READ_RANGE = 1450
            self._LENGTH = 120
        else:  # this is a linear sensor
            self._wiper_pin = args[0]
            self._wiper = DigitalInOut(args[0])
            self._v1 = DigitalInOut(args[2])
            self._v2 = DigitalInOut(args[3])
            if self._type == 1:
                self._ZERO_OFFSET = 200
                self._READ_RANGE = 2600
                self._LENGTH = 100
            else:
                self._ZERO_OFFSET = 500
                self._READ_RANGE = 1900
                self._LENGTH = 55
        # print(args, kwargs)

    def begin(self):
        if self._type == 0:
            self._ref.direction = Direction.OUTPUT
            self._ref.value = 1
            self._d0.direction = Direction.OUTPUT
            self._d0.value = 1
            self._d120.direction = Direction.OUTPUT
            self._d120.value = 1
            self._d240.direction = Direction.OUTPUT
            self._d240.value = 0
        else:
            self._v1.direction = Direction.OUTPUT
            self._v1.value = 0
            self._v2.direction = Direction.OUTPUT
            self._v2.value = 0
            self._wiper.direction = Direction.OUTPUT
            self._wiper.value = 0
            self._ref.direction = Direction.OUTPUT
            self._ref.value = 0

    # Generic command
    def get_position(self, tail_to_tip=True):
        if self._type == 0:
            return self._get_round_position()
        if self._type == 1 or self._type == 2:
            return self._get_linear_position(tail_to_tip)

    def get_force(self):
        if self._type == 0:
            return self._get_round_force()
        if self._type == 1 or self._type == 2:
            return self._get_linear_force()

    # Linear sensors
    def _get_linear_position(self, tail_to_tip=True):
        self._wiper.deinit()
        l_wiper = AnalogIn(self._wiper_pin)
        self._ref.switch_to_input(pull=Pull.DOWN)

        if tail_to_tip:  # Read from tail end
            self._v1.value = 1
            time.sleep(0.001)
            value = self._get_voltage(l_wiper)
            self._v1.value = 0
        else:
            self._v2.value = 1
            time.sleep(0.001)
            value = self._get_voltage(l_wiper)
            self._v2.value = 0

        l_wiper.deinit()
        self._wiper = DigitalInOut(self._wiper_pin)
        self._wiper.direction = Direction.OUTPUT
        self._wiper.value = 0
        self._ref.switch_to_output(value=False)
        return self._get_millimeters(value)

    def _get_millimeters(self, voltage):
        value = int((((voltage * 1000) - self._ZERO_OFFSET) * self._LENGTH) /
                    self._READ_RANGE)
        if value < 0:
            value = 0
        if value > self._LENGTH:
            value = self._LENGTH
        return value

    # this is method 3 from the implementation guide.
    # Section 4.2.3, page 5
    # https://www.mouser.com/pdfdocs/Ohmite-FSP-Integration-Guide-V1-0_27-03-18.pdf
    def _get_linear_force(self):
        self._wiper.deinit()
        l_wiper = AnalogIn(self._wiper_pin)
        self._ref.value = 0
        self._v1.switch_to_output(value=True)
        self._v2.switch_to_input()
        time.sleep(0.001)
        wiper_1 = l_wiper.value

        self._v2.switch_to_output(value=True)
        self._v1.switch_to_input()
        time.sleep(0.001)
        wiper_2 = l_wiper.value

        l_wiper.deinit()
        self._wiper = DigitalInOut(self._wiper_pin)
        self._wiper.direction = Direction.OUTPUT
        self._wiper.value = 0
        self._v1.direction = Direction.OUTPUT
        self._v1.value = 0
        self._v2.value = 0

        return ((
            (wiper_1 + wiper_2) / 2) * self._VOLTAGE) / self._ANALOG_RESOLUTION

    # Round sensor helpers

    def _calc_position(self, low, high, off):
        # off should be the DX pin  Disable
        off.switch_to_input()
        high.value = 1
        low.value = 0
        time.sleep(0.001)
        wiper_v = self._get_voltage(self._wiper)
        # print(wiper_v)
        # Convert to milli volts and apply offsets to wiper_v
        _angle = ((((wiper_v * 1000) - self._ZERO_OFFSET) * self._LENGTH) /
                  self._READ_RANGE)
        # print(angle)
        # off should be reset to output
        off.switch_to_output(value=False)

        return int(_angle)

    def _get_round_position(self):
        # Read analog voltage on D 1
        self._d0.value = 1
        self._d120.value = 1
        self._d240.value = 0
        time.sleep(0.001)
        d3 = self._wiper.value

        self._d0.value = 0
        self._d120.value = 1
        self._d240.value = 1
        time.sleep(0.001)
        d1 = self._wiper.value

        self._d0.value = 1
        self._d120.value = 0
        self._d240.value = 1
        time.sleep(0.001)
        d2 = self._wiper.value

        _angle = 0
        # which voltage is the lowest:
        # print(d1, d2, d3, f1)
        if d1 < d2 and d1 < d3:
            if d2 < d3:
                # d1 and d2
                # print ("d1:d2")
                _angle = self._calc_position(self._d0, self._d120, self._d240)
            else:
                # d1 and d3
                # print("d1:d3")
                _angle = self._calc_position(self._d240, self._d0, self._d120)
                _angle = _angle + 240

        if d2 < d1 and d2 < d3:
            if d1 < d3:
                # print ("d2:d1")
                _angle = self._calc_position(self._d0, self._d120, self._d240)
            else:
                # print ("d2:d3")
                _angle = self._calc_position(self._d120, self._d240, self._d0)
                _angle = _angle + 120

        if d3 < d1 and d3 < d2:
            if d1 < d2:
                # print ("d3:d1")
                _angle = self._calc_position(self._d240, self._d0, self._d120)
                _angle = _angle + 240
            else:
                # print ("d3:d2")
                _angle = self._calc_position(self._d120, self._d240, self._d0)
                _angle = _angle + 120

        if _angle < 0 or _angle > 360:
            _angle = 0

        return _angle

    def _get_round_force(self):
        # read force
        self._d0.value = 1
        self._d120.value = 1
        self._d240.value = 1
        self._ref.switch_to_output(value=False)
        time.sleep(0.001)
        _f = self._get_voltage(self._wiper)
        self._ref.switch_to_input()
        return _f

    def _get_voltage(self, pin):
        return (pin.value * self._VOLTAGE) / self._ANALOG_RESOLUTION
Beispiel #17
0
            selected -= 4
            rect.y -= 62
            display.refresh()
            print("up")
            time.sleep(5)
            continue

        if not btnC.value and selected < 4:
            selected += 4
            rect.y += 62
            display.refresh()
            print("down")
            time.sleep(5)
            continue

        if not btnD.value and selected != 3 and selected != 7:
            selected += 1
            rect.x += 74
            display.refresh()
            print("right")
            time.sleep(5)
            continue

btnA.deinit()
btnB.deinit()
btnC.deinit()
btnD.deinit()

print("Starting ", projects[int(alarm.sleep_memory[0])])
__import__("/projects/" + projects[int(alarm.sleep_memory[0])])
Beispiel #18
0
class GroveUltrasonicRanger:
    """Control a Grove ultrasonic range sensor.

	Example use:

	::

		import time
		import board

		import grove_ultrasonic_ranger

		sonar = grove_ultrasonic_ranger.GroveUltrasonicRanger(sig_pin=board.D2)


		while True:
			try:
				print((sonar.distance,))
			except RuntimeError as e:
				print("Retrying due to exception =", e)
				pass
			time.sleep(0.1)
	"""
    def __init__(self, sig_pin, unit=1.0, timeout=1.0):
        """
		:param sig_pin: The pin on the microcontroller that's connected to the
			``Sig`` pin on the GroveUltrasonicRanger.
		:type sig_pin: microcontroller.Pin
		:param float unit: pass in conversion factor for unit conversions from cm
			for example 2.54 would convert to inches.
		:param float timeout: Max seconds to wait for a response from the
			sensor before assuming it isn't going to answer. Should *not* be
			set to less than 0.05 seconds!
		"""
        self._unit = unit
        self._timeout = timeout * TICKS_PER_SEC

        if _USE_PULSEIO:
            self._sig = PulseIn(sig_pin)
            self._sig.pause()
            self._sig.clear()
        else:
            self._sig = DigitalInOut(sig_pin)
            self._sig.direction = Direction.OUTPUT
            self._sig.value = False  # Set trig low

    def __enter__(self):
        """Allows for use in context managers."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Automatically de-initialize after a context manager."""
        self.deinit()

    def deinit(self):
        """De-initialize the sig pin."""
        self._sig.deinit()

    @property
    def distance(self):
        """Return the distance measured by the sensor in cm (or user specified units.)

		This is the function that will be called most often in user code. The
		distance is calculated by timing a pulse from the sensor, indicating
		how long between when the sensor sent out an ultrasonic signal and when
		it bounced back and was received again.

		If no signal is received, we'll throw a RuntimeError exception. This means
		either the sensor was moving too fast to be pointing in the right
		direction to pick up the ultrasonic signal when it bounced back (less
		likely), or the object off of which the signal bounced is too far away
		for the sensor to handle. In my experience, the sensor can detect
		objects over 460 cm away.

		:return: Distance in centimeters (can be divided by a unit conv factor.)
		:rtype: float
		"""
        return self._dist_one_wire()

    def _dist_one_wire(self):
        if _USE_PULSEIO:
            self._sig.pause()
            self._sig.clear()  # Discard any previous pulse values
        else:
            #self._sig.direction = Direction.OUTPUT
            self._sig.value = True  # Set trig high
            time.sleep(0.00001)  # 10 micro seconds 10/1000/1000
            self._sig.value = False  # Set trig low
            self._sig.direction = Direction.INPUT

        pulselen = None
        timestamp = MONOTONIC_TICKS()
        if _USE_PULSEIO:
            self._sig.resume(10)
            while not self._sig:
                # Wait for a pulse
                if (MONOTONIC_TICKS() - timestamp) > self._timeout:
                    self._sig.pause()
                    raise RuntimeError(
                        "Timed out (pulseio waiting for a pulse)")
            self._sig.pause()
            pulselen = self._sig[0]
        else:
            # OK no hardware pulse support, we'll just do it by hand!
            # hang out while the pin is low
            while not self._sig.value:
                if MONOTONIC_TICKS() - timestamp > self._timeout:
                    self._sig.direction = Direction.OUTPUT
                    raise RuntimeError(
                        "Timed out (gpio, waiting for pulse leading edge)")
            timestamp = MONOTONIC_TICKS()
            # track how long pin is high
            while self._sig.value:
                if MONOTONIC_TICKS() - timestamp > self._timeout:
                    self._sig.direction = Direction.OUTPUT
                    raise RuntimeError(
                        "Timed out (gpio, waiting for pulse trailing edge)")
            pulselen = MONOTONIC_TICKS() - timestamp
            self._sig.direction = Direction.OUTPUT
            pulselen *= (1000000 / TICKS_PER_SEC
                         )  # convert to us to match pulseio
        if pulselen >= 65535:
            raise RuntimeError("Timed out (unreasonable pulse length)")

        # positive pulse time, in seconds, times 340 meters/sec, then
        # divided by 2 gives meters. Multiply by 100 for cm
        # 1/1000000 s/us * 340 m/s * 100 cm/m * 2 = 0.017
        # Divide by the supplied unit conversion factor
        return (pulselen * 0.017) / self._unit
class HCSR04:
    """Control a HC-SR04 ultrasonic range sensor.

    Example use:

    ::

        import time
        import board

        import adafruit_hcsr04

        sonar = adafruit_hcsr04.HCSR04(trigger_pin=board.D2, echo_pin=board.D3)


        while True:
            try:
                print((sonar.distance,))
            except RuntimeError:
                print("Retrying!")
                pass
            time.sleep(0.1)
    """
    def __init__(self, trigger_pin, echo_pin, *, timeout=0.1):
        """
        :param trigger_pin: The pin on the microcontroller that's connected to the
            ``Trig`` pin on the HC-SR04.
        :type trig_pin: microcontroller.Pin
        :param echo_pin: The pin on the microcontroller that's connected to the
            ``Echo`` pin on the HC-SR04.
        :type echo_pin: microcontroller.Pin
        :param float timeout: Max seconds to wait for a response from the
            sensor before assuming it isn't going to answer. Should *not* be
            set to less than 0.05 seconds!
        """
        self._timeout = timeout
        self._trig = DigitalInOut(trigger_pin)
        self._trig.direction = Direction.OUTPUT

        if _USE_PULSEIO:
            self._echo = PulseIn(echo_pin)
            self._echo.pause()
            self._echo.clear()
        else:
            self._echo = DigitalInOut(echo_pin)
            self._echo.direction = Direction.INPUT

    def __enter__(self):
        """Allows for use in context managers."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Automatically de-initialize after a context manager."""
        self.deinit()

    def deinit(self):
        """De-initialize the trigger and echo pins."""
        self._trig.deinit()
        self._echo.deinit()

    @property
    def distance(self):
        """Return the distance measured by the sensor in cm.

        This is the function that will be called most often in user code. The
        distance is calculated by timing a pulse from the sensor, indicating
        how long between when the sensor sent out an ultrasonic signal and when
        it bounced back and was received again.

        If no signal is received, we'll throw a RuntimeError exception. This means
        either the sensor was moving too fast to be pointing in the right
        direction to pick up the ultrasonic signal when it bounced back (less
        likely), or the object off of which the signal bounced is too far away
        for the sensor to handle. In my experience, the sensor can detect
        objects over 460 cm away.

        :return: Distance in centimeters.
        :rtype: float
        """
        return self._dist_two_wire(
        )  # at this time we only support 2-wire meausre

    def _dist_two_wire(self):
        if _USE_PULSEIO:
            self._echo.clear()  # Discard any previous pulse values
        self._trig.value = True  # Set trig high
        time.sleep(0.00001)  # 10 micro seconds 10/1000/1000
        self._trig.value = False  # Set trig low

        pulselen = None
        timestamp = time.monotonic()
        if _USE_PULSEIO:
            self._echo.resume()
            while not self._echo:
                # Wait for a pulse
                if (time.monotonic() - timestamp) > self._timeout:
                    self._echo.pause()
                    raise RuntimeError("Timed out")
            self._echo.pause()
            pulselen = self._echo[0]
        else:
            # OK no hardware pulse support, we'll just do it by hand!
            # hang out while the pin is low
            while not self._echo.value:
                if time.monotonic() - timestamp > self._timeout:
                    raise RuntimeError("Timed out")
            timestamp = time.monotonic()
            # track how long pin is high
            while self._echo.value:
                if time.monotonic() - timestamp > self._timeout:
                    raise RuntimeError("Timed out")
            pulselen = time.monotonic() - timestamp
            pulselen *= 1000000  # convert to us to match pulseio
        if pulselen >= 65535:
            raise RuntimeError("Timed out")

        # positive pulse time, in seconds, times 340 meters/sec, then
        # divided by 2 gives meters. Multiply by 100 for cm
        # 1/1000000 s/us * 340 m/s * 100 cm/m * 2 = 0.017
        return pulselen * 0.017
Beispiel #20
0
class PiperDpad:
    def __init__(self,
                 dpad_l_pin=board.D3,
                 dpad_r_pin=board.D4,
                 dpad_u_pin=board.D1,
                 dpad_d_pin=board.D0):
        # Setup DPAD
        #
        self.left_pin = DigitalInOut(dpad_l_pin)
        self.left_pin.direction = Direction.INPUT
        self.left_pin.pull = Pull.UP
        self.left = Debouncer(self.left_pin)

        self.right_pin = DigitalInOut(dpad_r_pin)
        self.right_pin.direction = Direction.INPUT
        self.right_pin.pull = Pull.UP
        self.right = Debouncer(self.right_pin)

        self.up_pin = DigitalInOut(dpad_u_pin)
        self.up_pin.direction = Direction.INPUT
        self.up_pin.pull = Pull.UP
        self.up = Debouncer(self.up_pin)

        self.down_pin = DigitalInOut(dpad_d_pin)
        self.down_pin.direction = Direction.INPUT
        self.down_pin.pull = Pull.UP
        self.down = Debouncer(self.down_pin)

    def deinit(self):
        self.up_pin.deinit()
        self.down_pin.deinit()
        self.left_pin.deinit()
        self.right_pin.deinit()

    def update(self):
        self.left.update()
        self.right.update()
        self.up.update()
        self.down.update()

    def leftPressed(self):
        return not self.left.value

    def leftPressedEvent(self):
        return self.left.fell

    def leftReleasedEvent(self):
        return self.left.rose

    def rightPressed(self):
        return not self.right.value

    def rightPressedEvent(self):
        return self.right.fell

    def rightReleasedEvent(self):
        return self.right.rose

    def upPressed(self):
        return not self.up.value

    def upPressedEvent(self):
        return self.up.fell

    def upReleasedEvent(self):
        return self.up.rose

    def downPressed(self):
        return not self.down.value

    def downPressedEvent(self):
        return self.down.fell

    def downReleasedEvent(self):
        return self.down.rose