class RadPowerRail: def __init__(self, pgpin, analogpin=None): self.pg = DigitalInOut(pgpin) self.pg.switch_to_input(pull=Pull.UP) if analogpin: self.mon = AnalogIn(analogpin) else: self.mon = None
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
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.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 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
class RunGo: groundColor_list = ((128, 128, 128), (255, 0, 0), (128, 128, 0), (0, 255, 0), (0, 128, 128), (0, 0, 255), (128, 0, 128)) groundColor_name = ('White', 'Red', 'Yellow', 'Green', 'Cyan', 'Blue', 'Purple') def __init__(self, enButtons=True): self._buttonA = None self._buttonB = None self._enbuttons = False if enButtons: self._enbuttons = True self._buttonA = DigitalInOut(board.IO43) self._buttonA.switch_to_input(pull=Pull.UP) self._db_buttonA = Debouncer(self._buttonA, 0.01, True) self._buttonB = DigitalInOut(board.IO44) self._buttonB.switch_to_input(pull=Pull.UP) self._db_buttonB = Debouncer(self._buttonB, 0.01, True) # 3x Neopixels RGB pixels: IO0 self._pixels = neopixel.NeoPixel( board.IO0, 3, \ brightness=0.5, auto_write=False, pixel_order=neopixel.GRB ) self._colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] for i in range(3): self._pixels[i] = self._colors[i] self._pixels.show() self._pixelsRotationDt = 0.2 self._pixelsRotationSt = time.monotonic() # Sense color Sensor (颜色传感器): IO7 self._colorSensor = AnalogIn(board.IO7) # Lighting Sensor (光强度传感器): IO8--leftLightSensor, IO9--rightLightSensor self._leftLightSensor = AnalogIn(board.IO8) self._rightLightSensor = AnalogIn(board.IO9) # left and right head-LED: IO17--rightHeadLED, IO18--leftHeadLED self._leftHeadLED = DigitalInOut(board.IO18) self._leftHeadLED.direction = Direction.OUTPUT self._leftHeadLED.value = 0 self._rightHeadLED = DigitalInOut(board.IO17) self._rightHeadLED.direction = Direction.OUTPUT self._rightHeadLED.value = 0 # Ultrasonic module (超声波模块): IO11--trig, IO10--echo self._timeout = 0.1 self._trig = DigitalInOut(board.IO11) self._trig.direction = Direction.OUTPUT self._trig.value = 0 if _USE_PULSEIO: self._echo = PulseIn(board.IO10) self._echo.pause() self._echo.clear() else: self._echo = DigitalInOut(board.IO10) self._echo.direction = Direction.INPUT # Tracking sensors (循迹传感器): IO4--rightTracker, IO3--rightTracker self._leftTracker = DigitalInOut(board.IO4) self._leftTracker.direction = Direction.INPUT self._rightTracker = DigitalInOut(board.IO3) self._rightTracker.direction = Direction.INPUT # Motor (Right): IO41--rightMotor1IN, IO42--rightMotor2IN self._rightMotor1IN = PWMOut(board.IO41, frequency=100, duty_cycle=0) self._rightMotor2IN = PWMOut(board.IO42, frequency=100, duty_cycle=0) # Motor (Left): IO12--leftMotor1IN, IO40--leftMotor2IN self._leftMotor1IN = PWMOut(board.IO12, frequency=100, duty_cycle=0) self._leftMotor2IN = PWMOut(board.IO40, frequency=100, duty_cycle=0) # state of button A @property def button_A(self): """ to check the state of Button-A on the RunGo this example to check the state of Button-A To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: if car.button_A: print('A be pressed') time.sleep(0.05) """ if self._enbuttons: return not self._buttonA.value else: return False # state of button B @property def button_B(self): """ to check the state of Button-B on the RunGo this example to check the state of Button-B To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: if car.button_B: print('B be pressed') time.sleep(0.05) """ if self._enbuttons: return not self._buttonB.value else: return False def buttons_update(self): """ to update the state of Button-A, and Button-B on the RunGo this example to update the state of Button-A, and Button-B To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_A_wasPressed: print('A be pressed') if car.button_B_wasPressed: print('B be pressed') """ if self._enbuttons: self._db_buttonA.read() self._db_buttonB.read() else: pass @property def button_A_wasPressed(self): """ to check the state of Button-A on the RunGo this example to check the state of Button-A To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_A_wasPressed: print('A be pressed') """ if self._enbuttons: return self._db_buttonA.wasPressed else: return False @property def button_A_wasReleased(self): """ to check the state of Button-A on the RunGo this example to check the state of Button-A To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_A_wasReleased: print('A be released') """ if self._enbuttons: return self._db_buttonA.wasReleased else: return False def button_A_pressedFor(self, t_s): """ to check the state of Button-A on the RunGo this example to check the state of Button-A To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_A_pressedFor(2.0): print('A be preased longly over 2.0 second') """ if self._enbuttons: return self._db_buttonA.pressedFor(t_s) else: return False @property def button_B_wasPressed(self): """ to check the state of Button-B on the RunGo this example to check the state of Button-B To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_B_wasPressed: print('B be pressed') """ if self._enbuttons: return self._db_buttonB.wasPressed else: return False @property def button_B_wasReleased(self): """ to check the state of Button-B on the RunGo this example to check the state of Button-B To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_B_wasReleased: print('B be released') """ if self._enbuttons: return self._db_buttonB.wasReleased else: return False def button_B_pressedFor(self, t_s): """ to check the state of Button-B on the RunGo this example to check the state of Button-B To use with the IoTs2: .. code-block:: python from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.buttons_update() if car.button_B_pressedFor(2.0): print('B be preased longly over 2.0 second') """ if self._enbuttons: return self._db_buttonB.pressedFor(t_s) else: return False @property def pixels(self): """ to control the pixels[0..2] on the bottom of RunGo this example to control the color of three RGB LEDs To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() colors = [(255,0,0), (0,255,0), (0,0,255)] while True: for i in range(3): car.pixels[i] = colors[i] car.pixels.show() # round colors tc = colors[0] colors[0] = colors[1] colors[1] = colors[2] colors[2] = tc time.sleep(0.5) """ return self._pixels @property def pixelsColor(self): c = (self._colors[0], self._colors[1], self._colors[2]) return c @pixelsColor.setter def pixelsColor(self, colors): ln = min(len(colors), 3) for i in range(ln): self._pixels[i] = colors[i] self._colors[i] = colors[i] self._pixels.show() def pixelsRotation(self, dt=None): if not dt == None: self._pixelsRotationDt = dt et = time.monotonic() if (et - self._pixelsRotationSt) >= self._pixelsRotationDt: self._pixelsRotationSt = et tc = self._colors[0] self._colors[0] = self._colors[1] self._colors[1] = self._colors[2] self._colors[2] = tc for i in range(3): self._pixels[i] = self._colors[i] self._pixels.show() def motor(self, lspeed=50, rspeed=-50): """ Dual DC-Motor control interface to achieve forward, backward, turn left and turn right this example to demostrate car forward, backward, turn left and turn right To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() car.motor(50, 50) # forward with 50 speed (max-speed: 255) time.sleep(1.2) # runing time (1.2s) car.motor(-50, -50) # backward with 50 speed (max-speed: 255) time.sleep(1.2) # runing time (1.2s) car.motor(-50, 50) # turn left with car center time.sleep(2.0) # runing time (2s) car.motor(50, -50) # turn right with car center time.sleep(2.0) # runing time (2s) car.stop() print("program done!") """ lspeed = min(lspeed, 255) lspeed = max(-255, lspeed) ldir = 0x01 if lspeed < 0 else 0x00 # 正反转: 0x00,CCW, 0x01,CW lspeed = abs(lspeed) lspeed = lspeed * 255 # 0~65535 rspeed = min(rspeed, 255) rspeed = max(-255, rspeed) rdir = 0x01 if rspeed < 0 else 0x00 # 正反转: 0x00,CCW, 0x01,CW rspeed = abs(rspeed) rspeed = rspeed * 255 # 0~65535 if rdir == 0x01: self._rightMotor2IN.duty_cycle = rspeed self._rightMotor1IN.duty_cycle = 0 if rdir == 0x0: self._rightMotor1IN.duty_cycle = rspeed self._rightMotor2IN.duty_cycle = 0 if ldir == 0x01: self._leftMotor1IN.duty_cycle = lspeed self._leftMotor2IN.duty_cycle = 0 if ldir == 0x0: self._leftMotor2IN.duty_cycle = lspeed self._leftMotor1IN.duty_cycle = 0 def moveTime(self, mtdir=0, mtspeed=50, mt=2.0): """ Dual DC-Motor control interface to achieve forward, backward, turn left and turn right this example to demostrate car forward, backward, turn left and turn right To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() car.moveTime(0, 50, 1.2) # forward with 50 speed, and running 1.2s car.moveTime(1, 50, 1.2) # backward with 50 speed, and running 1.2s car.moveTime(2, 50, 2.0) # turn left with car center, , and running 2.0s car.moveTime(3, 50, 2.0) # turn right with car center, , and running 2.0s print("program done!") """ if mtdir >= 0 and mtdir <= 3: self.move(mtdir, mtspeed) time.sleep(mt) self.motor(0, 0) def move(self, mdir=0, mspeed=50): """ Dual DC-Motor control interface to car move(forward, backward, turn left and turn right) this example to demostrate car move To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() car.move(0, 50) # forward with 50 speed, and running 1.2s time.sleep(1.2) # runing time (1.2s) car.move(1, 50) # backward with 50 speed, and running 1.2s time.sleep(1.2) # runing time (1.2s) car.move(2, 50) # turn left with car center, , and running 2.0s time.sleep(2.0) # runing time (2.0s) car.move(3, 50) # turn right with car center, , and running 2.0s time.sleep(2.0) # runing time (2.0s) car.stop() print("program done!") """ sp = abs(mspeed) if mdir == 0: # Forward self.motor(sp, sp) elif mdir == 1: # Backward self.motor(-sp, -sp) elif mdir == 2: # Rotate-Left self.motor(-sp, sp) elif mdir == 3: # Rotate-Right self.motor(sp, -sp) def stop(self): # stop car self.motor(0, 0) @property def leftLightSensor(self): """ get the brightness value of the left-lighting-sensor this example to get the brightness of left lighting sensor To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: print(car.leftLightSensor) time.sleep(0.5) """ return self._leftLightSensor.value @property def rightLightSensor(self): """ get the brightness value of the right-lighting-sensor this example to get the brightness of right lighting sensor To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: print(car.rightLightSensor) time.sleep(0.5) """ return self._rightLightSensor.value def _getRawRGB_light(self): __colorComps = ((255, 0, 0), (0, 255, 0), (0, 0, 255)) __bt = self._pixels.brightness self._pixels.brightness = 1.0 self._pixels.fill(0x0) self._pixels.show() __Craw = [0, 0, 0] i = 0 for cc in __colorComps: self.pixels[0] = cc self.pixels.show() time.sleep(0.1) __Craw[i] = int(self._colorSensor.value * 255 // (2**16)) i += 1 self._pixels.fill(0x0) self._pixels.show() time.sleep(0.1) self._pixels.brightness = __bt return __Craw[0], __Craw[1], __Craw[2] @staticmethod def _rgb2hsv(r, g, b): __rR, __rG, __rB = r / 255, g / 255, b / 255 __Cmax, __Cmin = max(__rR, __rG, __rB), min(__rR, __rG, __rB) __Cdelta = __Cmax - __Cmin V = __Cmax # HSV: Value if __Cmax == 0.0: S = 0.0 # HSV: Saturation else: S = __Cdelta / __Cmax # HSV: Saturation if __Cdelta == 0.0: H = 0 # HSV: Hue elif __Cmax == __rR: H = 60 * (((__rG - __rB) / __Cdelta) % 6) # HSV: Hue [--Red++] elif __Cmax == __rG: H = 60 * (((__rB - __rR) / __Cdelta) + 2) # HSV: Hue [--Green++] else: H = 60 * (((__rR - __rG) / __Cdelta) + 4) # HSV: Hue [--Blue++] H = int(H) return H, S, V @property def groundColorID(self): rawR, rawG, rawB = self._getRawRGB_light() H, S, V = self._rgb2hsv(rawR, rawG, rawB) if S < 0.075: return 0 # white if H < 30 or H >= 330: # 330~359, 0~29 return 1 # red elif H >= 30 and H < 90: # 30~89 return 2 # yellow elif H >= 90 and H < 150: # 90~149 return 3 # green elif H >= 150 and H < 210: # 150~209 return 4 # cyan elif H >= 210 and H < 270: # 210~269 return 5 # blue else: # 270~329 return 6 # purple @property def groundColor(self): return self.groundColor_name[self.groundColorID] @property def groundColorValue(self): return self.groundColor_list[self.groundColorID] @property def leftHeadLED(self): """ get the status value of the left-head-led this example to get the state of left head LED To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.leftHeadLED = not car.leftHeadLED time.sleep(0.5) """ return self._leftHeadLED.value @leftHeadLED.setter def leftHeadLED(self, value): """ to control the left-head-led on or off this example to control the state of left head LED To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.leftHeadLED = not car.leftHeadLED time.sleep(0.5) """ self._leftHeadLED.value = value @property def rightHeadLED(self): """ get the status value of the right-head-led this example to get the state of right head LED To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.rightHeadLED = not car.rightHeadLED time.sleep(0.5) """ return self._rightHeadLED.value @rightHeadLED.setter def rightHeadLED(self, value): """ to control the right-head-led on or off this example to control the state of right head LED To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: car.rightHeadLED = not car.rightHeadLED time.sleep(0.5) """ self._rightHeadLED.value = value @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 this example to control the state of right head LED To use with the IoTs2: .. code-block:: python import time from hiibot_iots2_rungo import RunGo car = RunGo() while True: print(car.distance) time.sleep(0.5) """ 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 = 65535 ok_echo = True 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() ok_echo = False break # output a error result vs stop running #raise RuntimeError("Timed out") self._echo.pause() if ok_echo: 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: break #raise RuntimeError("Timed out") timestamp = time.monotonic() # track how long pin is high while self._echo.value: if time.monotonic() - timestamp > self._timeout: break #raise RuntimeError("Timed out") pulselen = time.monotonic() - timestamp pulselen *= 1000000 # convert to us to match pulseio if pulselen >= 65535: ok_echo = False #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 @property def leftTracker(self): """ return l sensor status: True/1, no-reflected signal, maybe just above the black line False/0, the state of the reflected signal """ return self._leftTracker.value @property def rightTracker(self): """ return r sensor status: True/1, no-reflected signal, maybe just above the black line False/0, the state of the reflected signal """ return self._rightTracker.value def tracking(self, lr_mode=0): """ lr_mode: 0, the width of back-line greater than the width between the l and r sensors 3, the width of white-line greater than the width between the l and r sensors 1, a barrow back-line be used, and l sensor be used to track 2, a barrow back-line be used, and r sensor be used to track """ if lr_mode == 0: return self._leftTracker.value and self._rightTracker.value elif lr_mode == 1: return self._leftTracker.value and not self._rightTracker.value elif lr_mode == 2: return not self._leftTracker.value and self._rightTracker.value elif lr_mode == 3: return not self._leftTracker.value and not self._rightTracker.value else: return False def trackSide(self, side=0, lr_mode=1): if side == 0 and lr_mode == 0: return self._leftTracker.value elif side == 0 and lr_mode == 1: return not self._leftTracker.value elif side == 1 and lr_mode == 0: return not self._rightTracker.value elif side == 1 and lr_mode == 1: return self._rightTracker.value else: return False
def log_info(*args): # out = " ".join([arg if type(arg) == str else repr(arg) for arg in args]) + "\r\n" # usb_cdc.data.write(out.encode("utf8")) if usb_cdc.console is None and usb_cdc.data is None: pass else: print(*args) #################################################################### # setup buttons #################################################################### butA = DigitalInOut(board.IO38) butA.switch_to_input(Pull.DOWN) butB = DigitalInOut(board.IO33) butB.switch_to_input(Pull.DOWN) but1 = DigitalInOut(board.IO6) but1.switch_to_input(Pull.DOWN) but2 = DigitalInOut(board.IO5) but2.switch_to_input(Pull.DOWN) buttons = [ [butA, "BUTA"], [butB, "BUTB"], [but1, "BUT1"], [but2, "BUT2"], ] ####################################################################
class ESP32: """Class to manage ESP32 running NINA firmware for WiFi or Bluetooth.""" NOT_IN_USE = 0 """Not currently being used.""" BOOTLOADER = 1 """Put ESP32 into bootloader mode.""" BLUETOOTH = 2 """HCI Bluetooth mode.""" WIFI = 3 """WiFi mode.""" _MODES = (NOT_IN_USE, BOOTLOADER, BLUETOOTH, WIFI) # pylint: disable=invalid-name def __init__(self, *, reset: Optional[Pin] = None, reset_high: bool = False, gpio0: Optional[Pin] = None, busy: Optional[Pin] = None, chip_select: Optional[Pin] = None, tx: Optional[Pin] = None, rx: Optional[Pin] = None, spi: Optional[SPI] = None): """Create an ESP32 instance, passing the objects needed to reset and communicate with the adapter. :param reset ~microcontroller.Pin: ESP32 RESET pin. If `None`, use ``board.ESP_RESET``. :param reset_high bool: True if `reset` is brought high to reset; `False` if brought low. :param gpio0 ~microcontroller.Pin: ESP32 GPIO0 pin. Used for ESP32 boot selection when reset, and as RTS for UART communication. If `None`, use ``board.ESP_GPIO0``. :param busy ~microcontroller.Pin: ESP32 BUSY pin (sometimes called READY). Used as CTS indicator for UART communication. If `None`, use ``board.ESP_BUSY``. :param chip_select ~microcontroller.Pin: ESP32 CS (chip select) pin. Also used for ESP32 mode selection when reset. If `None`, use ``board.ESP_CS``. :param tx ~microcontroller.Pin: ESP32 TX pin for Bluetooth UART communication. If `None`, use ``board.ESP_TX`` when in Bluetooth mode. :param rx ~microcontroller.Pin: ESP32 RX pin for Bluetooth UART communication. If `None`, use ``board.ESP_RX`` when in Bluetooth mode. :param spi busio.SPI: Used for communication with the ESP32. If not supplied, ``board.SPI()`` is used when in WiFi mode. """ self._mode = ESP32.NOT_IN_USE # We can't use board.ESP_RESET, etc. as defaults, because they may not exist. self._reset = DigitalInOut(reset or board.ESP_RESET) # Turn off ESP32 by holding reset line self._reset.switch_to_output(reset_high) self._reset_high = reset_high # These will be set to input or input as necessary. self._gpio0_rts = DigitalInOut(gpio0 or board.ESP_GPIO0) self._busy_cts = DigitalInOut(busy or board.ESP_BUSY) self._chip_select = DigitalInOut(chip_select or board.ESP_CS) # Used for Bluetooth mode. self._tx = tx self._rx = rx self._uart = None self._bleio_adapter = None # Used for WiFi mode. self._spi = spi def reset(self, mode: int, debug: bool = False) -> None: """Do hard reset of the ESP32. :param mode: One of `ESP32.NOT_IN_USE`, `ESP32.BOOTLOADER`, `ESP32.BLUETOOTH`, `ESP32.WIFI`. """ if mode not in ESP32._MODES: raise ValueError("Invalid mode") # GPIO0 high means boot from SPI flash. # Low means go into bootloader mode. self._gpio0_rts.switch_to_output(mode != ESP32.BOOTLOADER) if mode == ESP32.NOT_IN_USE: # Turn of ESP32 by holding reset line. self._reset.switch_to_output(self._reset_high) self._mode = mode return if mode == ESP32.BLUETOOTH: self._chip_select.switch_to_output(False) elif mode == ESP32.WIFI: self._chip_select.switch_to_output(True) # Initial mode. Changed if reset is successful. self._mode = ESP32.NOT_IN_USE # Reset by toggling reset pin for 100ms self._reset.switch_to_output(self._reset_high) time.sleep(0.1) self._reset.value = not self._reset_high # Wait 1 second for startup. time.sleep(1.0) if mode == ESP32.BOOTLOADER: # No startup message expected. return startup_message = b"" while self._uart.in_waiting: # pylint: disable=no-member more = self._uart.read() if more: startup_message += more if not startup_message: raise RuntimeError("ESP32 did not respond with a startup message") if debug: try: print(startup_message.decode("utf-8")) except UnicodeError: raise RuntimeError( "Garbled ESP32 startup message") from UnicodeError # Everything's fine. Remember mode. self._mode = mode # pylint: disable=invalid-name def start_bluetooth(self, debug: bool = False) -> Adapter: """Set up the ESP32 in HCI Bluetooth mode, if it is not already doing something else. :param debug bool: Print out some debugging information. :return: A `_bleio.Adapter`, to be passed to ``_bleio.set_adapter()``. """ # Will fail with ImportError if _bleio is not on the board. # That exception is probably good enough. # pylint: disable=import-outside-toplevel import _bleio if self._mode == ESP32.BLUETOOTH: # Already started. return _bleio.adapter if self._mode == ESP32.WIFI: raise RuntimeError("ESP32 is in WiFi mode; use stop_wifi() first") # Choose Bluetooth mode. self._chip_select.switch_to_output(False) self._uart = busio.UART( self._tx or board.ESP_TX, self._rx or board.ESP_RX, baudrate=115200, timeout=0, receiver_buffer_size=512, ) # Reset into Bluetooth mode. self.reset(ESP32.BLUETOOTH, debug=debug) self._busy_cts.switch_to_input() self._gpio0_rts.switch_to_output() # pylint: disable=no-member # pylint: disable=unexpected-keyword-arg self._bleio_adapter = _bleio.Adapter(uart=self._uart, rts=self._gpio0_rts, cts=self._busy_cts) self._bleio_adapter.enabled = True return self._bleio_adapter def stop_bluetooth(self): """Stop Bluetooth on the ESP32. Deinitialize the ~busio.UART used for communication""" if self._mode != ESP32.BLUETOOTH: return self._bleio_adapter.enabled = False self.reset(ESP32.NOT_IN_USE) self._uart.deinit() self._uart = None def start_wifi(self, debug: bool = False) -> SPI: """Start WiFi on the ESP32. :return: the ``busio.SPI`` object that will be used to communicate with the ESP32. :rtype: busio.SPI """ if self._mode == ESP32.WIFI: # Already started. return self._spi if self._mode == ESP32.BLUETOOTH: raise RuntimeError( "ESP32 is in Bluetooth mode; use stop_bluetooth() first") self.reset(ESP32.WIFI, debug=debug) if self._spi is None: self._spi = board.SPI() return self._spi def stop_wifi(self): """Stop WiFi on the ESP32. The `busio.SPI` object used is not deinitialized, since it may be in use for other devices. """ if self._mode != ESP32.WIFI: return self.reset(ESP32.NOT_IN_USE)
try: import board from digitalio import DigitalInOut import adafruit_dotstar except ImportError: print( "Blinka not installed? Run 'pip3 install adafruit-circuitpython-dotstar'" ) raise ImportError( "Blinka not installed? Run 'pip3 install adafruit-circuitpython-dotstar'" ) # Setup button button = DigitalInOut(board.D17) button.switch_to_input() # Setup DotStar LEDs dots = adafruit_dotstar.DotStar( board.D6, board.D5, 3, auto_write=True, brightness=0.2, pixel_order=adafruit_dotstar.BGR, ) dots.fill(0x000000) ASSISTANT_API_ENDPOINT = "embeddedassistant.googleapis.com" END_OF_UTTERANCE = embedded_assistant_pb2.AssistResponse.END_OF_UTTERANCE DIALOG_FOLLOW_ON = embedded_assistant_pb2.DialogStateOut.DIALOG_FOLLOW_ON
} # Get wifi details and more from a secrets.py file try: from secrets import secrets except ImportError: print("WiFi secrets are kept in secrets.py, please add them there!") raise print("Matrix Clock Plus") # --- Display setup --- matrix = Matrix() display = matrix.display network = Network(status_neopixel=board.NEOPIXEL, debug=False) button_down = DigitalInOut(board.BUTTON_DOWN) button_down.switch_to_input(pull=Pull.UP) button_up = DigitalInOut(board.BUTTON_UP) button_up.switch_to_input(pull=Pull.UP) # --- Weather data setup --- UNITS = "imperial" DATA_LOCATION = [] DATA_SOURCE = ("http://api.openweathermap.org/data/2.5/weather?q=" + secrets["openweather_loc"] + "&units=" + UNITS) DATA_SOURCE += "&appid=" + secrets["openweather_token"] current_temp = '0' # --- Drawing setup --- group = displayio.Group(max_size=4) # Create a Group bitmap = displayio.Bitmap(64, 32, len(color_codes) +
from digitalio import DigitalInOut, Pull import touchio print("NeoKey Trinkey HID") # create the pixel and turn it off pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1) pixel.fill(0x0) time.sleep(1) # Sleep for a bit to avoid a race condition on some systems keyboard = Keyboard(usb_hid.devices) keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :) # create the switch, add a pullup, start it with not being pressed button = DigitalInOut(board.SWITCH) button.switch_to_input(pull=Pull.DOWN) button_state = False # create the captouch element and start it with not touched touch = touchio.TouchIn(board.TOUCH) touch_state = False # print a string on keypress key_output = "Hello World!\n" # one character on keypress # key_output = Keycode.A # multiple simultaneous keypresses # key_output = (Keycode.SHIFT, Keycode.A) # capital A # key_output = (Keycode.CONTROL, Keycode.ALT, Keycode.DELETE) # three finger salute!
# Set up keyboard kbd = Keyboard(usb_hid.devices) # LED setup, G=Green B=BLUE ledG = DigitalInOut(board.GP14) ledB = DigitalInOut(board.GP15) # LED direction ledG.direction = Direction.OUTPUT ledB.direction = Direction.OUTPUT # Set switch and direction\ switch = [] for x in range(13): temp = DigitalInOut(getattr(board,f"GP{x}")) temp.switch_to_input(Pull.UP) switch.append(temp) continue while True: # We could also do "led.value = not switch.value"! if switch[0].value: ledB.value = False else: ledB.value = True kbd.send(Keycode.F13) time.sleep(0.1) kbd.release(Keycode.F13) if switch[1].value: ledB.value = False
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
import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi import busio from secrets import secrets esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) water_sensor = AnalogIn(board.A0) force_sensor = AnalogIn(board.A1) button = DigitalInOut(board.D12) button.switch_to_input(pull=Pull.UP) switch = DigitalInOut(board.D7) switch.direction = Direction.OUTPUT switch.value = False transistorOutput = AnalogIn(board.A5) requests.set_socket(socket, esp) #if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: # print("ESP32 found and in idle mode") #print("Firmware vers.", esp.firmware_version) #print("MAC addr:", [hex(i) for i in esp.MAC_address]) #for ap in esp.scan_networks(): # print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"]))
class RadJTAG: def __init__(self, fn="radboot.bin"): self.fn = fn self.tck = DigitalInOut(board.TCK) self.tms = DigitalInOut(board.TMS) self.tdi = DigitalInOut(board.TDI) self.tdo = DigitalInOut(board.TDO) self.tck.switch_to_output(value=False) self.tms.switch_to_output(value=False) self.tdi.switch_to_output(value=False) self.tdo.switch_to_input() def clock(self, tdi=False): self.tdi.value = tdi self.tck.value = True self.tck.value = False def idcode(self): self.tms.value = True self.clock() # select-DR self.tms.value = False self.clock() # capture-DR self.clock() # now in shift-DR. # Data appears on TDO *now* # data is clocked into TDI *at next clock* val = 0 for i in range(32): val |= int(self.tdo.value) << i # could exit at 32 here if I felt like it self.clock() self.tms.value = True self.clock() self.clock() self.tms.value = False self.clock() return val def shiftir(self, value): # assume we start in RTI self.tms.value = True self.clock() # Select-DR self.clock() # Select-IR self.tms.value = False self.clock() # capture-ir self.clock() # shift-ir for i in range(5): self.clock(value & 0x1) value = value >> 1 self.tms.value = True self.clock(value & 0x1) # exit1-IR : now go to RTI self.clock() # update-IR self.tms.value = False self.clock() # RTI def begin(self): # TLR self.tms.value = True self.tdi.value = True for i in range(5): self.clock() # go to RTI self.tms.value = False self.tdi.value = False self.clock() def config(self): # Config sequence is simple, just: # JPROGRAM self.shiftir(0x0b) # NOOP self.shiftir(0x14) # wait at least 0.1 sec time.sleep(0.1) # Can shift in 0x14 and look # at the IR output. As far as I can # tell, Xilinx just checks # DONE=0 and INIT=1. # now shift in CONFIG self.shiftir(0x05)
class Locomotive(Drivetrain): """This class relies soley on one `Solenoid` object controlling 2 solenoids in tandem. Like with a locomotive train, applied force is alternated between the 2 solenoids using a boolean-ized pressure sensor or switch to determine when the applied force is alternated. :param ~drivetrain.motor.Solenoid solenoids: This object has 1 or 2 solenoids attached. It will be used to apply the force for propulsion. :param ~microcontroller.Pin switch: This should be the (`board` module's) :py:class:`~microcontroller.Pin` that is connected to the sensor that will be used to determine when the force for propulsion should be alternated between solenoids. .. note:: There is no option to control the speed in this drivetrain class due to the nature of using solenoids for propulsion. Electronic solenoids apply either their full force or none at all. We currently are not supporting dynamic linear actuators (in which the force applied can vary) because they are basically motors simulating linear motion via a gear box controlling a shaft's extension/retraction. This may change when we support servos though. """ def __init__(self, solenoids, switch): if isinstance(solenoids, (BiMotor, PhasedMotor, StepperMotor)): raise ValueError('this drivetrain only uses a 1 Solenoid object') super(Locomotive, self).__init__([solenoids]) if MICROPY: self._switch = machine.Pin(switch, machine.Pin.IN) else: self._switch = DigitalInOut(switch) self._switch.switch_to_input() self._is_forward = True self._is_in_motion = False self._cancel_thread = not IS_THREADED self._moving_thread = None def stop(self): """This function stops the process of alternating applied force between the solenoids.""" if IS_THREADED: self._stop_thread() self._is_in_motion = False def _stop_thread(self): if self._moving_thread is not None: self._cancel_thread = True self._moving_thread.join() self._cancel_thread = False self._moving_thread = None def go(self, forward): """This function starts the process of alternating applied force between the solenoids with respect to the specified direction. :param bool forward: `True` cylces the forces in a way that invokes a forward motion. `False` does the same but invokes a force in the backward direction. .. note:: Since we are talking about applying linear force to a wheel or axle, the direction is entirely dependent on the physical orientation of the solenoids. In other words, the armature of one solenoid should be attached to the wheel(s) or axle(s) in a position that is always opposite the position of the other solenoid's armature on the same wheel(s) or axel(s). """ self._is_forward = forward self._is_in_motion = True self.stop() if IS_THREADED: self._moving_thread = Thread(target=self._move) self._moving_thread.start() else: self.sync() def _move(self): do_while = True while do_while: self.sync() do_while = not self._cancel_thread def sync(self): """This function should be used at least once in the application's main loop. It will trigger the alternating of each solenoid's applied force. This IS needed on MCUs (microcontroller units) that can't use the threading module.""" alternate = (1 if self._switch.value else -1) * \ (-1 if self._is_forward else 1) self._motors[0].go(alternate) @property def is_cellerating(self): """This attribute contains a `bool` indicating if the drivetrain's applied force via solenoids is in the midst of alternating. (read-only)""" if self._moving_thread is not None or self._is_in_motion: return True return False
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 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, stop=True): """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], stop) 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, stop=True): """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, stop=stop) 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 _set_values(self, *, scl, sda, delay=None): if delay is None: delay = self._delay self._scl.value = scl self._scl.value = sda sleep(delay) 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
from adafruit_led_animation.animation.solid import Solid from adafruit_led_animation.animation.comet import Comet from adafruit_led_animation.animation.pulse import Pulse from adafruit_led_animation.helper import PixelSubset from adafruit_led_animation.group import AnimationGroup from adafruit_led_animation.color import RED, ORANGE, WHITE ORANGE_DIM = 0x801400 # half value version RED_DIM = 0x800000 # ---Set Volume Max Here--- VOLUME_MULT = 0.65 # 1 = full volume, 0.1 is very quiet, 0 is muted # ---SWITCH/BUTTON SETUP--- mode_switch = DigitalInOut(board.D9) mode_switch.switch_to_input(pull=Pull.UP) mode_state = mode_switch.value trig_button = DigitalInOut(board.A4) trig_button.switch_to_input(pull=Pull.UP) alt_button = DigitalInOut(board.A5) alt_button.switch_to_input(pull=Pull.UP) # ---ACCELEROMETER SETUP--- # Set up accelerometer on I2C bus, 4G range: i2c = busio.I2C(board.SCL, board.SDA) int1 = DigitalInOut(board.D6) accel = adafruit_lis3dh.LIS3DH_I2C(i2c, int1=int1) # ---SPEAKER SETUP--- enable = DigitalInOut(board.D10) enable.direction = Direction.OUTPUT
import board from time import sleep from digitalio import DigitalInOut, Pull, Direction import neopixel from random import randint, choice import audioio from microcontroller import reset btn_a = DigitalInOut(board.BUTTON_A) btn_a.switch_to_input(pull=Pull.DOWN) btn_b = DigitalInOut(board.BUTTON_B) btn_b.switch_to_input(pull=Pull.DOWN) spkrenable = DigitalInOut(board.SPEAKER_ENABLE) spkrenable.switch_to_output() spkrenable.value = True np = neopixel.NeoPixel(board.A1, 64, brightness=.3, auto_write=0) PICTURES = [ 'main_screen_1.txt', '3.txt', '2.txt', '1.txt', 'go.txt', 'game1.txt', 'heart.txt', 'end.txt', 'a.txt', 'main_screen_2.txt' ] R, G, B, Y, M, W, T, O, BL = (64, 0, 0), (0, 32, 0), (0, 0, 32), (32, 32, 0), (32, 0, 32),\ (20, 20, 20), (0, 32, 32), (42, 10, 0), (0, 0, 0) COLORS = [R, G, B, Y, M, W, T, O] FLOOR = [56, 57, 58, 59, 60, 61, 62, 63] PAD_pos, DIG = 58, 51 color = choice(COLORS)
class FeatherS2: def __init__(self): # the boot button ! self._boot = DigitalInOut(board.IO0) self._boot.switch_to_input(pull=Pull.UP) # pin 13 and on-board RGB self._led13 = DigitalInOut(board.LED) self._led13.direction = Direction.OUTPUT self._dotstar = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.5, auto_write=True) # the second LDO self._ldo2 = DigitalInOut(board.LDO2) self._ldo2.direction = Direction.OUTPUT # ambient light sensor self._light = analogio.AnalogIn(board.AMB) """Reading the on-board multipurpose button known as boot""" @property def boot(self): return not self._boot.value """The pin 13 is blue""" @property def blue_led(self): return self._led13.value @blue_led.setter def blue_led(self, value): #set the internal LED IO13 to it's inverse state self._led13.value = value """Set the power for the second on-board LDO to allow no current draw when not needed.""" @property def ldo2(self): return self._ldo2.value @ldo2.setter def ldo2(self, state): # Set the LDO2 power pin on / off self._ldo2.value = state # A small delay to let the IO change state time.sleep(0.035) """Old style convenience function for enabling LDO2""" def enable_LDO2(self, state): self.ldo2 = state """On board RGB LED, otherwise used for Circuitpython status""" @property def dot(self): return self._dotstar """Color wheel to allow for cycling through the rainbow of RGB colors.""" @staticmethod def wheel(wheel_pos): wheel_pos = wheel_pos % 255 if wheel_pos < 85: return 255 - wheel_pos * 3, 0, wheel_pos * 3 elif wheel_pos < 170: wheel_pos -= 85 return 0, wheel_pos * 3, 255 - wheel_pos * 3 else: wheel_pos -= 170 return wheel_pos * 3, 255 - wheel_pos * 3, 0 """Light, the friendly light sensor (516-52686) - make a percent version ? (0-100)""" @property def light(self): return self._light.value
# Copy this as 'boot.py' in your Pico's CIRCUITPY drive # from https://gist.github.com/Neradoc/8056725be1c209475fd09ffc37c9fad4 # Useful in case Pico locks up (which it's done a few times on me) # import board import time from digitalio import DigitalInOut, Pull import time led = DigitalInOut(board.LED) led.switch_to_output() safe = DigitalInOut(board.GP14) safe.switch_to_input(Pull.UP) def reset_on_pin(): if safe.value is False: import microcontroller microcontroller.on_next_reset(microcontroller.RunMode.SAFE_MODE) microcontroller.reset() led.value = False for x in range(16): reset_on_pin() led.value = not led.value time.sleep(0.1)
IMAGE_DURATION = (1, 0.5, 10) IMAGE_FOLDER = ( "/bmps", "/bmps2", "/bmps3", ) # pylint: disable=invalid-name # --- Display setup --- matrix = Matrix(bit_depth=6) display = matrix.display ACCEL = adafruit_lis3dh.LIS3DH_I2C(busio.I2C(board.SCL, board.SDA), address=0x19) _ = ACCEL.acceleration # Dummy reading to blow out any startup residue pin_down = DigitalInOut(board.BUTTON_DOWN) pin_down.switch_to_input(pull=Pull.UP) button_down = Debouncer(pin_down) pin_up = DigitalInOut(board.BUTTON_UP) pin_up.switch_to_input(pull=Pull.UP) button_up = Debouncer(pin_up) ALIGN_RIGHT = True auto_advance = True i = 0 NUM_FOLDERS = 2 #first folder is numbered 0 slideshow = SlideShow( display, None, folder=IMAGE_FOLDER[i],
class Badge: BTN_UP = 1 << 0 BTN_LEFT = 1 << 1 BTN_DOWN = 1 << 2 BTN_RIGHT = 1 << 3 BTN_ACTION = 1 << 4 def __init__(self): self._up = DigitalInOut(board.UP_BUTTON) self._up.switch_to_input(pull=Pull.UP) self._down = DigitalInOut(board.DOWN_BUTTON) self._down.switch_to_input(pull=Pull.UP) self._left = DigitalInOut(board.LEFT_BUTTON) self._left.switch_to_input(pull=Pull.UP) self._right = DigitalInOut(board.RIGHT_BUTTON) self._right.switch_to_input(pull=Pull.UP) self._action = DigitalInOut(board.ACTION_BUTTON) self._action.switch_to_input(pull=Pull.UP) self._battery = AnalogIn(board.BATTERY_SENSE) self._led = DigitalInOut(board.LED) self._led.switch_to_output(value=True) self._vibration = DigitalInOut(board.VIBRATION_MOTOR) self._vibration.switch_to_output() self._pixels = neopixel.NeoPixel(board.NEOPIXEL, 4) self._i2c = None self._lis3dh = None self._spi = None self._display_bus = None self._display = None self._sound = None self._midi = None self._gamepad = None @property def up(self): """``True`` when the up button is pressed. ``False`` if not.""" return not self._up.value @property def down(self): """``True`` when the down button is pressed. ``False`` if not.""" return not self._down.value @property def left(self): """``True`` when the left button is pressed. ``False`` if not.""" return not self._left.value @property def right(self): """``True`` when the right button is pressed. ``False`` if not.""" return not self._right.value @property def action(self): """``True`` when the action button is pressed. ``False`` if not.""" return not self._action.value @property def gamepad(self): if not self._gamepad: import gamepad self._gamepad = gamepad.GamePad( self._up, self._left, self._down, self._right, self._action ) return self._gamepad @property def back_led(self): """The LED at the back of the board""" return not self._led.value @back_led.setter def back_led(self, value): self._led.value = not value @property def vibration(self): """Set to ``True`` to start vibrating""" return self._vibration.value @vibration.setter def vibration(self, value): self._vibration.value = value @property def pixels(self): """Array with the values of the 4 neopixels at the top of the board. See `neopixel.NeoPixel` for more info. .. code-block:: python from badgeio import badge import time badge.pixels.brightness = 0.5 while True: badge.pixels[0] = (255, 0, 0) # Red time.sleep(0.5) badge.pixels[0] = (0, 255, 0) # Green time.sleep(0.5) """ return self._pixels @property def i2c(self): """direct access to the I2C bus""" if not self._i2c: self._i2c = board.I2C() return self._i2c @property def spi(self): """direct access to the SPI bus""" if not self._spi: self._spi = board.SPI() return self._spi @property def display_bus(self): if not self._display_bus: self._display_bus = displayio.FourWire(self.spi, command=board.DISP_DC, chip_select=board.DISP_CS, reset=board.DISP_RESET, baudrate=1000000) return self._display_bus @property def display(self): if not self._display: displayio.release_displays() self._display = display.Display(self.display_bus, width=296, height=128, rotation=270, seconds_per_frame=5, busy_pin=board.DISP_BUSY, swap_rams=True, black_bits_inverted=False) return self._display @property def acceleration(self): """Obtain acceleration as a tuple with 3 elements: (x, y, z)""" if not self._lis3dh: import adafruit_lis3dh self._lis3dh = adafruit_lis3dh.LIS3DH_I2C(self.i2c, address=0x18) return self._lis3dh.acceleration @property def battery_voltage(self): """The battery voltage (if currently operating off the battery)""" return (self._battery.value * 3.3) / 65536 def show_bitmap(self, path, pixel_shader=displayio.ColorConverter()): """Draws the bitmap from the given file. Must be in .bmp format""" image = displayio.OnDiskBitmap(open(path, "rb")) grid = displayio.TileGrid(image, pixel_shader=pixel_shader) group = displayio.Group(max_size=1) group.append(grid) self.display.show(group) while self.display.time_to_refresh > 0: pass self.display.refresh()