Hola a toda la comunidad. Estoy realizando, junto con un colega, un controlador MIDI DIY
El proyecto está casi completo, consta de 12 potenciómetros análogos de 100k conectados a un Multiplexor Analógico 16 canales basado en 74HC4067. Realizamos las debidas conexiones de los potenciómetros al Multiplexor de 16 canales analogicos y de este último a la placa de Arduino UNO, estas últimas conexiones de manera desmontable para la verificación del proyecto y poder saber si la comunicación entre el controlador y la PC es correcta. Utilizamos los programas LoopMIDI y Hairless MIDIserial creando un puerto virtual y hacer la comunicación serial.
Probamos el controlador en Ableton Live 10 y los potes son reconocidos con los respectivos valores del protocolo MIDI (0 a 127), nuestro único inconveniente es que cuando los potenciómetros están enviando información los valores de los mismos empiezan a oscilar por sí solos de -1 a 1 (Ejemplo: Channel 1 = 020, oscila de manera continua a 019, 020, 021, 020, 018, 020, etc.). Después de investigar de varias fuentes, concluimos dos problemas de Hardware posibles:
A) Los potenciómetros son de baja calidad y son sensibles a posibles ruidos eléctricos.
B) La gran cantidad de cables conectados dificulta o genera interferencias en la energía del Arduino.
Comprobamos las conexiones y sus aislamientos entre sí y no parece haber problema en ello.
Una posible solución a esto es modificar el código con un filtro pasa bajos utilizando la técnica de media móvil, este método no fue probado aún. Tanto el código utilizado como el modificado fue realizado por el Chat GPT y cargado desde el programa arduino.
Otra solución, que me recomendo un profesor, es que pruebe primero incluyendo en el codigo un alibreria del MUX 74HC4067 y verificar que el problema no es del Multiplexor y luego incluir libreria <MIDI.h> en el codigo
Quería consultarles que le parece este método, si existe alguno que realmente funciones o recomendar librerias del integrado para incluir al codigo y si nos puedsn brindar algún consejo para que el controlador sea funcional y sin fallas ya que es nuestro primer proyecto con leguaje de programacion Arduino o protocolo MIDI.
A continuación les dejo los links de descarga de los programas que utilizamos, el código original que venimos usando, el codigo con filtro pasa bajos incluido:
Hairless MIDI: https://forum.arduino.cc/t/hairless-midi-download/1136528
LoopMIDI: https://www.tobias-erichsen.de/software/loopmidi.html
Codigo Original:
const int s0Pin = 8; // Pin S0 del multiplexor conectado al pin digital 8 del Arduino
const int s1Pin = 9; // Pin S1 del multiplexor conectado al pin digital 9 del Arduino
const int s2Pin = 10; // Pin S2 del multiplexor conectado al pin digital 10 del Arduino
const int s3Pin = 11; // Pin S3 del multiplexor conectado al pin digital 11 del Arduino
const int outPin = A0; // Pin de salida del multiplexor conectado al pin analógico A0 del Arduino
const int numChannels = 12; // Número de canales/potenciómetros
int potValues[numChannels]; // Array para almacenar los valores de los potenciómetros
void setup() {
pinMode(s0Pin, OUTPUT);
pinMode(s1Pin, OUTPUT);
pinMode(s2Pin, OUTPUT);
pinMode(s3Pin, OUTPUT);
// Inicializar los valores de los potenciómetros
for (int i = 0; i < numChannels; ++i) {
potValues[i] = 0;
}
// Configurar la comunicación serial para MIDI
Serial.begin(115200);
}
void loop() {
// Leer el valor de cada potenciómetro
for (int channel = 0; channel < numChannels; ++channel) {
selectChannel(channel);
int value = 127 - (analogRead(outPin) / 8); // Escalar el valor analógico de 0-1023 a 127-0 (inverso)
// Verificar si el valor del potenciómetro ha cambiado
if (value != potValues[channel]) {
potValues[channel] = value;
// Enviar mensaje MIDI con el valor del potenciómetro
sendMidiControlChange(channel, value);
}
delay(10); // Pequeña pausa para evitar envíos demasiado rápidos
}
}
void selectChannel(int channel) {
digitalWrite(s0Pin, bitRead(channel, 0));
digitalWrite(s1Pin, bitRead(channel, 1));
digitalWrite(s2Pin, bitRead(channel, 2));
digitalWrite(s3Pin, bitRead(channel, 3));
}
void sendMidiControlChange(int channel, int value) {
// Enviar mensaje MIDI
Serial.write(0xB0 | channel); // Status byte para Control Change
Serial.write(channel); // Canal MIDI
Serial.write(value); // Valor del Control Change
}
Codigo con Filtro Pasa bajos:
#include <MIDI.h>
const int s0Pin = 8; // Pin S0 del multiplexor conectado al pin digital 8 del Arduino
const int s1Pin = 9; // Pin S1 del multiplexor conectado al pin digital 9 del Arduino
const int s2Pin = 10; // Pin S2 del multiplexor conectado al pin digital 10 del Arduino
const int s3Pin = 11; // Pin S3 del multiplexor conectado al pin digital 11 del Arduino
const int outPin = A0; // Pin de salida del multiplexor conectado al pin analógico A0 del Arduino
const int numChannels = 12; // Número de canales/potenciómetros
const int filterSamples = 5; // Número de muestras para el filtro de media móvil
int filterBuffer[numChannels][filterSamples]; // Buffer para almacenar las muestras filtradas
int filterIndex = 0; // Índice actual del buffer de filtrado
MIDI_CREATE_DEFAULT_INSTANCE();
int potValues[numChannels]; // Array para almacenar los valores de los potenciómetros
void selectChannel(int channel) {
digitalWrite(s0Pin, bitRead(channel, 0));
digitalWrite(s1Pin, bitRead(channel, 1));
digitalWrite(s2Pin, bitRead(channel, 2));
digitalWrite(s3Pin, bitRead(channel, 3));
}
void setup() {
Serial.begin(31250);
pinMode(s0Pin, OUTPUT);
pinMode(s1Pin, OUTPUT);
pinMode(s2Pin, OUTPUT);
pinMode(s3Pin, OUTPUT);
MIDI.begin(MIDI_CHANNEL_OMNI); // Iniciar la comunicación MIDI
// Inicializar los valores de los potenciómetros
for (int i = 0; i < numChannels; ++i) {
potValues[i] = 0;
for (int j = 0; j < filterSamples; ++j) {
filterBuffer[i][j] = 0;
}
}
}
void loop() {
// Leer el valor de cada potenciómetro
for (int channel = 0; channel < numChannels; ++channel) {
selectChannel(channel);
int rawValue = analogRead(outPin);
// Aplicar el filtro de media móvil
filterBuffer[channel][filterIndex] = rawValue;
int filteredValue = 0;
for (int i = 0; i < filterSamples; ++i) {
filteredValue += filterBuffer[channel][i];
}
filteredValue /= filterSamples;
// Escalar el valor analógico de 0-1023 a 0-127
int scaledValue = map(filteredValue, 0, 1023, 0, 127);
// Verificar si el valor del potenciómetro ha cambiado
if (scaledValue != potValues[channel]) {
potValues[channel] = scaledValue;
// Enviar mensaje MIDI con el valor del potenciómetro
MIDI.sendControlChange(channel, scaledValue, MIDI_CHANNEL_OMNI);
// Imprimir el valor del potenciómetro por el puerto serie
Serial.print("Pot ");
Serial.print(channel);
Serial.print(": ");
Serial.println(scaledValue);
}
}
Desde ya, muchas gracias