first commit CPB Volume BLE, added .python-version to .gitignore, because of Catalina and pylint shennanigans
This commit is contained in:
parent
be1ef3adbc
commit
59151c7a07
2 changed files with 138 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,3 +3,4 @@ Hue_Controller/secrets.h
|
|||
.idea
|
||||
*.DS_Store
|
||||
CircuitPython_Logger/secrets\.py
|
||||
.python-version
|
||||
|
|
|
|||
137
CPB_Volume_BLE/cpb_volume_ble.py
Normal file
137
CPB_Volume_BLE/cpb_volume_ble.py
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
"""
|
||||
A CircuitPython 'multimedia' dial demo
|
||||
Uses a Circuit Playground Bluefruit + Rotary Encoder -> BLE out
|
||||
Knob controls volume, push encoder for mute, CPB button A for Play/Pause
|
||||
Once paired, bonding will auto re-connect devices
|
||||
"""
|
||||
|
||||
import time
|
||||
import digitalio
|
||||
import board
|
||||
import rotaryio
|
||||
import neopixel
|
||||
from adafruit_hid.consumer_control import ConsumerControl
|
||||
from adafruit_hid.consumer_control_code import ConsumerControlCode
|
||||
|
||||
import adafruit_ble
|
||||
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
|
||||
from adafruit_ble.services.standard.hid import HIDService
|
||||
from adafruit_ble.services.standard.device_info import DeviceInfoService
|
||||
|
||||
|
||||
ble = adafruit_ble.BLERadio()
|
||||
ble.name = "Bluefruit-Volume-Control"
|
||||
# Using default HID Descriptor.
|
||||
hid = HIDService()
|
||||
device_info = DeviceInfoService(software_revision=adafruit_ble.__version__,
|
||||
manufacturer="Adafruit Industries")
|
||||
advertisement = ProvideServicesAdvertisement(hid)
|
||||
cc = ConsumerControl(hid.devices)
|
||||
|
||||
FILL_COLOR = (0, 32, 32)
|
||||
UNMUTED_COLOR = (0, 128, 128)
|
||||
MUTED_COLOR = (128, 0, 0)
|
||||
DISCONNECTED_COLOR = (40, 40, 0)
|
||||
|
||||
# NeoPixel LED ring
|
||||
# Ring code will auto-adjust if not 16 so change to any value!
|
||||
ring = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.05, auto_write = False)
|
||||
ring.fill(DISCONNECTED_COLOR)
|
||||
ring.show()
|
||||
dot_location = 0 # what dot is currently lit
|
||||
|
||||
# CPB button for Play/Pause
|
||||
button_A = digitalio.DigitalInOut(board.BUTTON_A)
|
||||
button_A.switch_to_input(pull=digitalio.Pull.DOWN)
|
||||
|
||||
button_a_pressed = False # for debounce state
|
||||
|
||||
# Encoder button is a digital input with pullup on A1
|
||||
# so button.value == False means pressed.
|
||||
button = digitalio.DigitalInOut(board.A1)
|
||||
button.pull = digitalio.Pull.UP
|
||||
|
||||
encoder = rotaryio.IncrementalEncoder(board.A2, board.A3)
|
||||
|
||||
last_pos = encoder.position
|
||||
muted = False
|
||||
command = None
|
||||
# Disconnect if already connected, so that we pair properly.
|
||||
if ble.connected:
|
||||
for connection in ble.connections:
|
||||
connection.disconnect()
|
||||
|
||||
|
||||
def draw():
|
||||
if not muted:
|
||||
ring.fill(FILL_COLOR)
|
||||
ring[dot_location] = UNMUTED_COLOR
|
||||
else:
|
||||
ring.fill(MUTED_COLOR)
|
||||
ring.show()
|
||||
|
||||
|
||||
advertising = False
|
||||
connection_made = False
|
||||
print("let's go!")
|
||||
while True:
|
||||
if not ble.connected:
|
||||
ring.fill(DISCONNECTED_COLOR)
|
||||
ring.show()
|
||||
connection_made = False
|
||||
if not advertising:
|
||||
ble.start_advertising(advertisement)
|
||||
advertising = True
|
||||
continue
|
||||
else:
|
||||
if connection_made:
|
||||
pass
|
||||
else:
|
||||
ring.fill(FILL_COLOR)
|
||||
ring.show()
|
||||
connection_made = True
|
||||
|
||||
advertising = False
|
||||
|
||||
pos = encoder.position
|
||||
delta = pos - last_pos
|
||||
last_pos = pos
|
||||
direction = 0
|
||||
|
||||
if delta > 0:
|
||||
command = ConsumerControlCode.VOLUME_INCREMENT
|
||||
direction = -1
|
||||
elif delta < 0:
|
||||
command = ConsumerControlCode.VOLUME_DECREMENT
|
||||
direction = 1
|
||||
|
||||
if direction:
|
||||
muted = False
|
||||
for _ in range(abs(delta)):
|
||||
cc.send(command)
|
||||
# spin neopixel LED around in the correct direction!
|
||||
dot_location = (dot_location + direction) % len(ring)
|
||||
draw()
|
||||
|
||||
if not button.value:
|
||||
if not muted:
|
||||
print("Muting")
|
||||
cc.send(ConsumerControlCode.MUTE)
|
||||
muted = True
|
||||
else:
|
||||
print("Unmuting")
|
||||
cc.send(ConsumerControlCode.MUTE)
|
||||
muted = False
|
||||
draw()
|
||||
while not button.value: # debounce
|
||||
time.sleep(0.1)
|
||||
|
||||
if button_A.value and not button_a_pressed: # button is pushed
|
||||
cc.send(ConsumerControlCode.PLAY_PAUSE)
|
||||
print("Play/Pause")
|
||||
button_a_pressed = True # state for debouncing
|
||||
time.sleep(0.05)
|
||||
|
||||
if not button_A.value and button_a_pressed:
|
||||
button_a_pressed = False
|
||||
time.sleep(0.05)
|
||||
Loading…
Reference in a new issue