USB Volume Control

I am not any sort of coder but I found this video on how to make a USB Volume Control Here is the video: Arduino: USB Volume Control - YouTube I have the whole thing wired out(not that it matters right now) but it won’t compile, here is my Code:

 #include <Encoder.h>
Encoder myEnc(3,2);
const int pinLed = LED_BUILTIN;
const int pinButton = 12;
int bulbPin = 9; 
int oldPosition  = -999;
boolean muted = 0;
int safePosition = 0;
int volume = 0;
int oldVolume = 0;
int actualVolume = 0;
void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
Serial.begin(9600);
  Consumer.begin();
  delay(1000);
  for(int i = 50; i > 0; i--){
  Consumer.write(MEDIA_VOLUME_DOWN);
  delay(1);
  }
}

void loop() {
  int newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    safePosition = newPosition;
    if(newPosition < 0){
      safePosition = 0;
      myEnc.write(safePosition);
    }
    if(newPosition > 400){
      safePosition = 400;
      myEnc.write(safePosition);
    }
    oldPosition = safePosition;
    volume = safePosition / 4;
    volume = volume / 2;
    noInterrupts();  
    Serial.print("calc volume: ");
    Serial.print(volume);
    Serial.print(" act volume: ");
    Serial.print(actualVolume);
    Serial.println("");
    changeVolume();
    interrupts();
   
  }
  
  if (!digitalRead(pinButton)) {
   
    Consumer.write(MEDIA_VOLUME_MUTE);
    muted = !muted;
    delay(300);
  }
  if(muted){
    analogWrite(bulbPin, 0);
  }
  else{
    analogWrite(bulbPin, map(volume, 0, 100, 0, 255));
  }
  
  if (digitalRead(7)) {
    //Serial.write(227);
    Keyboard.press(KEY_LEFT_GUI);
    Keyboard.press('d');
    Keyboard.releaseAll();
    delay(300);
  }
 if (digitalRead(8)) {
  Keyboard.println("Thanks,");
  Keyboard.println("");
  Keyboard.println("David Watts");
    Keyboard.println("Resident Nerd and Tinkerer");
    delay(300);
  }

}

void changeVolume(){
if (volume != oldVolume) {
    if(volume > oldVolume){
      //delay(100);
      Consumer.write(MEDIA_VOLUME_UP);
      actualVolume = actualVolume + 2;
      oldVolume = volume; 
    }
    else{
      //delay(100);
      Consumer.write(MEDIA_VOLUME_DOWN);
      actualVolume = actualVolume - 2;
      oldVolume = volume; 
    }
  }
}

Here is my error report:

Arduino: 1.6.5 (Windows 8.1), Board: "Arduino/Genuino Uno"

Using library Encoder in folder: C:\Users\Owner\Documents\Arduino\libraries\Encoder 



C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IC:\Users\Owner\Documents\Arduino\libraries\Encoder C:\Users\Owner\AppData\Local\Temp\build3758709467688430361.tmp\HID-volume-control.cpp -o C:\Users\Owner\AppData\Local\Temp\build3758709467688430361.tmp\HID-volume-control.cpp.o 

HID-volume-control.ino: In function 'void setup()':
HID-volume-control.ino:16:3: error: 'Consumer' was not declared in this scope
HID-volume-control.ino:19:18: error: 'MEDIA_VOLUME_DOWN' was not declared in this scope
HID-volume-control.ino: In function 'void loop()':
HID-volume-control.ino:52:5: error: 'Consumer' was not declared in this scope
HID-volume-control.ino:52:20: error: 'MEDIA_VOLUME_MUTE' was not declared in this scope
HID-volume-control.ino:65:5: error: 'Keyboard' was not declared in this scope
HID-volume-control.ino:65:20: error: 'KEY_LEFT_GUI' was not declared in this scope
HID-volume-control.ino:71:3: error: 'Keyboard' was not declared in this scope
HID-volume-control.ino: In function 'void changeVolume()':
HID-volume-control.ino:84:7: error: 'Consumer' was not declared in this scope
HID-volume-control.ino:84:22: error: 'MEDIA_VOLUME_UP' was not declared in this scope
HID-volume-control.ino:90:7: error: 'Consumer' was not declared in this scope
HID-volume-control.ino:90:22: error: 'MEDIA_VOLUME_DOWN' was not declared in this scope
'Consumer' was not declared in this scope

Thanks in advance. :slight_smile:

The code linked from the YouTube video seems to have forgotten to include the NicoHood HID library. I can't seem to figure out how to install the library so good luck.

You can use the built in Keyboard function. You just have to take the MEDIA key codes and add 136.

johnwasser: The code linked from the YouTube video seems to have forgotten to include the NicoHood HID library. I can't seem to figure out how to install the library so good luck.

You can use the built in Keyboard function. You just have to take the MEDIA key codes and add 136.

Thank you, though I don't quite understand what you mean by adding 136 to MEDIA keycodes. Is there anyway you could rephrase it?

Don, you really should post your code and any error messages within code </> tags. It makes life much easier for those that try to help you out.
Putting your links between hyperlink (url) tags is a pretty good idea, too, so people don’t have to copy and paste. The easier you make it for people to help you, the more help you’ll get. :wink:

I guess I was wrong. The Arduino library can only handle raw USB scan codes up to 119 and the scan codes for Volume Up and Volume Down are 128 and 129 respectively. To get it to work you would have to change functions in the avr core.

In HID.cpp change the Keyboard_:press() function to start with:

size_t Keyboard_::press(uint16_t k) 
{
    uint8_t i;
    if (k >= 136) {         // it's a non-printing key (not a modifier)
        k = k - 136;

In USBAPI.h change the declaration of Keyboard_:press() to match:

    virtual size_t press(uint16_t k);

With those changes you can use Keyboard.press(128+136) for Volume Up and Keyboard.press(129+136) for Volume Down. You will need to use Keyboard.releaseAll() to release the keys or modify Keyboard_release() to allow for values higher than 255.

johnwasser: I guess I was wrong. The Arduino library can only handle raw USB scan codes up to 119 and the scan codes for Volume Up and Volume Down are 128 and 129 respectively. To get it to work you would have to change functions in the avr core.

In HID.cpp change the Keyboard_:press() function to start with:

size_t Keyboard_::press(uint16_t k) 
{
    uint8_t i;
    if (k >= 136) {         // it's a non-printing key (not a modifier)
        k = k - 136;

In USBAPI.h change the declaration of Keyboard_:press() to match:

  virtual size_t press(uint16_t k);

With those changes you can use Keyboard.press(128+136) for Volume Up and Keyboard.press(129+136) for Volume Down. You will need to use Keyboard.releaseAll() to release the keys or modify Keyboard_release() to allow for values higher than 255.

Ok thank you, I have the files changed, but I seem to be confused about what to do for coding.

After getting rid of “Consumer” the code would look like this:

#include <Encoder.h>
Encoder myEnc(3, 2);
const int pinLed = LED_BUILTIN;
const int pinButton = 12;
const int bulbPin = 9;
int oldPosition  = -999;
boolean muted = 0;
int safePosition = 0;
int volume = 0;
int oldVolume = 0;
int actualVolume = 0;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
  Serial.begin(9600);
  delay(1000);
  for (int i = 50; i > 0; i--) {
    Keyboard.press(129 + 136); // Volume Down
    Keyboard.releaseAll();
    delay(1);
  }
}

void loop() {
  int newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    safePosition = newPosition;
    if (newPosition < 0) {
      safePosition = 0;
      myEnc.write(safePosition);
    }
    if (newPosition > 400) {
      safePosition = 400;
      myEnc.write(safePosition);
    }
    oldPosition = safePosition;
    volume = safePosition / 4;
    volume = volume / 2;
    noInterrupts();
    Serial.print("calc volume: ");
    Serial.print(volume);
    Serial.print(" act volume: ");
    Serial.print(actualVolume);
    Serial.println("");
    changeVolume();
    interrupts();

  }

  if (!digitalRead(pinButton)) {
    Keyboard.press(127 + 136); // Mute
    Keyboard.releaseAll();
    muted = !muted;
    delay(300);
  }

  if (muted) {
    analogWrite(bulbPin, 0);
  }
  else {
    analogWrite(bulbPin, map(volume, 0, 100, 0, 255));
  }

  if (digitalRead(7)) {
    //Serial.write(227);
    Keyboard.press(KEY_LEFT_GUI);
    Keyboard.press('d');
    Keyboard.releaseAll();
    delay(300);
  }

  if (digitalRead(8)) {
    Keyboard.println("Thanks,");
    Keyboard.println("");
    Keyboard.println("David Watts");
    Keyboard.println("Resident Nerd and Tinkerer");
    delay(300);
  }
}

void changeVolume() {
  if (volume != oldVolume) {
    if (volume > oldVolume) {
      //delay(100);
      Keyboard.press(128 + 136); // Volume Up
      Keyboard.releaseAll();
      actualVolume += 2;
      oldVolume = volume;
    }
    else {
      //delay(100);
      Keyboard.press(129 + 136); // Volume Down
      Keyboard.releaseAll();
      actualVolume -= 2;
      oldVolume = volume;
    }
  }
}

johnwasser:
After getting rid of “Consumer” the code would look like this:

#include <Encoder.h>

Encoder myEnc(3, 2);
const int pinLed = LED_BUILTIN;
const int pinButton = 12;
const int bulbPin = 9;
int oldPosition  = -999;
boolean muted = 0;
int safePosition = 0;
int volume = 0;
int oldVolume = 0;
int actualVolume = 0;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
  Serial.begin(9600);
  delay(1000);
  for (int i = 50; i > 0; i–) {
    Keyboard.press(129 + 136); // Volume Down
    Keyboard.releaseAll();
    delay(1);
  }
}

void loop() {
  int newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    safePosition = newPosition;
    if (newPosition < 0) {
      safePosition = 0;
      myEnc.write(safePosition);
    }
    if (newPosition > 400) {
      safePosition = 400;
      myEnc.write(safePosition);
    }
    oldPosition = safePosition;
    volume = safePosition / 4;
    volume = volume / 2;
    noInterrupts();
    Serial.print(“calc volume: “);
    Serial.print(volume);
    Serial.print(” act volume: “);
    Serial.print(actualVolume);
    Serial.println(””);
    changeVolume();
    interrupts();

}

if (!digitalRead(pinButton)) {
    Keyboard.press(127 + 136); // Mute
    Keyboard.releaseAll();
    muted = !muted;
    delay(300);
  }

if (muted) {
    analogWrite(bulbPin, 0);
  }
  else {
    analogWrite(bulbPin, map(volume, 0, 100, 0, 255));
  }

if (digitalRead(7)) {
    //Serial.write(227);
    Keyboard.press(KEY_LEFT_GUI);
    Keyboard.press(‘d’);
    Keyboard.releaseAll();
    delay(300);
  }

if (digitalRead(8)) {
    Keyboard.println(“Thanks,”);
    Keyboard.println("");
    Keyboard.println(“David Watts”);
    Keyboard.println(“Resident Nerd and Tinkerer”);
    delay(300);
  }
}

void changeVolume() {
  if (volume != oldVolume) {
    if (volume > oldVolume) {
      //delay(100);
      Keyboard.press(128 + 136); // Volume Up
      Keyboard.releaseAll();
      actualVolume += 2;
      oldVolume = volume;
    }
    else {
      //delay(100);
      Keyboard.press(129 + 136); // Volume Down
      Keyboard.releaseAll();
      actualVolume -= 2;
      oldVolume = volume;
    }
  }
}

Thank You!
Is there anyway my friend could do this with an Arduino Uno?

don3194: Is there anyway my friend could do this with an Arduino Uno?

Not easily. Your friend should scrape together $6 and order a cheap Arduino Micro clone like: http://www.ebay.com/itm/Leonardo-Pro-Micro-ATmega32U4-Arduino-IDE-1-0-3-Bootloader-replace-Pro-Mini-Z3-/252033324716

johnwasser: Not easily. Your friend should scrape together $6 and order a cheap Arduino Micro clone like: http://www.ebay.com/itm/Leonardo-Pro-Micro-ATmega32U4-Arduino-IDE-1-0-3-Bootloader-replace-Pro-Mini-Z3-/252033324716

Ok thanks again!