-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
possibility of motorized faders #5
Comments
Yes, but it requires specialized timing, and complicated control systems. That's why I didn't include it with the library (yet). |
It would be great! I think it's very good what you've written so far .. |
I am writing a code to incorporate the motorized faders and a bridge of meters powered by the Arduino PWM outputs. I have modified a code written in 2012 by Cody Hazelwood and updated in 2016 by Guerau Pasola and Adrian Salvador. But the original code only controlled one fader. Your library seems very good to me and I would like to use it for the rest of the controls, but I have not been here for a long time and I do not know how to do it. Thank you. #include <CapacitiveSensor.h> // Biblioteca para la sensibilidad táctil del fader
#include <MIDI.h> // Biblioteca para recibir mensajes MIDI
MIDI_CREATE_DEFAULT_INSTANCE();
#define PitchBend 0xE0 // Byte de estado para control de faders
#define AfterTouchChannel 0xD0 // Byte de estado para control de medidores
#define N 4 // Especifica aquí el numero de faders (max.8)
// Asignación de Pins en Arduino (MEGA)
const int motorUp[] = {23, 25, 27, 29, 31, 33, 35, 37}; // Controla H-Bridge para hacer que el motor ascienda
const int motorDown[] = {22, 24, 26, 28, 30, 32, 34, 36}; // Controla H-Bridge para hacer que el motor descienda
const int meterPin [] = {2, 3, 4, 5, 6, 7, 8, 9}; // pines PWM que se van a utilizar para los medidores
// Entradas
const int fader[] = {0, 1, 2, 3, 4, 5, 6, 7}; // Pin de entrada analogica del fader relativo a GND
const int touchSend = 10; // Pin de envio para circuito de detección de capacitancia
const int touchReceive = 11; // Pin de recepción para circuito de detección de capacitancia
// Variables
double faderMax[N]; // Valor leído por la posición máxima del fader (0-1023)
double faderMin[N]; // Valor leído por la posición mínima del fader (0-1023)
double posicion[N];
int faderChannel[N]; // Canal MIDI del fader (desde 1-8)
int returnValue[N];
int meterChannel = 0 ; // Canal MIDI del medidor
int valueAT = 0; // Valor de lectura desde DAW
int valueMeter = 0; // Valor de salida para PWM
bool touched = false;
bool positionUpdated[N];
CapacitiveSensor touchLine = CapacitiveSensor(touchSend, touchReceive);
void setup() {
MIDI.begin(MIDI_CHANNEL_OMNI); // Recibe mensajes en todos los canales MIDI
// Serial.begin(115200); // habilitar esta linea para testear a traves de Hairless MIDI
for (int i = 0; i < N; i++) {
pinMode (motorUp[i], OUTPUT);
pinMode (motorDown[i], OUTPUT);
faderMax[i] = 0 ;
faderMin[i] = 0 ;
posicion[i] = 0 ;
faderChannel[i] = (i+1);
positionUpdated[i] = false ;
analogWrite (meterPin[i], valueMeter); // Puesta a cero de medidores
}
calibrateFader();
}
void loop() {
for (int i = 0; i < N; i++) {
/* Si hay un mensaje MIDI en espera, y corresponde al actualmente seleccionado
fader, y es un mensaje PitchBend (usado para controlar el fader), luego convierte
el valor PitchBend y actualizar la posición actual del fader. */
if (MIDI.read() && MIDI.getChannel() == faderChannel[i] && MIDI.getType() == PitchBend ) {
/* Mapeo bit a bit para tomar dos valores de 7 bits para PitchBend y convertir a
un solo valor de 14 bits. Luego lo convierte en valor entre 0 y 1023
para controlar el fader */
int value = (((MIDI.getData2() << 7) + MIDI.getData1()) * 0.0625);
updateFader(value, i);
}
checkTouch(i); //Comprueba si el fader está siendo tocado
if (!positionUpdated[i]) { //Si se ha tocado el fader, necesita actualizar la posición en el DAW
updateFaderMidi(i);
positionUpdated[i] = true;
}
if (MIDI.read() && MIDI.getType() == AfterTouchChannel && ((MIDI.getData1() & 0x70) >> 4) == i) {
// meterChannel = (MIDI.getData1() & 0x70) >> 4;
valueAT = MIDI.getData1() & 0x0F; // Extrae el valor necesario del mensaje MIDI
valueMeter = map(valueAT, 0, 13, 0, 190); // Transformar los valores recibidos por el DAW para la salida PWM
analogWrite (meterPin[i], valueMeter); // Emite el valor por PWM hacia el filtro RC.
}
}
}
void checkTouch(int i) { // Comprueba el sensor capacitivo,
// el valor 700 es arbitrario y puede ser cambiado
// |||
if (!touched && touchLine.capacitiveSensor(30) >= 700) {
touched = true; // Si se ha tocado ..
// Envia mensaje Touch on al DAW
Serial.write(0x90);
Serial.write(0x67 + faderChannel[i]);
Serial.write(0x7f);
}
else if (touched && touchLine.capacitiveSensor(30) < 700) {
touched = false; // Si se ha dejado de tocar ..
// Envia mensaje Touch Off al DAW
Serial.write(0x90);
Serial.write(0x67 + faderChannel[i]);
Serial.write((byte) 0x00);
}
if (touched) { //
positionUpdated[i] = false;
}
}
void updateFaderMidi(int i) { // Envia posicion del fader al DAW
int volumen = faderPosition(i);
byte channelData = 0xE0 + (faderChannel[i] - 1);
// MIDI Message:
Serial.write(channelData); // E(PitchBend) Channel (0-9)
Serial.write(volumen & 0x7F); // Bits de datos menos significativos
Serial.write((volumen >> 7) & 0x7F); // Bits de datos más significativos
}
// Muever el fader a una posición específica entre 0-1023 si aún no está allí
void updateFader(int valuepos ,int i ) { // Envia posicion del DAW al fader
posicion[i] = valuepos;
if (posicion[i] < analogRead(fader[i]) - 10 && posicion[i] > faderMin[i] && !touched) {
digitalWrite(motorDown[i], HIGH);
while (posicion[i] < analogRead(fader[i]) - 10 && !touched) {}; // Bucles hasta que el motor se mueve
digitalWrite(motorDown[i], LOW);
}
else if (posicion[i] > analogRead(fader[i]) + 10 && posicion[i] < faderMax[i] && !touched) {
digitalWrite(motorUp[i], HIGH);
while (posicion[i] > analogRead(fader[i]) + 10 && !touched) {}; // Bucles hasta que el motor se mueve
digitalWrite(motorUp[i], LOW);
}
}
int faderPosition(int i) {
posicion[i] = analogRead(fader[i]);
if (posicion[i] <= faderMin[i]) {
returnValue[i] = 0;
}
else if (posicion[i] >= faderMax[i]) {
returnValue[i] = 16383;
}
else {
returnValue[i] = ((float)(posicion[i] - faderMin[i]) / (faderMax[i] - faderMin[i])) * 16383;
}
return returnValue[i];
}
void calibrateFader() {
for (int i = 0; i < N; i++) {
// Enviar faders a la parte superior y leer las posiciónes máximas
digitalWrite(motorUp[i], HIGH);
delay(300);
digitalWrite(motorUp[i], LOW);
faderMax[i] = analogRead(fader[i]) - 5;
}
for (int i = 0; i < N; i++) {
// Enviar faders a la parte inferior y leer las posiciónes mínimas
digitalWrite(motorDown[i], HIGH);
delay(300);
digitalWrite(motorDown[i], LOW);
faderMin[i] = analogRead(fader[i]) + 5;
}
} |
Looking good! Like I said in the other issue, I currently have exams, so there's not much I can do until early July. I have tried the same (or similar) motorized fader sketch, but I wasn't happy with the result, for multiple reasons:
I've done some research into PID controllers, and that seems promising. However, I can't get them 100% smooth. The PWM power isn't linear at all, making it many times harder (especially at high frequencies, you don't want them in the audible spectrum, especially near audio equipent). You also need to call the control functions at a regular interval, which requires the use of timer interrupts. All tuning depends on the hardware it is used on, so it's really hard to come up with a "one-size-fits-all" solution to distribute with this library. If I manage to do it, I'll probably only support Teensy boards, because it is a pain to support the right PWM and Timer settings on AVR, while Teensy comes with easily portable function for all of this. I don't expect anyone to run such a "heavy" project on an AVR anyways. I also have some updates (almost) ready for the MIDI Controller library, improving filtering of the analog inputs. If you're having problems with that, keep an eye out for version 3.1.0 somewhere in the first week of July. |
I agree with you. |
Any progress with the faders ??? |
I posted my code here: https://github.com/tttapa/MotorFader I'm not satisfied with the results, and it's a lot of work to integrate it with the Control Surface library, and I don't have the time. I also have to add a Kalman filter and a better way to tune the PID controller dynamically. |
For future reference: |
Could it include the reading of messages (MIDI_Input "PitchBend") to manipulate motorized faders?
The text was updated successfully, but these errors were encountered: