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
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 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
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