Introduction: USB Volume Control and Caps Lock LED - Simple, Cheap, Extensible

Picture of USB Volume Control and Caps Lock LED - Simple, Cheap, Extensible

I'm not the first person to publish an Instructable for a USB volume control, but I think this one is about as simple and cheap as it gets, and at the same time can be extended at minimal cost to various other functions such as:

  • Mute, Play, Pause and various other media buttons
  • Keyboard LEDs such as Caps Lock, Scroll Lock and Num Lock (a kana LED is also defined for Japanese users)
  • Application launch buttons such as browser, email, calculator etc
  • Browser navigation and other application control buttons
  • Gamepad buttons
  • System buttons for functions such as Sleep, Hibernate, Wake, Power down
  • Laptop screen brightness (Windows 8/10 only)
  • Mouse buttons and movement

and many more, subject to support being provided by your operating system. Mine implements the volume and mute functions (mute by pressing the knob) and the 3 main keyboard LEDs.

Have you ever clicked on a Youtube video and then fumbled for the volume control buttons when it started playing far too loud? Older laptops used to have a physical volume control but this is rare on newer ones and on desktop computers, which is why I wanted to build this.

And how many times have you carried on typing long after accidentally hitting Caps Lock, maybe on a scrabble tile type keyboard with the Caps Lock button a bit too close to the A key, and maybe having an inadequate Caps Lock light or no light at all? That was the other reason.

I assume you'll probably use a different box and so I leave most of the mechanical details to you, Other Instructables may give you a more aesthetically pleasing product using computerised manufacturing but my objective is to concentrate on the electronics.

Step 1: What You Need

Picture of What You Need

This project is built around the Arduino Pro Micro (5V version), available from Far Eastern suppliers for £2 - £3. Other ATMega 32u4 based devices could be used, but not ones based on the ATmega328 such as the Nano or Pro Mini.

You also need a 5-pin rotary encoder, which you can probably find for £0.99, and a knob to suit.

The remaining parts you may have lying around:

  • Micro USB cable
  • LEDs (if required) and a 330Ω resistor for each LED
  • 1 tactile push button switch (or more for additional functions)
  • A couple of scraps of stripboard
  • Small project box
  • Connecting wire, soldering iron, solder, wire strippers and cutters etc.

Step 2: How It Works

Picture of How It Works

You may have noticed that a lot of USB keyboards have multimedia keys such as volume up and down, mute, play/pause. Some also have application keys such as email, browser or calculator, and some even have system keys such as sleep and hibernate.

The normal alphanumeric and arrow keys don't send a character to the computer but a scan code, representing the key position. The existence of multimedia and other keys implies that these too have scan codes, so I reasoned it should be easy enough to program an Arduino to send these since the Leonardo and Pro Micro can emulate a keyboard or mouse through their USB port. But I soon hit a snag.

I quickly discovered that the Arduino Keyboard library only allows you to send the keys found on the original standard IBM PC keyboard. Multimedia and system keys comprise completely separate sets which are not supported. In the same way, mouse movements and clicks are another set, supported by the Arduino Mouse library. However, amongst those sets there is a huge array of functions defined, though not all are implemented by Windows or other operating systems.

Digging into it to the point where I was almost ready to start enhancing the Keyboard library, I found it had already been done. The optional HID-Project library provides everything you could possibly want.

Step 3: Construction

Picture of Construction

I used a box I've had for years, left over from a long since forgotten project that never got completed. It has dimensions 50x50x20mm and is probably this one from Maplin.

But you will probably be using a different one, so I leave all the mechanical construction details to you. You can see well enough from the pictures how I built mine.

The Arduino and a push-button are mounted on a piece of stripboard cut to fit the box. (The push-button is needed to reset the Arduino for programming.) The stripboard is used more to mount them than to wire them up. A couple of short pieces of wire passing through unused Arduino pads and through the stripboard, soldered to both, hold the Arduino on place. The stripboard is held in place in the box with a couple of blobs of hot melt glue.

The LEDs and resistors are mounted on a second piece of stripboard. The LEDs are a tight push fit in the holes they fit in and need no other fixing.

Step 4: Wiring It Up

Picture of Wiring It Up

If you like, you can test it out on a half-size breadboard. Alternatively use the diagram to solder it up.

Use stranded wire. I used a couple of scraps of rainbow ribbon cable, which kept the wiring reasonably neat, and the different colours made it easy to see which wire was going where.

Step 5: Programming

If you don't already have it, you need to download and install the Arduino IDE.

In your Arduino folder (by default under Windows this is in My Documents) create a folder called VolumeCtrl. Copy the file VolumeCtrl.ino into this folder. Now launch the Arduino IDE and locate the sketch VolumeCtrl in your sketchbook.

You will need to install the HID-Project library. This is easy:

Click on Sketch - Include Library - Manage Libraries. In the Filter box, type HID-Project. This should give you Extended HID Functions for Arduino. Click the Install button. That's all there is to it.

You will also need to ensure you have the Pro Micro board definition installed. If you haven't, don't be tempted to try a different one - you'll see why in a moment.

Click on Tools - Board - Board Manager. Check whether Sparkfun Pro Micro is already shown. If not, in the Filter box, type Pro Micro. Select and install the package which includes the SparkFun Pro Micro in its list of supported boards.

Now, under Tools - Board, select SparkFun Pro Micro, and under Processor, select ATMega32u4 (5V, 16MHz).

Note: if you try to program the device with the wrong board selected you will likely kill the bootloader! (If you already have done, keep reading.)

There are 3 ways of programming the Pro Micro, and before proceeding you must decide which you are going to use:

  1. USB programming through the Pro Micro's USB port
  2. ISP programming using an AVR ISP programmer
  3. Programming using another Arduino as ISP programmer.

These are described in the next steps.

Step 6: USB Programming

Picture of USB Programming

Programming through the Pro Micro's microUSB port depends on having a working bootloader. If you've already killed it you will need to use method 2 or 3 (which can also be used to restore a broken bootloader).

Connect the Pro Micro to a USB port on your computer. On the Arduino IDE, click Sketch - Upload (not Upload using Programmer). Watch the black panel at the bottom of the IDE. When compilation and linking are complete you will see it scanning COM ports looking for the Pro Micro. At this point, quickly do a double-press on the reset button. It should then be programmed, with a progress bar consisting of "#" characters. It should reset and start working as a volume control.

Step 7: ISP Programming

Picture of ISP Programming

USB programming depends on having a bootloader pre-installed. This is just another program pretty much like one you might write yourself. ISP programming, on the other hand, uses dedicated logic on the chip itself, and is how the bootloader gets loaded by the manufacturer.

You can get an AVR ISP programmer quite cheaply (this is method 2). Make sure it's one the IDE supports. The programmer comes with a 6-pin connector. Use your favourite search engine to search for "avr isp pinout" to identify the pins. Fit an ISP header to the stripboard and wire it up to the Pro Micro as follows:

ISP PinPro Micro pin

Under Tools - Programmer you need to select the type of programmer you are using.

Alternatively you can use another Arduino to do the same job (method 3). This can be a cheap Nano, or an even cheaper Pro Mini with an FTDI USB/serial adapter.

In the IDE, click on File - Examples - ArduinoISP. A block comment at the front of the sketch tells you how to wire it up. This depends on whether your additional Arduino has an ISP header and whether you use it. If not, you will have to uncomment the line


On the Arduino used for programming, connect a LED and 330Ω from each of pins 7, 8 and 9 to ground. These indicate Programming Mode, Error and Heartbeat. Connect other pins to the ISP header you fitted, or directly to the Pro Micro. Program it with the ArduinoISP sketch, and under Tools - Programmer select Arduino as ISP.

Step 8: Adding Additional Functions

The USB HID (Human Interface Device) class allows a wholerange of controls, matching the different types of human interface device. The HID-Project library used here makes many if not all of them easily available.

Examine the sketch VolumeCtrl. The push-button function on the rotary encoder is defined as ROTARY_C. You can define further buttons if you like in the same way and use the same logic to detect button pushes. Instead of the line Consumer.write(MEDIA_VOL_MUTE); you write a similar line to perform the required function.

In the IDE, click File - Examples - HID-Project for examples showing how the different types are used. The full range of controls for each type is given in a header file located in libraries\HID-Project\src\HID-APIs in your Arduino folder (which is normally in My Documents).

The examples and header file for each type are given below.


  • Hundreds of controls are available including a full range of media player controls, screensaver, application launch (email, browser, calculator), browser navigation and media centre controls.
  • Example: Consumer
  • List of controls: ConsumerAPI.h


  • System controls such as sleep, hibernate, power down, undock, wakup, primary/secondary display controls and menu navigation.
  • Example: System
  • List of controls: SystemAPI.h


  • 32 Buttons, 6 Axis, 2 D-Pads
  • Example: Gamepad
  • List of controls: GamepadAPI.h


  • Several variants are available: a boot keyboard understood by the BIOS, an improoved keyboard allowing text strings to be sent, and a keyboard allowing n-key roll-over.
  • Examples: BootKeyboard, ImprovedKeyboard, NKROKeyboard
  • List of keys: ImprovedKeylayouts.h

Keyboard LEDs:

  • Reports the Caps Lock, Scroll Lock and Num Lock LEDs and some more you never knew existed.
  • Example: KeyboardLed
  • List of LEDs: ImprovedKeyLayouts.h


  • Two variants, one pretty much the same as the standard Mouse library, and another allowing movement to an absolute position.
  • Examples: ImprovedMouse, AbsoluteMouse
  • List of controls: MouseAPI.h

Laptop screen brightness

  • Supported on Windows from Win 8 only (see ref) - Mac/Linux support unknown.
  • Use the same code as for the volume control but replace MEDIA_VOL_UP and MEDIA_VOL_DOWN by 0x006F and 0x0070 respectively.
  • Works for laptop (or mobile device) screen only (though I haven't tried it). Won't work for an attached monitor or projector as neither VGA or DVI/HDMI interfaces support it.
Further documentation can be found at


illumation_ (author)2017-07-18

I use the NicoHood library you described but the volume doesn't
seems to work on Windows. Tried it on Windows 7 and Windows 10. Tried it
on Android (Galaxy S3) and it works.

Tried the codes
them seems to work on Windows, they all work on Android.

Any Ideas?

illumation_ (author)illumation_2017-07-18

Okay, found it. I have used the Keyboard object instead of the Consumer object. But it is kinda strange why it is not working when using the Keyboard object.

p_leriche (author)illumation_2017-07-18

Glad you sorted it!

Sir Snuggly McKittens (author)2017-06-24

Hey mate, is there a way to program the mute volume button to a mute mic instead? Thanks!



I'm not very sure though whether that will do it. It may be a question of whether a particular application responds to that control. Anyway, let us know how you get on!

It didn't seem to work. Nothing happens after pressing the button

Unfortunately it looks like this may not be possible. The speaker volume is intercepted by the operating system which actions it, but it seems like the mic mute is passed through to the current application (if any), which may or may not be listening for it or even support it. Just possibly it might work if you're using a USB headset, but it's a long shot.

R3VERSE (author)2017-02-17

can't seem to find the pro micro board definition. won't the Leonardo setup work too as it's the same processor?

p_leriche (author)R3VERSE2017-02-18

Make sure you have a recent version of the Arduino IDE. Under Tools -> Board -> Boards Manager, select Type: All and search for pro micro. It should be in SparkFun AVR Boards, but you have to read the list of boards supported by the package fairly carefully to spot it.

Setting it as a Leonardo might work but if it doesn't you'll probably kill the bootloader and then have to use ISP programming. The Pro Micro (and probably Leonardo) can be a bit finicky in that respect. The Leonardo indeed uses the same processor, but there are fuse bits which set certain low level processor options and I'm not certain these are exactly the same.

R3VERSE (author)p_leriche2017-02-18

I can only find "Arduino AVR boards" if i search for pro micro. IDE is 1.8.1

p_leriche (author)R3VERSE2017-02-18

You're right - I'm sorry I'd forgotten that I'd had to install additional board descriptions from a SparkFun Github repository. This url gives you the files and very clear instructions:

Have fun!

EdwardF2005 (author)p_leriche2017-05-31

the arduino pro micro is a scaled down version of the Leonardo if you dont want to use sparkfun libraries you can just you just say its a leonardo

R3VERSE (author)p_leriche2017-02-18

Big thanks! works a charm

JGUZMANO (author)2017-02-02

Loved the layout and presentation of your project. Very professional but clear for the beginners eye.Thanks for sharing

pit1988 (author)2017-01-29

Very nice project!!

adicontakt (author)2017-01-23

nice project , and a few question , on reboot of the windows , you have to reconect the board(I made something similar and on each reboot i had to reconect the board)

can you add some rgb leds to show the precentage of the volume (e.g. from withe to blue , am a flashing red whem mute is preset, something la dj consoles)

p_leriche (author)adicontakt2017-01-23

I'd love to be proved wrong but as far as I can tell the media functions are write-only, i.e. like a TV remote you can change the volume or toggle the mute but the on screen display is the only indication of the volume level or mute state.

I don't have to reconnect mine - it starts up as soon as Windows powers-up the USB port. But if you connect it to a USB port that is permanently powered I suppose you might just have to reconnect it if the Arduino hadn't noticed that Windows had gone away and was coming back as a brand new session.

adicontakt (author)p_leriche2017-01-23

this guy made it with rgb leds , i am trying to figure it out how , but i am only an electronist and not so good with "coding" . maybe you can take a look

p_leriche (author)adicontakt2017-01-23

Yes, I looked at this one. The LED colour is changed as you turn the knob but it has no way of knowing what the PC thinks the volume level is to start with. It simply colours the LED more blue as you increase the volume until it's all blue, or more red as you decrease it until it's all red. So for it to mean anything, you'd have to first turn the knob until it's all red AND the PC thinks the volume is zero in order to get it into step.

You could do the same with mine if you wanted to. It has the advantage that no drivers are required and it's OS-independant whereas his requires a programme running on the PC to change the volume, the Arduino sending it conventional keyboard hotkey combinations.

adicontakt (author)p_leriche2017-01-25

ok , but i don"t now how to do it , that s why i ask if you could change the code and schematic

p_leriche (author)adicontakt2017-01-25

I'm afraid I can't undertake to do custom variants for people. Coding Arduino isn't hard and it's a lot of fun, and there are loads of Instructables and other tutorials to get you started. Read up all you can and start learning - hey, it could even lead you into a new career!

CurtR (author)2017-01-22

Are you sure of those box dimensions? Might they be 50mm x 50mm x 20mm?

p_leriche (author)CurtR2017-01-23

Silly misteak ;-) Well spotted!

ElectronicaXAB3 (author)2017-01-21

Voted! Nice work!

Pantopush (author)2017-01-21

This is actually exactly what I wanted for another project I had in mind. Great job!

Yavnik (author)2017-01-20

Awesome!!! Definitely gonna vote for you!!!

Jules1050 (author)2017-01-20

Good job, looks very clean!

About This Instructable




Bio: You can also find me on and Twitter @pleriche. Volunteer with and keen to share my knowledge and skills and do ... More »
More by p_leriche:How to Build Arduino Weighing ScalesUSB Volume Control and Caps Lock LED - simple, cheap, extensibleFibreoptic Christmas Tree Upgrade
Add instructable to: