├── LICENSE ├── README.md ├── config.yaml └── deej_encoder.ino /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 SNR-Tech-Bytes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deej_encoder 2 | Branch of the Deej Library by Omriharel but for use with encoders 3 | 4 | Youtube Video: https://youtu.be/pkEw7x2GMIA 5 | 6 | Original work: https://github.com/omriharel/deej/blob/master/LICENSE 7 | 8 | Thingiverse: https://www.thingiverse.com/thing:4598978/ 9 | 10 | 11 | Bill of Materials: 12 | 13 | 1x Enclosure (3d Printed) 14 | 15 | 1x Front Plate (3d Printed) 16 | 17 | 5x Click encoders (https://www.amazon.com/gp/product/B06XQTHDRR/) 18 | 19 | 5x Neopixels (https://www.adafruit.com/product/1612) 20 | 21 | 1x Arduino MkrZero (https://store.arduino.cc/usa/arduino-mkrzero) 22 | 23 | ~30x Jumper Cables Male to Female (https://www.amazon.com/Elegoo-EL-CP-004-Multicolored-Breadboard-arduino/dp/B01EV70C78/) 24 | 25 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | # process names are case-insensitive 2 | # you can use 'master' to indicate the master channel, or a list of process names to create a group 3 | # you can use 'mic' to control your mic input level (uses the default recording device) 4 | # you can use 'deej.unmapped' to control all apps that aren't bound to any slider (this ignores master, system, mic and device-targeting sessions) (experimental) 5 | # windows only - you can use 'deej.current' to control the currently active app (whether full-screen or not) (experimental) 6 | # windows only - you can use a device's full name, i.e. "Speakers (Realtek High Definition Audio)", to bind it. this works for both output and input devices 7 | # windows only - you can use 'system' to control the "system sounds" volume 8 | # important: slider indexes start at 0, regardless of which analog pins you're using! 9 | slider_mapping: 10 | 0: master 11 | 1: discord.exe 12 | 2: chrome.exe 13 | 3: 14 | - pathofexile_x64.exe 15 | - rocketleague.exe 16 | - EoCApp.exe 17 | - Titanfall2.exe 18 | 4: spotify.exe 19 | 20 | # set this to true if you want the controls inverted (i.e. top is 0%, bottom is 100%) 21 | invert_sliders: false 22 | 23 | # settings for connecting to the arduino board 24 | com_port: COM3 25 | baud_rate: 9600 26 | 27 | # adjust the amount of signal noise reduction depending on your hardware quality 28 | # supported values are "low" (excellent hardware), "default" (regular hardware) or "high" (bad, noisy hardware) 29 | noise_reduction: high 30 | -------------------------------------------------------------------------------- /deej_encoder.ino: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* Encoder Library - TwoKnobs Example 4 | * http://www.pjrc.com/teensy/td_libs_Encoder.html 5 | * 6 | * This example code is in the public domain. 7 | */ 8 | 9 | #include 10 | #include 11 | const int NUM_SLIDERS = 5; 12 | #define NUMPIXELS 5 13 | #define PIN 7 14 | Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); 15 | int analogSliderValues[NUM_SLIDERS]; 16 | // Change these pin numbers to the pins connected to your encoder. 17 | // Best Performance: both pins have interrupt capability 18 | // Good Performance: only the first pin has interrupt capability 19 | // Low Performance: neither pin has interrupt capability 20 | Encoder knobMaster(4,11); 21 | Encoder knobDiscord(2 , 6); 22 | Encoder knobChrome(12,8); 23 | Encoder knobGaming(14,9); 24 | Encoder knobMusic(10, 5); 25 | int Master, Discord, Chrome, Gaming, Music; 26 | int masterMute, discordMute, chromeMute, gamingMute, musicMute; 27 | int masterDebounceTime; 28 | // avoid using pins with LEDs attached 29 | //buttons: 1, A5, A2, A1, A6 30 | const int masterButton=1; 31 | const int discordButton=A5; 32 | const int chromeButton=A2; 33 | const int gamingButton=A1; 34 | const int musicButton=A6; 35 | unsigned long lastDebounceTime = 0; // the last time the output pin was toggled 36 | unsigned long debounceDelay = 175; // the debounce time; increase if the output flickers 37 | 38 | int masterState=0; 39 | int discordState=0; 40 | int chromeState=0; 41 | int gamingState=0; 42 | int musicState=0; 43 | 44 | 45 | 46 | 47 | 48 | void setup() { 49 | 50 | Serial.begin(9600); 51 | pinMode(masterButton, INPUT_PULLUP); 52 | pinMode(discordButton, INPUT_PULLUP); 53 | pinMode(chromeButton, INPUT_PULLUP); 54 | pinMode(gamingButton, INPUT_PULLUP); 55 | pinMode(musicButton, INPUT_PULLUP); 56 | 57 | analogSliderValues[0] = 512; 58 | knobMaster.write(51); 59 | analogSliderValues[1] = 512; 60 | knobDiscord.write(51); 61 | analogSliderValues[2] = 512; 62 | knobChrome.write(51); 63 | analogSliderValues[3] = 512; 64 | knobGaming.write(51); 65 | analogSliderValues[4] = 512; 66 | knobMusic.write(51); 67 | pixels.begin(); 68 | pixels.clear(); 69 | masterMute=0; 70 | discordMute=0; 71 | chromeMute=0; 72 | gamingMute=0; 73 | musicMute=0; 74 | } 75 | 76 | 77 | 78 | void loop() { 79 | 80 | Master = knobMaster.read(); 81 | Discord = knobDiscord.read(); 82 | Chrome = knobChrome.read(); 83 | Gaming = knobGaming.read(); 84 | Music = knobMusic.read(); 85 | 86 | 87 | 88 | checkButtons(); 89 | checkEncoders(); 90 | sendSliderValues(); 91 | //printSliderValues();//debug 92 | pixels.show(); 93 | 94 | 95 | } 96 | 97 | void sendSliderValues() { 98 | String builtString = String(""); 99 | 100 | for (int i = 0; i < NUM_SLIDERS; i++) { 101 | builtString += String((int)analogSliderValues[i]); 102 | 103 | if (i < NUM_SLIDERS - 1) { 104 | builtString += String("|"); 105 | } 106 | } 107 | 108 | Serial.println(builtString); 109 | } 110 | void printSliderValues() { 111 | for (int i = 0; i < NUM_SLIDERS; i++) { 112 | String printedString = String("Slider #") + String(i + 1) + String(": ") + String(analogSliderValues[i]) + String(" mV"); 113 | Serial.write(printedString.c_str()); 114 | 115 | if (i < NUM_SLIDERS - 1) { 116 | Serial.write(" | "); 117 | } else { 118 | Serial.write("\n"); 119 | } 120 | } 121 | } 122 | void checkButtons(){ 123 | if (digitalRead(masterButton)==0 && masterState ==0){ 124 | masterMute = !masterMute ; 125 | masterState =1; 126 | delay(25); 127 | } 128 | if (digitalRead(masterButton)==1){ 129 | masterState=0; 130 | } 131 | if (digitalRead(discordButton)==0 && discordState ==0){ 132 | discordMute = !discordMute ; 133 | discordState =1; 134 | delay(25); 135 | } 136 | if (digitalRead(discordButton)==1){ 137 | discordState=0; 138 | } 139 | if (digitalRead(chromeButton)==0 && chromeState ==0){ 140 | chromeMute = !chromeMute ; 141 | chromeState =1; 142 | delay(25); 143 | } 144 | if (digitalRead(chromeButton)==1){ 145 | chromeState=0; 146 | } 147 | if (digitalRead(gamingButton)==0 && gamingState ==0){ 148 | gamingMute = !gamingMute ; 149 | gamingState =1; 150 | delay(25); 151 | } 152 | if (digitalRead(gamingButton)==1){ 153 | gamingState=0; 154 | } 155 | if (digitalRead(musicButton)==0 && musicState ==0){ 156 | musicMute = !musicMute ; 157 | musicState =1; 158 | delay(25); 159 | } 160 | if (digitalRead(musicButton)==1){ 161 | musicState=0; 162 | } 163 | } 164 | void checkEncoders(){ 165 | if (Master > 0 && Master < 102 && masterMute==0){ 166 | analogSliderValues[0]=Master*10; 167 | pixels.setPixelColor(4, pixels.Color(0, 150, 0)); 168 | 169 | } 170 | else if (masterMute==0 && (Master > 102 || Master==102)){ 171 | analogSliderValues[0]=102*10; 172 | knobMaster.write(102); 173 | pixels.setPixelColor(4, pixels.Color(0, 150, 0)); 174 | 175 | } 176 | else if (masterMute==1){ 177 | analogSliderValues[0]=0; 178 | pixels.setPixelColor(4, pixels.Color(150, 0, 0)); 179 | 180 | } 181 | 182 | else { 183 | analogSliderValues[0]=0; 184 | knobMaster.write(0); 185 | pixels.setPixelColor(4, pixels.Color(150, 0, 0)); 186 | 187 | } 188 | 189 | if (Discord > 0 && (Discord < 102 && discordMute==0)){ 190 | analogSliderValues[1]=Discord*10; 191 | pixels.setPixelColor(3, pixels.Color(0, 150, 0)); 192 | } 193 | else if (discordMute==0 && Discord > 102 || Discord==102){ 194 | analogSliderValues[1]=102*10; 195 | knobDiscord.write(102); 196 | pixels.setPixelColor(3, pixels.Color(0, 150, 0)); 197 | } 198 | else if (discordMute==1){ 199 | analogSliderValues[1]=0; 200 | pixels.setPixelColor(3, pixels.Color(150, 0, 0)); 201 | } 202 | else { 203 | analogSliderValues[1]=0; 204 | knobDiscord.write(0); 205 | pixels.setPixelColor(3, pixels.Color(150, 0, 0)); 206 | } 207 | if (chromeMute==0 && Chrome > 0 && Chrome < 102){ 208 | analogSliderValues[2]=Chrome*10; 209 | pixels.setPixelColor(2, pixels.Color(0, 150, 0)); 210 | } 211 | else if (chromeMute ==0 && (Chrome > 102 || Chrome==102)){ 212 | analogSliderValues[2]=102*10; 213 | knobChrome.write(102); 214 | pixels.setPixelColor(2, pixels.Color(0, 150, 0)); 215 | } 216 | else if (chromeMute==1){ 217 | analogSliderValues[2]=0; 218 | pixels.setPixelColor(2, pixels.Color(150, 0, 0)); 219 | } 220 | else { 221 | analogSliderValues[2]=0; 222 | knobChrome.write(0); 223 | pixels.setPixelColor(2, pixels.Color(150, 0, 0)); 224 | } 225 | if (gamingMute==0 && Gaming > 0 && Gaming < 102){ 226 | analogSliderValues[3]=Gaming*10; 227 | pixels.setPixelColor(1, pixels.Color(0, 150, 0)); 228 | 229 | } 230 | else if (gamingMute==0 && (Gaming > 102 || Gaming==102)){ 231 | analogSliderValues[3]=102*10; 232 | knobGaming.write(102); 233 | pixels.setPixelColor(1, pixels.Color(0, 150, 0)); 234 | } 235 | else if (gamingMute==1){ 236 | analogSliderValues[3]=0; 237 | pixels.setPixelColor(1, pixels.Color(150, 0, 0)); 238 | } 239 | else { 240 | analogSliderValues[3]=0; 241 | knobGaming.write(0); 242 | pixels.setPixelColor(1, pixels.Color(150, 0, 0)); 243 | } 244 | if (musicMute==0 && Music > 0 && Music < 102){ 245 | analogSliderValues[4]=Music*10; 246 | pixels.setPixelColor(0, pixels.Color(0, 150, 0)); 247 | } 248 | else if (musicMute ==0 && (Music > 102 || Music==102)){ 249 | analogSliderValues[4]=102*10; 250 | knobMusic.write(102); 251 | pixels.setPixelColor(0, pixels.Color(0, 150, 0)); 252 | } 253 | else if (musicMute==1){ 254 | analogSliderValues[4]=0; 255 | pixels.setPixelColor(0, pixels.Color(150, 0, 0)); 256 | } 257 | else { 258 | analogSliderValues[4]=0; 259 | knobMusic.write(0); 260 | pixels.setPixelColor(0, pixels.Color(150, 0, 0)); 261 | } 262 | 263 | } 264 | --------------------------------------------------------------------------------