Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 2 | |||
![]() |
| × | 9 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 |
I wanted to build a dedicated controller for the Scorpio's equalizer, and realized it could be done by emulating a USB keyboard using an Arduino.
It took me a while to get the encoders right, so they didn't skip any steps, even when turned fast.
Done with the software, I had some goals to design the enclosure:- mount to the CL-12 side panels- mimic the layout of a console EQ- keep the visual identity of the CL-12
By far, the most complicated part was fitting the electronics inside the enclosure, in a way that it could be assembled and disassembled.
Making a simple device like this increases my admiration for the huge amount of engineering required to build professional tools, such as Sound Devices recorders.
/*
DISCLAIMER:
This project is licensed under Creative Commons CC BY-NC 4.0
https://creativecommons.org/licenses/by-nc/4.0/
You are free to:
Share — copy and redistribute the material in any medium or format
Adapt — remix, transform, and build upon the material
*You may NOT use the material for commercial purposes*
You must give appropriate credit and provide a link to the license.
It also utilizes libraries from third party developers:
>> NicoHood Arduino HID Project:
Copyright (c) 2014-2015 NicoHood
https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard
>> Buxtronix Arduino Rotary:
Copyright 2011 Ben Buxton. Licenced under the GNU GPL Version 3
https://github.com/buxtronix/arduino/tree/master/libraries/Rotary
---------------------------------------------------------------------------
How the buttons and encoders are connected to the Arduino Pro Micro board:
Encoder 1:
GND --> GND
+ --> 5V
SW1 --> 7
DT --> 0
CLK --> 1
Encoder 2:
GND --> GND
+ --> 5V
SW2 --> 8
DT --> 3
CLK --> 2
Button 1 = 9;
Button 2 = 21;
Button 3 = 20;
Button 4 = 19;
Button 5 = 18;
Button 6 = 15;
Button 7 = 14;
Button 8 = 16;
Button 9 = 10;
Green LED (10k resistor) = 5;
Blue LED (1k resistor) = 6;
*/
// includes third party libraries
#include <HID-Project.h>
#include <Rotary.h>
Rotary encoder1 = Rotary(1, 0); //CLK, DATA
Rotary encoder2 = Rotary(2, 3); //CLK, DATA
// encoder 1 switch
int botaoEnc1 = 7;
int statusBotaoEnc1 = HIGH;
// encoder 2 switch
int botaoEnc2 = 8;
int statusBotaoEnc2 = HIGH;
//leds
int ledAzul = 5; // green LED
int ledVerde = 6; // blue LED
// buttons
int botao1 = 9;
int botao2 = 21;
int botao3 = 20;
int botao4 = 19;
int botao5 = 18;
int botao6 = 15;
int botao7 = 14;
int botao8 = 16;
int botao9 = 10;
int statusBotao1 = HIGH;
int statusBotao2 = HIGH;
int statusBotao3 = HIGH;
int statusBotao4 = HIGH;
int statusBotao5 = HIGH;
int statusBotao6 = HIGH;
int statusBotao7 = HIGH;
int statusBotao8 = HIGH;
// button 9 variables (change mode)
int statusBotao9 = HIGH; // the current leituraBotao9 from the input pin
int ultimoStatusBotao9 = HIGH; // the previous leituraBotao9 from the input pin
unsigned long timerReset = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 600; // interval at which to blink (milliseconds)
// sets the initial mode (1 = EQ, 2 = general control)
int modo = 2;
int counter = 0;
// SETUP
void setup() {
Serial.begin (9600); // starts the serial monitor and set the baud rate
// attaches the interrupts to the encoders
attachInterrupt(digitalPinToInterrupt(1), rotate1, CHANGE);
attachInterrupt(digitalPinToInterrupt(0), rotate1, CHANGE);
attachInterrupt(digitalPinToInterrupt(2), rotate2, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), rotate2, CHANGE);
// sets the pin modes and pull up resistors
pinMode (botaoEnc1, INPUT_PULLUP);
pinMode (botaoEnc2, INPUT_PULLUP);
pinMode (botao1, INPUT_PULLUP);
pinMode (botao2, INPUT_PULLUP);
pinMode (botao3, INPUT_PULLUP);
pinMode (botao4, INPUT_PULLUP);
pinMode (botao5, INPUT_PULLUP);
pinMode (botao6, INPUT_PULLUP);
pinMode (botao7, INPUT_PULLUP);
pinMode (botao8, INPUT_PULLUP);
pinMode (botao9, INPUT_PULLUP);
//LEDS
pinMode (ledAzul, OUTPUT);
pinMode (ledVerde, OUTPUT);
// inicia o controle com o BootKeyboard
BootKeyboard.begin();
} // END OF SETUP
//LOOP
void loop() {
// light up the LEDS to indicate the current mode. I'm using PWM to match the LEDs brightness
if (modo == 1) {
analogWrite(ledAzul, 50); // low brightness LED, 1kΩ resistor
analogWrite(ledVerde, 0);
}
if (modo == 2) {
analogWrite(ledAzul, 0);
analogWrite(ledVerde, 3); // high brightness LED, 10kΩ resistor
}
// reads button 9 and sets the mode:
int leituraBotao9 = digitalRead(botao9);
if (leituraBotao9 != ultimoStatusBotao9) {
timerReset = millis();
}
if ((millis() - timerReset) > debounceDelay) {
if (leituraBotao9 != statusBotao9) {
statusBotao9 = leituraBotao9;
if (statusBotao9 == LOW) {
modo++;
if (modo == 3 ) {
modo = 1;
}
if (modo == 1) {
Serial.println("MODE 1");
}
if (modo == 2) {
Serial.println("MODE 2");
}
}
}
}
ultimoStatusBotao9 = leituraBotao9; // resets button 9 last status
// once the mode is set, what each button does:
// MODE 1: EQUALIZER
if (modo == 1) {
// ENCODER 1 SWITCH
statusBotaoEnc1 = digitalRead(botaoEnc1);
if (statusBotaoEnc1 == LOW) {
BootKeyboard.press(KEY_F6);
BootKeyboard.releaseAll();
Serial.println("MODE 1: F6 = IN/BYPASS");
// delay para debounce
delay(200);
}
// ENCODER 2 SWITCH
statusBotaoEnc2 = digitalRead(botaoEnc2);
if (statusBotaoEnc2 == LOW) {
BootKeyboard.press(KEY_F9);
BootKeyboard.releaseAll();
Serial.println("MODE 1: F9 = Q");
// delay para debounce
delay(200);
}
// BUTTON 1 (EQ)
statusBotao1 = digitalRead(botao1);
// if button 1 is pressed:
if (statusBotao1 == LOW) {
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
Serial.println("MODE 1: Open EQ");
// debounce delay
delay(200);
}
// BUTTON 2 (Pre/Post/Off)
statusBotao2 = digitalRead(botao2);
// if button 2 is pressed:
if (statusBotao2 == LOW) {
BootKeyboard.press(KEY_F5);
BootKeyboard.releaseAll();
Serial.println("MODE 1: Pre/Post/Off");
// debounce delay
delay(200);
}
// BUTTON 3 (HIGH)
statusBotao3 = digitalRead(botao3);
// if button 3 is pressed:
if (statusBotao3 == LOW) {
BootKeyboard.press(KEY_F8);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F8);
BootKeyboard.releaseAll();
Serial.println("MODE 1: High Band");
// debounce delay
delay(200);
}
// BUTTON 4 (MID)
statusBotao4 = digitalRead(botao4);
// if button 4 is pressed:
if (statusBotao4 == LOW) {
BootKeyboard.press(KEY_F7);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F7);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F8);
BootKeyboard.releaseAll();
Serial.println("MODE 1: Mid Band");
//debounce delay
delay(200);
}
// BUTTON 5 (LOW)
statusBotao5 = digitalRead(botao5);
// if button 5 is pressed:
if (statusBotao5 == LOW) {
BootKeyboard.press(KEY_F7);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F7);
BootKeyboard.releaseAll();
Serial.println("MODE 1: Low Band");
// debounce delay
delay(200);
}
// BUTTON 6 (Peak/Shelf)
statusBotao6 = digitalRead(botao6);
// if button 6 is pressed:
if (statusBotao6 == LOW) {
BootKeyboard.press(KEY_F10);
BootKeyboard.releaseAll();
Serial.println("MODE 1: Peak/Shelf");
// debounce delay
delay(200);
}
// BUTTON 7 (Not mapped in MODE 1)
// BUTTON 8 (Exit)
statusBotao8 = digitalRead(botao8);
// if button 8 is pressed:
if (statusBotao8 == LOW) {
BootKeyboard.press(KEY_F1);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_ESC);
BootKeyboard.releaseAll();
Serial.println("Exit");
// // BUTTON 6 (Peak/Shelf)
delay(200);
}
} //END OF MODE 1
// MODE 2: GENERAL CONTROL
if (modo == 2) {
// ENCODER 1 SWITCH
statusBotaoEnc1 = digitalRead(botaoEnc1);
// if encoder 2 switch is pressed:
if (statusBotaoEnc1 == LOW) {
BootKeyboard.press(KEY_RIGHT_CTRL);
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
Serial.println("MODE 2: CTRL + ENTER");
// debounce delay
delay(200);
}
// ENCODER 2 SWITCH
statusBotaoEnc2 = digitalRead(botaoEnc2);
// if encoder 2 switch is pressed:
if (statusBotaoEnc2 == LOW) {
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
Serial.println("MODO 2: ENTER");
// debounce delay
delay(200);
}
// BUTTON 1 (MENU)
statusBotao1 = digitalRead(botao1);
// if button 1 is pressed:
if (statusBotao1 == LOW) {
BootKeyboard.press(KEY_F1);
BootKeyboard.releaseAll();
Serial.println("MODE 2: MENU");
// debounce delay
delay(200);
}
// BUTTON 2 (ESC)
statusBotao2 = digitalRead(botao2);
// if button 2 is pressed:
if (statusBotao2 == LOW) {
BootKeyboard.press(KEY_ESC);
BootKeyboard.releaseAll();
Serial.println("MODE 2: ESC");
// debounce delay
delay(200);
}
// BUTTON 3 (EDIT LAST TAKE NOTES)
statusBotao3 = digitalRead(botao3);
// if button 3 is pressed:
if (statusBotao3 == LOW) {
BootKeyboard.press(KEY_F2);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
Serial.println("MODE 2: EDIT LAST TAKE NOTES");
// debounce delay
delay(200);
}
// BUTTON 4 (EDIT SCENE NAME)
statusBotao4 = digitalRead(botao4);
// if button 4 is pressed:
if (statusBotao4 == LOW) {
BootKeyboard.press(KEY_F2);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F5);
BootKeyboard.releaseAll();
Serial.println("MODE 2: EDIT SCENE NAME");
// debounce delay
delay(200);
}
// BUTTON 5 (RENAME AS "REHEARSAL")
statusBotao5 = digitalRead(botao5);
// if button 1 is pressed:
if (statusBotao5 == LOW) {
BootKeyboard.press(KEY_F2);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
BootKeyboard.print("ENSAIO");
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_RETURN);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_ESC);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_ESC);
BootKeyboard.releaseAll();
Serial.println("MODE 2: RENAME LAST TAKE AS REHEARSAL");
// debounce delay
delay(200);;
}
// BUTTON 6 (BUSES) *only works when in Meter View 1-8
statusBotao6 = digitalRead(botao6);
// if button 6 is pressed:
if (statusBotao6 == LOW) {
BootKeyboard.press(KEY_F12);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
Serial.println("MODE 2: BUS VIEW");
// debounce delay
delay(200);
}
// BOTAO 7 (OUPUTS) *only works when in Meter View 1-8
statusBotao7 = digitalRead(botao7);
// if button 7 is pressed:
if (statusBotao7 == LOW) {
BootKeyboard.press(KEY_F12);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
BootKeyboard.press(KEY_F3);
BootKeyboard.releaseAll();
Serial.println("MODE 2: OUTPUT VIEW");
// debounce delay
delay(200);
}
// BUTTON8 (Exit)
statusBotao8 = digitalRead(botao8);
// if button 6 is pressed:
if (statusBotao8 == LOW) {
BootKeyboard.press(KEY_F12);
BootKeyboard.releaseAll();
Serial.println("Exit");
// debounce delay
delay(200);
}
}// END OF MODE 2
} // END OF LOOP
// ENCODER 1
// rotate is called anytime the rotary inputs change state.
void rotate1() {
// ROTARY ENCODER 1, MODE 1
if (modo == 1) {
unsigned char result = encoder1.process();
if (result == DIR_CW) {
counter++;
Serial.println(counter);
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
} else if (result == DIR_CCW) {
counter--;
Serial.println(counter);
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
}
}
// ROTARY ENCODER 1, MODE 2
if (modo == 2) {
unsigned char result = encoder1.process();
if (result == DIR_CW) {
counter--;
Serial.println(counter);
BootKeyboard.press(KEY_RIGHT_CTRL);
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
} else if (result == DIR_CCW) {
counter++;
Serial.println(counter);
BootKeyboard.press(KEY_RIGHT_CTRL);
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
}
}
} // END OF ROTATE 1
// ENCODER 2
// rotate is called anytime the rotary inputs change state.
void rotate2() {
// ENCODER 2, MODE 1
if (modo == 1) {
unsigned char result = encoder2.process();
if (result == DIR_CW) {
counter++;
Serial.println(counter);
BootKeyboard.press(KEY_RIGHT_CTRL);
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
} else if (result == DIR_CCW) {
counter--;
Serial.println(counter);
BootKeyboard.press(KEY_RIGHT_CTRL);
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
}
}
// ENCODER 2, MODE 2
if (modo == 2) {
unsigned char result = encoder2.process();
if (result == DIR_CW) {
counter--;
Serial.println(counter);
BootKeyboard.press(KEY_UP_ARROW);
BootKeyboard.releaseAll();
} else if (result == DIR_CCW) {
counter++;
Serial.println(counter);
BootKeyboard.press(KEY_DOWN_ARROW);
BootKeyboard.releaseAll();
}
}
} // END OF ROTATE 2
Comments
Please log in or sign up to comment.