/ examples / ble_color_proximity.py
ble_color_proximity.py
  1  """
  2  This demo uses advertising to set the color of scanning devices depending on the strongest broadcast
  3  signal received. Circuit Playgrounds can be switched between advertising and scanning using the
  4  slide switch. The buttons change the color when advertising.
  5  """
  6  
  7  import time
  8  import board
  9  import digitalio
 10  
 11  import neopixel
 12  
 13  from adafruit_ble import BLERadio
 14  from adafruit_ble.advertising.adafruit import AdafruitColor
 15  
 16  # The color pickers will cycle through this list with buttons A and B.
 17  color_options = [
 18      0x110000,
 19      0x111100,
 20      0x001100,
 21      0x001111,
 22      0x000011,
 23      0x110011,
 24      0x111111,
 25      0x221111,
 26      0x112211,
 27      0x111122,
 28  ]
 29  
 30  ble = BLERadio()
 31  
 32  slide_switch = digitalio.DigitalInOut(board.SLIDE_SWITCH)
 33  slide_switch.pull = digitalio.Pull.UP
 34  button_a = digitalio.DigitalInOut(board.BUTTON_A)
 35  button_a.pull = digitalio.Pull.DOWN
 36  button_b = digitalio.DigitalInOut(board.BUTTON_B)
 37  button_b.pull = digitalio.Pull.DOWN
 38  
 39  led = digitalio.DigitalInOut(board.D13)
 40  led.switch_to_output()
 41  
 42  neopixels = neopixel.NeoPixel(board.NEOPIXEL, 10, auto_write=False)
 43  
 44  i = 0
 45  advertisement = AdafruitColor()
 46  advertisement.color = color_options[i]
 47  neopixels.fill(color_options[i])
 48  while True:
 49      # The first mode is the color selector which broadcasts it's current color to other devices.
 50      if slide_switch.value:
 51          print("Broadcasting color")
 52          ble.start_advertising(advertisement)
 53          while slide_switch.value:
 54              last_i = i
 55              if button_a.value:
 56                  i += 1
 57              if button_b.value:
 58                  i -= 1
 59              i %= len(color_options)
 60              if last_i != i:
 61                  color = color_options[i]
 62                  neopixels.fill(color)
 63                  print("New color {:06x}".format(color))
 64                  advertisement.color = color
 65                  ble.stop_advertising()
 66                  ble.start_advertising(advertisement)
 67                  time.sleep(0.5)
 68          ble.stop_advertising()
 69      # The second mode listens for color broadcasts and shows the color of the strongest signal.
 70      else:
 71          closest = None
 72          closest_rssi = -80
 73          closest_last_time = 0
 74          print("Scanning for colors")
 75          while not slide_switch.value:
 76              for entry in ble.start_scan(AdafruitColor, minimum_rssi=-100, timeout=1):
 77                  if slide_switch.value:
 78                      break
 79                  now = time.monotonic()
 80                  new = False
 81                  if entry.address == closest:
 82                      pass
 83                  elif entry.rssi > closest_rssi or now - closest_last_time > 0.4:
 84                      closest = entry.address
 85                  else:
 86                      continue
 87                  closest_rssi = entry.rssi
 88                  closest_last_time = now
 89                  discrete_strength = min((100 + entry.rssi) // 5, 10)
 90                  # print(entry.rssi, discrete_strength)
 91                  neopixels.fill(0x000000)
 92                  for i in range(0, discrete_strength):
 93                      neopixels[i] = entry.color
 94                  neopixels.show()
 95  
 96              # Clear the pixels if we haven't heard from anything recently.
 97              now = time.monotonic()
 98              if now - closest_last_time > 1:
 99                  neopixels.fill(0x000000)
100                  neopixels.show()
101          ble.stop_scan()