Skip to content

first commit CPB Volume BLE, added .python-version to .gitignore #995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Hue_Controller/secrets.h
.idea
*.DS_Store
CircuitPython_Logger/secrets\.py
.python-version
137 changes: 137 additions & 0 deletions CPB_Volume_BLE/cpb_volume_ble.py
Original file line number Diff line number Diff line change
@@ -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)