Using an Arduino, I made a USB-connected volume control button that can turn up, turn down, or mute the volume of a PC.
There are many different types of Arduino, but we will use the Arduino Micro, which has a microcontroller called ATmega32U4. The ATmega32U4 has the ability to handle UBS, allowing you to make USB devices with Arduino.
schematic
The circuit is simple: there is a button that connects pins 7, 8, and 9 to GND, and each button is used to turn the PC volume to high, low, or mute.
Before we continue with the programming procedure, we will briefly explain what HID is.
About HID
Although it is up to the developer to decide what kind of device to create using USB, commonly used USB devices such as mice and keyboards are predefined in the USB standard as HID (Human Interface Device).
Since device drivers for HID devices are standard in PC operating systems, HID devices can be used on any PC simply by plugging them in and without installing any additional programs.
Fortunately, the volume control button is also defined by HID, so we have created the volume control button as an HID device there.
About HID for volume control buttons
The volume control button is treated as a separate category of function called "consumer control" rather than "keyboard" in the HID, so you cannot use the USB keyboard library in the Arduino to press the volume control button.
Also, the keyboard and mouse libraries are included in the Arduino IDE (Arduino's development tool), but there is no consumer control library, so it must be implemented separately, using other libraries as reference.
Now, let's get into the specific program steps.
program procedure
Main Program (Sketch)
Create the following main program under any name.
VolumeControlButton.ino
#include "ConsumerControl.h" u8 previousButtonState = 1; // 連打防止フラグ void setup() { pinMode(7, INPUT_PULLUP); // 音量大にするピン7 pinMode(8, INPUT_PULLUP); // 音量小にするピン8 pinMode(9, INPUT_PULLUP); // 音量消音にするピン9 } void loop() { if(digitalRead(7)==LOW){ ConsumerControl.press(VOLUME_UP); // 音量大ボタンを押す ConsumerControl.release(); // ボタンを離す delay(100); } else if(digitalRead(8)==LOW){ ConsumerControl.press(VOLUME_DOWN); // 音量小ボタンを押す ConsumerControl.release(); // ボタンを離す delay(100); } else if(digitalRead(9)==LOW){ if(previousButtonState==0){ ConsumerControl.press(VOLUME_MUTE); // 音量消音ボタンを押す previousButtonState = 1; } else { ConsumerControl.release(); // ボタンを離す previousButtonState = 1; } }else { if(previousButtonState==1){ ConsumerControl.release(); // ボタンを離す previousButtonState = 0; } } }
consumer control program
Place the following "ConsumerControl.h" and "ConsumerControl.cpp" in the same folder as the main program above.
ConsumerControl.h
#include "HID.h" #define REPORT_ID 1 #define VOLUME_UP 0 #define VOLUME_DOWN 1 #define VOLUME_MUTE 2 class ConsumerControl_ { public: ConsumerControl_(void); void press(u8 buttonBit); void release(void); }; extern ConsumerControl_ ConsumerControl;
ConsumerControl.cpp
#include "ConsumerControl.h" static const uint8_t _hidReportDescriptor[] PROGMEM = { 0x05, 0x0c, // USAGE_PAGE (Consumer) 0x09, 0x01, // USAGE (Consumer Control) 0xa1, 0x01, // COLLECTION (Application) 0x85, REPORT_ID, // REPORT_ID (X) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x09, 0xe9, // USAGE (Volume Increment) 0x09, 0xea, // USAGE (Volume Decrement) 0x09, 0xe2, // USAGE (Mute) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x05, // REPORT_COUNT (5) 0x81, 0x03, // INPUT (Const,Var,Abs) 0xC0 // END_COLLECTION }; ConsumerControl_::ConsumerControl_(void) { static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); HID().AppendDescriptor(&node); } void ConsumerControl_::press(u8 buttonBit) { u8 m[1]; m[0]=(1 << buttonBit); HID().SendReport(REPORT_ID, m, sizeof(m)); } void ConsumerControl_::release() { u8 m[1]; m[0]=0; HID().SendReport(REPORT_ID, m, sizeof(m)); } ConsumerControl_ ConsumerControl;
execution
After that, you can compile the program (sketch) in the Arduino's IDE, transfer it to Adruino and write it, and you have a USB-connected PC volume control button.
The written program persists even when the Arduino is disconnected from the PC, so it can be recognized and used as a volume control button even when the Arduino is plugged into another PC.
application
The part of the main program that adjusts the volume is
- Press the volume control button for the "button name" in
ConsumerControl.press(<button name>)
. - Deactivate all volume control buttons with
ConsumerControl.release()
.
Since the main program is only a "volume control device," you can rewrite the main program to create a PC volume control device of your choice.
Also, since it is possible to have multiple HIDs for a single USB device, it would be possible to create a keyboard that also has volume control by combining it with a library of keyboards.