Comments (9)
It would be great! I think it's very good what you've written so far ..
from control-surface.
For future reference:
Motorized faders are now supported, you can find the documentation at https://tttapa.github.io/Pages/Arduino/Control-Theory/Motor-Fader and the code in tttapa/Control-Surface-Motor-Fader.
from control-surface.
Yes, but it requires specialized timing, and complicated control systems. That's why I didn't include it with the library (yet).
from control-surface.
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.
Everything seems to work correctly although not fluid enough as it should. :(
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.
I thought that when you have time maybe you can help me solve this.
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;
}
}
from control-surface.
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:
- The control system is very primitive, it's just "turn the motor all the way on until you reach your target value minus 10". It's not accurate.
- The while loops of the fader movement block the entire system, so it doesn't react to MIDI in or button presses, etc.
- "Smooth" fader curves aren't smooth, because of the terrible control system.
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.
from control-surface.
I agree with you.
The behavior of the system gets worse as new elements are added. Maybe the control of the faders needs a dedicated microcontroller.
We will also talk in a few weeks about the level meters on PWM.
A greeting.
from control-surface.
i was thinking that also if we put the faders on a dedicated controller
here is the design i'm working on for my studio. It is for Cubase.
i the code works really well as a generic controller
would love to get 8 motor faders working from one board so i can program them in banks of 8
from control-surface.
Any progress with the faders ???
from control-surface.
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.
from control-surface.
Related Issues (20)
- Bankable::ManyAddresses::CCAbsoluteEncoder HOT 2
- Time Display does not work.
- Does it's support ESP32-S3/C3 via USB port? HOT 7
- How to use 1 shift button to change bank:
- The sketch compiles, but doesn't work HOT 3
- Arduino UNO R4 support and testing HOT 3
- Arduino Yun HOT 2
- Trying to setVelocity for all notebutton values in mux with piezo device HOT 1
- External app/webpage to change CC and Channel values HOT 1
- Hi, I would like to see the USBMIDI_Interface adapted so that you can specify the fixed cablenumber. This would it make possible to use pipes and filters connecting serial ports with virtual usb ports
- Support for MCP23S17 SPI
- error: 'SelectorPC' does not name a type HOT 2
- Switching presets Roland FP-30X HOT 2
- TYPO IN DOCUMENTATION HOT 1
- Error running on M1 Mac Sonoma with Teensy 4.0 HOT 4
- Arduino Nano 33 BLE Support? HOT 3
- Пример CCIncrementDecrementButtons.ino HOT 10
- Select bank HOT 2
- MIDI-монитор-OLED HOT 3
- Arduino Giga R1 Wifi support HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from control-surface.