Engineer
UNITED STATES OF AMERICA • + Follow
Edit Project
Tools, APP Software Used etc.
![]() |
Autodesk Fusion 360Autodesk
|
|
![]() |
KiCADKicad
|
Description
Wireless Bike Media Controller
I wanted an easy way to control my music while biking without having to look at my phone. This project solves that issue. This wireless device features a rotary encoder for volume and a mute button, plus three keys for previous track, play/pause, and next track. It also has a LiPo battery so no cables are needed. Just attach the bottom plate to the handlebar mount which fits your handlebars and you won't have to worry about looking down to switch songs!
Controls
- Left Button: Previous Track
- Center Button: Play/Pause
- Right Button: Next Track
- Knob CW: Volume Down
- Knob CCW: Volume Up
- Knob Button: Mute/Unmute
Hardware
- Seeed Studio XIAO ESP32C3
- 3x MX Switches
- 5x 10k Ohm Resistors
- Rotary Encoder
- 3.7v LiPo Battery
- 4x M3 x 6mm Screws
- 4x M3 heat set inserts
Code
Arduino Code for Seeed XIAO ESP32C3
C/C++
#include <BleKeyboard.h> #include <RotaryEncoder.h> const int button1Pin = 5; const int button2Pin = 6; const int button3Pin = 7; const int encoderAPin = 4; const int encoderBPin = 3; const int encoderSwitchPin = 2; bool button1Pressed = false; bool button2Pressed = false; bool button3Pressed = false; bool encoderSwitchPressed = false; BleKeyboard bleKeyboard; RotaryEncoder encoder(encoderAPin, encoderBPin, RotaryEncoder::LatchMode::TWO03); void setup() { Serial.begin(9600); pinMode(button1Pin, INPUT_PULLUP); pinMode(button2Pin, INPUT_PULLUP); pinMode(button3Pin, INPUT_PULLUP); pinMode(encoderAPin, INPUT_PULLUP); pinMode(encoderBPin, INPUT_PULLUP); pinMode(encoderSwitchPin, INPUT_PULLUP); bleKeyboard.begin(); } void loop() { // Check button inputs if (digitalRead(button1Pin) == LOW && !button1Pressed) { button1Pressed = true; Serial.write("Prev\n"); bleKeyboard.press(KEY_MEDIA_PREVIOUS_TRACK); } else if (digitalRead(button1Pin) == HIGH && button1Pressed) { button1Pressed = false; bleKeyboard.release(KEY_MEDIA_PREVIOUS_TRACK); } if (digitalRead(button2Pin) == LOW && !button2Pressed) { button2Pressed = true; Serial.write("Play/Pause\n"); bleKeyboard.press(KEY_MEDIA_PLAY_PAUSE); } else if (digitalRead(button2Pin) == HIGH && button2Pressed) { button2Pressed = false; bleKeyboard.release(KEY_MEDIA_PLAY_PAUSE); } if (digitalRead(button3Pin) == LOW && !button3Pressed) { button3Pressed = true; Serial.write("Next\n"); bleKeyboard.press(KEY_MEDIA_NEXT_TRACK); } else if (digitalRead(button3Pin) == HIGH && button3Pressed) { button3Pressed = false; bleKeyboard.release(KEY_MEDIA_NEXT_TRACK); } if (digitalRead(encoderSwitchPin) == LOW && !encoderSwitchPressed) { encoderSwitchPressed = true; Serial.write("Mute\n"); bleKeyboard.press(KEY_MEDIA_MUTE); } else if (digitalRead(encoderSwitchPin) == HIGH && encoderSwitchPressed) { encoderSwitchPressed = false; bleKeyboard.release(KEY_MEDIA_MUTE); } // Check encoder rotation static int pos = 0; encoder.tick(); int newPos = encoder.getPosition(); if (pos != newPos) { int dir = (-1) * (int)(encoder.getDirection()); if (dir > 0) { bleKeyboard.press(KEY_MEDIA_VOLUME_UP); delay(200); // Increase this delay for larger moves bleKeyboard.release(KEY_MEDIA_VOLUME_UP); Serial.write("Volume Up\n"); } else { bleKeyboard.press(KEY_MEDIA_VOLUME_DOWN); delay(200); // Increase this delay for larger moves bleKeyboard.release(KEY_MEDIA_VOLUME_DOWN); Serial.write("Volume Down\n"); } pos = newPos; } }
Schematic and Layout
Schematic: OPTIONAL: Connect Lipo Battery to Battery +/- on the back of the Seeed Studio XIAO with a switch to interrupt power.
BMC Schematic.png

CAD-Custom parts and enclosures
Dec 14,2023
789 views
end-flag
Wireless Bike Media Controller
Control your music and keep your eyes on the road with this handlebar mounted bluetooth media controller.
789
2
2
Published: Dec 14,2023
Purchase
Donation Received ($)
PCBWay Donate 10% cost To Author
*PCBWay community is a sharing platform. We are not responsible for any design issues and parameter issues (board thickness, surface finish, etc.) you choose.
Copy this HTML into your page to embed a link to order this shared project
Copy
Under the
Attribution-NonCommercial (CC BY-NC)
License.

Raspberry Pi 5 7 Inch Touch Screen IPS 1024x600 HD LCD HDMI-compatible Display for RPI 4B 3B+ OPI 5 AIDA64 PC Secondary Screen(Without Speaker)
BUY NOW
ESP32-S3 4.3inch Capacitive Touch Display Development Board, 800×480, 5-point Touch, 32-bit LX7 Dual-core Processor
BUY NOW
Raspberry Pi 5 7 Inch Touch Screen IPS 1024x600 HD LCD HDMI-compatible Display for RPI 4B 3B+ OPI 5 AIDA64 PC Secondary Screen(Without Speaker)
BUY NOW
VOTING
0 votes
- 0 USER VOTES
0.00
- YOUR VOTE 0.00 0.00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Design
1/4
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Usability
2/4
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Creativity
3/4
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Content
4/4
More by Engineer
You may also like
-
-
-
Modifying a Hotplate to a Reflow Solder Station
652 1 5 -
MPL3115A2 Barometric Pressure, Altitude, and Temperature Sensor
356 0 1 -
-
Nintendo 64DD Replacement Shell
321 0 1 -
V2 Commodore AMIGA USB-C Power Sink Delivery High Efficiency Supply Triple Output 5V ±12V OLED display ATARI compatible shark 100W
855 4 2 -
How to measure weight with Load Cell and HX711
594 0 3
It should work with both, but I have only tested it with android.