/*
Made by Gustavo Silveira, 2019.
- This Sketch reads the Arduino's digital and analog ports and send midi notes and midi control change
http://www.musiconerd.com
http://www.youtube.com/musiconerd
http://facebook.com/musiconerdmusiconerd
http://instagram.com/musiconerd/
http://www.gustavosilveira.net
[email protected]
If you are using for anything that's not for personal use don't forget to give credit.
PS: Just change the value that has a comment like " //* "
*/
/////////////////////////////////////////////
// Choosing your board
// Define your board, choose:
// "ATMEGA328" if using ATmega328 - Uno, Mega, Nano...
// "ATMEGA32U4" if using with ATmega32U4 - Micro, Pro Micro, Leonardo...
// "TEENSY" if using a Teensy board
// "DEBUG" if you just want to debug the code in the serial monitor
// you don't need to comment or uncomment any MIDI library below after you define your board
#define DEBUG 1 //* put here the uC you are using, like in the lines above followed by "1", like "ATMEGA328 1", "DEBUG 1", etc.
/////////////////////////////////////////////
// LIBRARIES
// -- Defines the MIDI library -- //
// if using with ATmega328 - Uno, Mega, Nano...
#ifdef ATMEGA328
#include <MIDI.h> // by Francois Best
//MIDI_CREATE_DEFAULT_INSTANCE();
// if using with ATmega32U4 - Micro, Pro Micro, Leonardo...
#elif ATMEGA32U4
#include "MIDIUSB.h"
#endif
// ---- //
//////////////////////////////////////////////
// Add this lib if using a cd4067 multiplexer
#ifdef USING_MUX
#include <Multiplexer4067.h> // Multiplexer CD4067 library >> https://github.com/sumotoy/Multiplexer4067
#endif
/////////////////////////////////////////////
// BUTTONS
const int N_BUTTONS = 6; //* total numbers of buttons
const byte N_BUTTONS_ARDUINO = 1; //If using Mux - these are pins plugged straight into the arduino
const int BUTTON_ARDUINO_PIN[N_BUTTONS] = {2}; //* pins of each button connected straight to the Arduino
#ifdef USING_MUX // Fill if you are using mux, otherwise just leave it
const byte N_BUTTONS_PER_MUX[N_MUX] = {5, 2}; //* number of buttons in each mux (in order)
const byte BUTTON_MUX_PIN[N_MUX][16] = {//* pin of each button of each mux in order
{10,11,12,13,14},
{0,1}
// ....
};
#endif
int buttonCState[N_BUTTONS] = {}; // stores the button current value
int buttonPState[N_BUTTONS] = {}; // stores the button previous value
//#define pin13 1 //* uncomment if you are using pin 13 (pin with led), or comment the line if not using
byte pin13index = 12; //* put the index of the pin 13 of the buttonPin[] array if you are using, if not, comment
// debounce
unsigned long lastDebounceTime[N_BUTTONS] = {0}; // the last time the output pin was toggled
unsigned long debounceDelay = 50; //* the debounce time; increase if the output flickers
/////////////////////////////////////////////
// POTENTIOMETERS
const int N_POTS = 6; //* total numbers of pots (slide & rotary)
const int N_POTS_ARDUINO = 5;
const int POT_ARDUINO_PIN[N_POTS_ARDUINO] = {A0, A1, A2, A3, A4}; //* pins of each pot connected straight to the Arduino
#ifdef USING_MUX
const int N_POTS_PER_MUX[N_MUX] = {0, 1};
const byte N_BUTTONS_MUX_PIN[N_MUX][16] = {//* pin of each button of each mux in order
{2},
// ....
};
#endif
int potCState[N_POTS] = {0}; // Current state of the pot
int potPState[N_POTS] = {0}; // Previous state of the pot
int potVar = 0; // Difference between the current and previous state of the pot
int midiCState[N_POTS] = {0}; // Current state of the midi value
int midiPState[N_POTS] = {0}; // Previous state of the midi value
const int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
const int varThreshold = 3; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[N_POTS] = {0}; // Previously stored time
unsigned long timer[N_POTS] = {0}; // Stores the time that has elapsed since the timer was reset
// Are you using high res faders?
#define USING_HIGH_RES_FADERS 1 //* comment if not using high res faders (any fader can be high res)
// Are you using Motorized Faders?
//#define USING_MOTORIZED_FADERS 1 //* comment if not using a motorized fader
/////////////////////////////////////////////
// MULTIPLEXERS
#ifdef USING_MUX
#define N_MUX 2 //* number of multiplexers
//* Define s0, s1, s2, s3, and x pins
#define s0 6
#define s1 5
#define s2 8
#define s3 7
#define x1 A5 // analog pin of the first mux
#define x2 A6 // analog pin of the second mux
//#define x3 A? // analog pin of the third mux
// add more #define and the x number if you need
// *** IMPORTANT: if you want to add more than one mux! ***
// In the Setup tab, line 123, add another "pinMode(x2, INPUT_PULLUP);" if you want to add a second mux,
// and "pinMode(x3, INPUT_PULLUP);" for a third mux, and so on...
// Initializes the multiplexer
Multiplexer4067 mux[N_MUX] = {
Multiplexer4067(s0, s1, s2, s3, x1), // The SIG pin where the multiplexer is connnected
Multiplexer4067(s0, s1, s2, s3, x2) // The SIG pin where the multiplexer is connnected
// Multiplexer4067(s0, s1, s2, s3, x3) // The SIG pin where the multiplexer is connnected
// ...
};
#endif
/////////////////////////////////////////////
// Are you using encoders?
//#define USING_ENCODER 1 //* comment if not using encoders, uncomment if using it.
//#define USING_ENCODER_MCP23017 1
//#define TRAKTOR 1 // uncomment if using with traktor, comment if not
// Are you using high res ENCODER?
//#define USING_HIGH_RES_ENC 1 //* comment if not using high res faders (any fader can be high res)
/////////////////////////////////////////////
// Are you using neopixels (any addressable strips)?
//#define USING_NEOPIXEL 1 //* comment if not using neopixels, uncomment if using it.
/////////////////////////////////////////////
// Are you using an I2C Oled Display?
//#define USING_DISPLAY 1 //* comment if not using an I2C Oled Display.
/////////////////////////////////////////////
// Are you using banks that can be switched with 2 buttons?
//#define USING_BANKS_WITH_BUTTONS 1 //* comment if not using banks with buttons.
//#define BANKS_FOR_BUTTONS 1
//#define BANKS_FOR_POTS 1
//#define BANKS_FOR_ENCODERS 1
// Are you using LED note feedback?
//#define USING_LED_FEEDBACK 1 //* comment if not using a VU
// Are you using a VU (led meter)?
//#define USING_VU 1//* comment if not using a VU
/////////////////////////////////////////////
// MIDI
byte midiCh = 0; //* MIDI channel to be used
byte note = 36; //* Lowest note to be used
byte cc = 1; //* Lowest MIDI CC to be used
/////////////////////////////////////////////
// SETUP
void setup() {
// Baud Rate
// use if using with ATmega328 (uno, mega, nano...)
// 31250 for MIDI class compliant | 115200 for Hairless MIDI
Serial.begin(115200); //*
#ifdef DEBUG
Serial.println("Debug mode");
Serial.println();
#endif
// Buttons
// Initialize buttons with pull up resistors
for (int i = 0; i < N_BUTTONS; i++) {
pinMode(BUTTON_ARDUINO_PIN[i], INPUT_PULLUP);
}
#ifdef pin13 // inicializa o pino 13 como uma entrada
pinMode(BUTTON_ARDUINO_PIN[pin13index], INPUT);
#endif
}
/////////////////////////////////////////////
// LOOP
void loop() {
buttons();
potentiometers();
}
/////////////////////////////////////////////
// BUTTONS
void buttons() {
for (int i = 0; i < N_BUTTONS; i++) {
buttonCState[i] = digitalRead(BUTTON_ARDUINO_PIN[i]); // read pins from arduino
#ifdef pin13
if (i == pin13index) {
buttonCState[i] = !buttonCState[i]; // inverts the pin 13 because it has a pull down resistor instead of a pull up
}
#endif
if ((millis() - lastDebounceTime[i]) > debounceDelay) {
if (buttonPState[i] != buttonCState[i]) {
lastDebounceTime[i] = millis();
if (buttonCState[i] == LOW) {
// Sends the MIDI note ON accordingly to the chosen board
#ifdef ATMEGA328
// use if using with ATmega328 (uno, mega, nano...)
MIDI.sendNoteOn(note + i, 127, midiCh); // note, velocity, channel
#elif ATMEGA32U4
// use if using with ATmega32U4 (micro, pro micro, leonardo...)
noteOn(midiCh, note + i, 127); // channel, note, velocity
MidiUSB.flush();
#elif TEENSY
//do usbMIDI.sendNoteOn if using with Teensy
usbMIDI.sendNoteOn(note + i, 127, midiCh); // note, velocity, channel
#elif DEBUG
Serial.print(i);
Serial.println(": button on");
#endif
}
else {
// Sends the MIDI note OFF accordingly to the chosen board
#ifdef ATMEGA328
// use if using with ATmega328 (uno, mega, nano...)
MIDI.sendNoteOn(note + i, 0, midiCh); // note, velocity, channel
#elif ATMEGA32U4
// use if using with ATmega32U4 (micro, pro micro, leonardo...)
noteOn(midiCh, note + i, 0); // channel, note, velocity
MidiUSB.flush();
#elif TEENSY
//do usbMIDI.sendNoteOn if using with Teensy
usbMIDI.sendNoteOn(note + i, 0, midiCh); // note, velocity, channel
#elif DEBUG
Serial.print(i);
Serial.println(": button off");
#endif
}
buttonPState[i] = buttonCState[i];
}
}
}
}
/////////////////////////////////////////////
// POTENTIOMETERS
void potentiometers() {
for (int i = 0; i < N_POTS; i++) { // Loops through all the potentiometers
potCState[i] = analogRead(POT_ARDUINO_PIN[i]); // reads the pins from arduino
midiCState[i] = map(potCState[i], 0, 1023, 0, 127); // Maps the reading of the potCState to a value usable in midi
potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot
if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
PTime[i] = millis(); // Stores the previous time
}
timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms
if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
potMoving = true;
}
else {
potMoving = false;
}
if (potMoving == true) { // If the potentiometer is still moving, send the change control
if (midiPState[i] != midiCState[i]) {
// Sends the MIDI CC accordingly to the chosen board
#ifdef ATMEGA328
// use if using with ATmega328 (uno, mega, nano...)
MIDI.sendControlChange(cc + i, midiCState[i], midiCh); // cc number, cc value, midi channel
#elif ATMEGA32U4
//use if using with ATmega32U4 (micro, pro micro, leonardo...)
controlChange(midiCh, cc + i, midiCState[i]); // (channel, CC number, CC value)
MidiUSB.flush();
#elif TEENSY
//do usbMIDI.sendControlChange if using with Teensy
usbMIDI.sendControlChange(cc + i, midiCState[i], midiCh); // cc number, cc value, midi channel
#elif DEBUG
Serial.print("Pot: ");
Serial.print(i);
Serial.print(" ");
Serial.println(midiCState[i]);
//Serial.print(" ");
#endif
potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
midiPState[i] = midiCState[i];
}
}
}
}
/////////////////////////////////////////////
// if using with ATmega32U4 (micro, pro micro, leonardo...)
#ifdef ATMEGA32U4
// Arduino (pro)micro midi functions MIDIUSB Library
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}
#endifLoading
cd74hc4067
cd74hc4067
Loading
ssd1306
ssd1306
Loading
ssd1306
ssd1306
Loading
ili9341-cap-touch
ili9341-cap-touch
Loading
cd74hc4067
cd74hc4067