Voy a poner un codigo que funciona perfecto pero usa otra librería y tiene unas cuantas lineas de codigo y variables para correguir el tema "debounce" tanto en botón como en potenciometro. Esto funciona perfecto, el "problema" es que con la librería controlsurface el codigo es más limpio ya que todo el debounce lo controla directamente con la librería, y me gustaría usarla por eso. Pero no doy con la tecla de cómo leer el estado al CCButtón.
Total, el código que funciona (los comentarios míos están en catalán, si alguién quiere que le traduzca alguna parte que me lo pida y lo haré encantado)
// NOTA CTRL+T ORDENA EL TEXT
// nomes lineas amb * es poden modificar
#include "MIDIUSB.h" // afegim la llibreria
//-----------BUTTONS-----------
// Es fa tot lo del debounce y no delay perque el delay para tot el codi i amb aixo del debounce no. El DEBOUNCE es l efecte que fa que apretis un boto i sembla que l apretis mes
// d'un copo
///***variables configurables***
const int N_BUTTONS = 2; //* Numero de botons
byte buttonPin[N_BUTTONS] = { 5, 6 }; //* Aqui s'ha de posar els pins on conectem els butos
int buttonTimeout = 200; //* El temps que esperarà a tornar a llegir el boto per evitar el debounce en milisegons. Sugestió xxx
byte NN[N_BUTTONS] = { 36, 38 }; //* Asignem quines notes envien els botons en fucnio dels botons que hi ha 36= C 38= D 40= E
///***variables NO configurables***
byte buttonState[N_BUTTONS] = { 0 }; //Aqui anira el estat ACTuAL del boto
byte buttonPrevState[N_BUTTONS] = { 0 }; //Aqui anira el estat PREVI del boto
unsigned long lastDebouncetime[N_BUTTONS] = { 0 }; //Variable per controlar el efecte "debounce" (que apretis un cop i reboti el boto dinant moltes senyals)
unsigned long buttonTimmer[N_BUTTONS] = { 0 }; //Variable per controlar el temps que ha passat
//-----POTENTIOMETERS-----
// Els pots poden tenir FLOATING, que es quan sembla que els toquis una mica quan ningu toca
///***variables configurables***
const int N_POTS = 1; //* Numero de pots
byte potPin[N_POTS] = { A0 }; //* Aqui s'ha de posar els pins on conectem els pots, format { A0, A1, A2 }
int CC[N_POTS] = { 11 }; //* La variable on envia els valors midi, tants com Pots hi hagi format { 11, 12, 13 }
int potThreashold = 20; //* Variable que controla si es un moviment soroll o real. son milisegons. sugerit 50
int potTimeOut = 20; //* Temps que mira del potencimetre en milisegons. son milisegons, sugerit 100
///***variables NO configurables***
int potState[N_POTS] = { 0 }; //Estat actual del pot
int potPrevState[N_POTS] = { 0 }; //Estat previ del pot
int midiState[N_POTS] = { 0 }; //El valor midi del estat del pot
int midiPrevState[N_POTS] = { 0 }; //El valor midi del estat previ del pot
unsigned long lastPotTime[N_POTS] = { 0 }; //Per mirar quan temps ha estar el potenciometre en moviment l ultim cop(no entenc)
unsigned long potTimer[N_POTS] = { 0 }; //Per mirar quan temps ha estar el potenciometre en moviment actual (no entenc)
/// LEDS
///***variables configurables***
const int N_LED = 2; //* Numero de leds
byte ledPin[N_LED] = { 10, 11 }; //* Pins dels leds { 12, 13 }
/// VARIABLES GLOBALS
//-------------------
int MIDI_CH = { 0 }; //* Declarem a quin canal envia la señal midi (0 to 15)
//------
void setup() {
// put your setup code here, to run once:
for (int i = 0; i < N_BUTTONS; i++) {
pinMode(buttonPin[i], INPUT_PULLUP); // declara els pins dels botons
}
for (int i = 0; i < N_LED; i++) {
pinMode(ledPin[i], OUTPUT); // declara els leds
}
}
void loop() {
// put your main code here, to run repeatedly:
buttons();
potentiometers();
}
void buttons() {
for (int i = 0; i < N_BUTTONS; i++) {
buttonState[i] = digitalRead(buttonPin[i]); // LLegeix l estat dels botons
buttonTimmer[i] = millis() - lastDebouncetime[i]; // mirem el temps que ha passat desde l ultim cop que s ha pulsat el boto
if (buttonTimmer[i] > buttonTimeout) { // mirem el tems que ha passat desde l ultim cop que ha rebut señal pel tema debounce
///El que fa el seguent if es mira si el boto ha canviat d estat, si ha canviat fa coses i guarda l estat pel seguent cop poder saber si ha canviat
//si no ha canviat no fa res
if (buttonState[i] != buttonPrevState[i]) { // compara si el estat del botó ha canviat, si no ha canviat no fa res (la placa no envia cap señal)
lastDebouncetime[i] = millis(); // aqui mirem el rellotge com esta quan s apreta el botó
if (buttonState[i] == LOW) { // Mira si el buto está pulsat, LOW es igual a apretat
//hauriem d'apagar tots els leds
for (int a = 0; a < N_LED; a++) {
digitalWrite(ledPin[a], LOW); //apagem tots els led
}
noteOn(MIDI_CH, NN[i], 127); // El que envía si el botó está pulsat
MidiUSB.flush(); // aixo sempre despres de que enviem midi
digitalWrite(ledPin[i], HIGH); // Encenem el led
lastDebouncetime[i] = millis(); // guarda el temps per controlar el debounce
} else {
noteOn(MIDI_CH, NN[i], 0); // El que envía si el botó está "released"
MidiUSB.flush(); // aixo sempre despres de que enviem midi
}
buttonPrevState[i] = buttonState[i]; // Guarda el estat a previous
}
}
}
// Serial.println();
}
void potentiometers() {
for (int i = 0; i < N_POTS; i++) {
potState[i] = analogRead(potPin[i]); // Llegeix el estat del potenciometre
midiState[i] = map(potState[i], 0, 1023, 0, 127); // convertim el valor a midi, format= (variable, valor maxim de la variable, valor minim, valor maxim midi, valor minim)
int potVar = abs(potState[i] - potPrevState[i]); // mirem la diferencia de valors per mirar si es "soroll" o es canvi real. abs converteix els valors negatius en positiu
if (potVar > potThreashold) { // compara si el moviment del pot es superior a la variable per mirar si es soroll, so ho es entra
lastPotTime[i] = millis(); // Si s ha mogut el potenciometre, guardem el temps que ha transcorregut (RESET THE CLOCK)
}
potTimer[i] = millis() - lastPotTime[i]; // Controla quan temps ha passat desde que s ha mogut el pot
if (potTimer[i] < potTimeOut) {
if (midiState[i] != midiPrevState[i]) { // Mirem si l estat d algun potencimetre ha canviat, si ha canviat mostrem
controlChange(MIDI_CH, CC[i], midiState[i]); // el que enviem a la funcio del midi
MidiUSB.flush(); // aixo sempre despres de que enviem midi
midiPrevState[i] = midiState[i]; // guardem el estat del pot midi com a stat previo
}
potPrevState[i] = potState[i]; // guardem el estat del pot com a stat previo (no entenc perque posem la variabke anterior amb el midi)
}
}
}
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = { 0x09, 0x90 | channel, pitch, velocity }; // es lo midi que s envia amb els botons al ordinador
MidiUSB.sendMIDI(noteOn);
}
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t noteOn = { 0x09, 0x90 | channel, control, value }; // es lo midi que s envia amb el potenciometre al ordinador
MidiUSB.sendMIDI(noteOn);
}
Y este es un codigo con "control surface" que también funciona, pero tiene debounce o yo hago algo mal porque cuando aprieto el botón manda decenas de mensajes midi, no hace un On/Off cómo me gustaría:
#include <Control_Surface.h> // Include the Control Surface library
// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;
CCPotentiometer pot(A0, CHANNEL_3); // Potenciómetro conectado al pin analógico A0
//CCPotentiometer pot1(A1, CHANNEL_4); // Potenciómetro conectado al pin analógico A1
const int N_BUTTONS=2; //numero de botons
CCButton Buttons[] = {
{ 0, { 20, CHANNEL_1 } }, /// Buto 1 (pin, valor, canal)
{ 1, { 20, CHANNEL_1 } }, /// Buto 2 (pin, valor, canal)
// { 2, { 20, CHANNEL_1 } }, /// Buto 3 (pin, valor, canal)
// { 3, { 20, CHANNEL_1 } }, /// Buto 4 (pin, valor, canal)
// { 4, { 20, CHANNEL_1 } }, /// Buto 5 (pin, valor, canal)
// { 5, { 20, CHANNEL_1 } }, /// Buto 6 (pin, valor, canal)
// { 6, { 20, CHANNEL_1 } }, /// Buto 7 (pin, valor, canal)
// { 7, { 20, CHANNEL_1 } }, /// Buto 8 (pin, valor, canal)
};
/// LEDS
///***variables configurables***
const int N_LED = 2; //* Numero de leds
byte ledPin[N_LED] = { 10, 11 }; //* Pins dels leds { 12, 13 }
void setup() {
Control_Surface.begin(); // Initialize Control Surface
for (int i = 0; i < N_LED; i++) {
pinMode(ledPin[i], OUTPUT); // declara els leds
}
}
void loop() {
Control_Surface.loop(); // Update the Control Surface
buttons();
delay(20);
}
void buttons(){
byte buttonState[N_BUTTONS] = { 0 };
for (int i = 0; i < N_BUTTONS; i++) {
buttonState[i] = digitalRead(Buttons[i]); // LLegeix l estat dels botons
if (buttonState[i] == LOW) { // Mira si el buto está pulsat, LOW es igual a apretat
//hauriem d'apagar tots els leds
for (int a = 0; a < N_LED; a++) {
digitalWrite(ledPin[a], LOW); //apagem tots els led
}
midi.sendNoteOn(NN[i], 127);
digitalWrite(ledPin[i], HIGH); // Encenem el led
midi.sendNoteOn(NN[i], 0);
}
}
En fin, por si alguien me guia un poco...