DIY MIDI USB CONTROLEUR Project Arduino Uno Besoin d'aide
- 76 réponses
- 10 participants
- 13 191 vues
- 10 followers
Mat Martigan
Mon projet est de réaliser un contrôleur MIDI
uniquement dans le but de commander des paramètres de mon logiciel mao et autres Vst
6 Potentiometres ( 10kohm )
8 boutons
je peux programmer via le logiciel Arduino ,la carte est bien reconnu par le port USB ,et je peux également flasher le contrôleur USB ATMEGA16U2 via le logiciel FLIP afin de pouvoir transmettre les Données Midi via L'usb manipulation que se fait sans problème
https://dartmobo.com/midi-over-usb/
Ci joint voici les programmes ainsi que les projets dont je me suis inspiré
https://www.hackster.io/etiennedesportes/ableton-live-midi-controller-9182b3
Les boutons fonctionnent le mappage se fait correctement dans mon logiciel Mao
Mais les potentiomètres ne fonctionnent pas
Leur course est différente
Leur mappage en midi est impossible car selon la position des potentiomètres la diode TX clignote en permanence
Même si je réussie a mapper un ou 2 potentiomètres le mappage des autres est impossible
Car des que je touche un autre potentiomètre la diode TX clignote donc le mappage est aléatoire
J'ai également testé avant avec ce programme
https://www.instructables.com/id/Easy-3-Pot-Potentiometer-Arduino-Uno-Effects-Midi-/
et le logiciel Hailess Midi et loopBe1
Les 3 potentiomètres (2k2ohm) fonctionnaient
Mon schéma de câblage
Est ce que Le problème vient du code ou bien est ce que mon câblage au niveau des potentiomètres n'est pas bon ?
Sur D'autres projets similaires comme celui ci
https://www.instructables.com/id/Custom-Arduino-MIDI-Controller/
il est conseillé de mettre des condensateurs de 100nf entre le masse et la commande ainsi qu'entre le + et la masse de chaque potentiomètres dans le but d’éliminer les bruits
je vous remercie par avance pour votre aide
Le code principale
const int buttonPin = 2; // the number of the Button pin
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int buttonPin6 = 7;
const int buttonPin7 = 8;
const int buttonPin8 = 9;
// the number of the pushbutton pin
const int ledPin = 11; // the number of the LED pin
const int ledPin2 = 12;
const int ledPin3 = 13;
const int ledPin4 = 14;
const int ledPin5 = 15;
const int ledPin6 = 16;
const int ledPin7 = 17;
const int ledPin8 = 18;
// variables will change:
boolean currentState = LOW;//stroage for current button state
boolean lastState = LOW;//storage for last button state
boolean currentState2 = LOW;
boolean lastState2 = LOW;
boolean currentState3 = LOW;
boolean lastState3 = LOW;
boolean currentState4 = LOW;
boolean lastState4 = LOW;
boolean currentState5 = LOW;
boolean lastState5 = LOW;
boolean currentState6 = LOW;
boolean lastState6 = LOW;
boolean currentState7 = LOW;
boolean lastState7 = LOW;
boolean currentState8 = LOW;
boolean lastState8 = LOW;
void setup() {
Serial.begin(31250); // default midi speed rate
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin2, OUTPUT);
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(ledPin3, OUTPUT);
pinMode(buttonPin3,INPUT_PULLUP);
pinMode(ledPin4, OUTPUT);
pinMode(buttonPin4, INPUT_PULLUP);
pinMode(ledPin5, OUTPUT);
pinMode(buttonPin5, INPUT_PULLUP);
pinMode(ledPin6, OUTPUT);
pinMode(buttonPin6, INPUT_PULLUP);
pinMode(ledPin7, OUTPUT);
pinMode(buttonPin7,INPUT_PULLUP);
pinMode(ledPin8, OUTPUT);
pinMode(buttonPin8, INPUT_PULLUP);
MIDI.begin();
}
static int iAn0Val, iAn1Val, iAn2Val, iAn3Val, iAn4Val, iAn5Val;
void loop(){
// read the state of the pushbutton value:
currentState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (currentState == LOW && lastState == HIGH) {
digitalWrite(ledPin,HIGH);
MIDI.sendNoteOff(42,0,1);
// turn LED off
}
else if (currentState == HIGH && lastState == LOW) {
digitalWrite(ledPin, LOW);
MIDI.sendNoteOn(42,127,1);
// turn LED on
delay(20);
MIDI.sendNoteOff(42,0,1);
// turn LED off
}
lastState = currentState;
currentState2 = digitalRead(buttonPin2);
if (currentState2 == LOW && lastState2 == HIGH) {
digitalWrite(ledPin2,HIGH);
MIDI.sendNoteOff(39,0,1);
}
else if (currentState2 == HIGH && lastState2 == LOW) {
digitalWrite(ledPin2, LOW);
MIDI.sendNoteOn(39,127,1);
delay(20);
MIDI.sendNoteOff(39,0,1);
}
lastState2 = currentState2;
currentState3 = digitalRead(buttonPin3);
if (currentState3 == LOW && lastState3 == HIGH) {
digitalWrite(ledPin3,HIGH);
MIDI.sendNoteOff(40,0,1);
}
else if (currentState3 == HIGH && lastState3 == LOW) {
digitalWrite(ledPin3, LOW);
MIDI.sendNoteOn(40,127,1);
delay(20);
MIDI.sendNoteOff(40,0,1);
}
lastState3 = currentState3;
currentState4 = digitalRead(buttonPin4);
if (currentState4 == LOW && lastState4 == HIGH) {
digitalWrite(ledPin4,HIGH);
MIDI.sendNoteOff(41,0,1);
}
else if (currentState4 == HIGH && lastState4 == LOW) {
digitalWrite(ledPin4, LOW);
MIDI.sendNoteOn(41,127,1);
delay(20);
MIDI.sendNoteOff(41,0,1);
}
lastState4 = currentState4;
currentState5 = digitalRead(buttonPin5);
if (currentState5 == LOW && lastState5 == HIGH) {
digitalWrite(ledPin5,HIGH);
MIDI.sendNoteOff(38,0,1);
}
else if (currentState5 == HIGH && lastState5 == LOW) {
digitalWrite(ledPin5, LOW);
MIDI.sendNoteOn(38,127,1);
delay(20);
MIDI.sendNoteOff(38,0,1);
}
lastState5 = currentState5;
currentState6 = digitalRead(buttonPin6);
if (currentState6 == LOW && lastState6 == HIGH) {
digitalWrite(ledPin6,HIGH);
MIDI.sendNoteOff(43,0,1);
}
else if (currentState6 == HIGH && lastState6 == LOW) {
digitalWrite(ledPin6, LOW);
MIDI.sendNoteOn(43,127,1);
delay(20);
MIDI.sendNoteOff(43,0,1);
}
lastState6 = currentState6;
currentState7 = digitalRead(buttonPin7);
if (currentState7 == LOW && lastState7 == HIGH) {
digitalWrite(ledPin7,HIGH);
MIDI.sendNoteOff(37,0,1);
}
else if (currentState7 == HIGH && lastState7 == LOW) {
digitalWrite(ledPin7, LOW);
MIDI.sendNoteOn(37,127,1);
delay(20);
MIDI.sendNoteOff(37,0,1);
}
lastState7 = currentState7;
currentState8 = digitalRead(buttonPin8);
if (currentState8 == LOW && lastState8 == HIGH) {
digitalWrite(ledPin8,HIGH);
MIDI.sendNoteOff(44,0,1);
}
else if (currentState8 == HIGH && lastState8 == LOW) {
digitalWrite(ledPin8, LOW);
MIDI.sendNoteOn(44,127,1);
delay(20);
MIDI.sendNoteOff(44,0,1);
}
lastState8 = currentState8;
static int iAn0ValPrev;
iAn0ValPrev = iAn0Val; // previous value
iAn0Val = analogRead(A0)/8; // Divide by 8 to get range of 0-127 for midi
analogPinMidiTX(1,iAn0Val,iAn0ValPrev); //TX value
static int iAn1ValPrev;
iAn1ValPrev = iAn1Val;
iAn1Val = analogRead(A1)/8;
analogPinMidiTX(2,iAn1Val,iAn1ValPrev);
static int iAn2ValPrev;
iAn2ValPrev = iAn2Val;
iAn2Val = analogRead(A2)/8;
analogPinMidiTX(3,iAn2Val,iAn2ValPrev);
static int iAn3ValPrev;
iAn3ValPrev = iAn3Val;
iAn3Val = analogRead(A3)/8;
analogPinMidiTX(4,iAn3Val,iAn3ValPrev);
static int iAn4ValPrev;
iAn4ValPrev = iAn4Val;
iAn4Val = analogRead(A4)/8;
analogPinMidiTX(5,iAn4Val,iAn4ValPrev);
static int iAn5ValPrev;
iAn5ValPrev = iAn5Val;
iAn5Val = analogRead(A5)/8;
analogPinMidiTX(6,iAn5Val,iAn5ValPrev);
}
void analogPinMidiTX(int iChan, int iVal, int iValPrev)
{
// TX Value only if it has changed
if(iValPrev != iVal)
{
MidiTX(176,iChan,iVal); // 176 = CC command, 1 = Which Control, val = value read from Potentionmeter
}
}
void MidiTX(unsigned char MESSAGE, unsigned char CONTROL, unsigned char VALUE) //Valeur en Midi Command
{
Serial.write(MESSAGE);
Serial.write(CONTROL);
Serial.write(VALUE);
}
La bibliothèque Midi.h
/*
Basic I/O MIDI tutorial
by Franky
28/07/2009
*/
#define LED 13 // LED pin on Arduino board
void setup() {
pinMode(LED, OUTPUT);
MIDI.begin(4); // Launch MIDI with default options
// input channel is set to 4
}
void loop() {
if (MIDI.read()) {
digitalWrite(LED,HIGH); // Blink the LED
MIDI.sendNoteOn(42,127,1); // Send a Note (pitch 42, velo 127 on channel 1)
delay(1000); // Wait for a second
MIDI.sendNoteOff(42,0,1); // Stop the note
digitalWrite(LED,LOW);
}
}
// This function will be automatically called when a NoteOn is received.
// It must be a void-returning function with the correct parameters,
// see documentation here:
// http://arduinomidilib.sourceforge.net/class_m_i_d_i___class.html
void HandleNoteOn(byte channel, byte pitch, byte velocity) {
// Do whatever you want when you receive a Note On.
if (velocity == 0) {
// This acts like a NoteOff.
}
/*
MIDI Input tutorial
by Franky
28/07/2009
NOTE: for easier MIDI input reading,
take a look a the Callbacks example.
*/
#define LED 13 // LED pin on Arduino board
void BlinkLed(byte num) { // Basic blink function
for (byte i=0;i<num;i++) {
digitalWrite(LED,HIGH);
delay(50);
digitalWrite(LED,LOW);
delay(50);
}
}
void setup() {
pinMode(LED, OUTPUT);
MIDI.begin(); // Launch MIDI with default options
// (input channel is default set to 1)
}
void loop() {
if (MIDI.read()) { // Is there a MIDI message incoming ?
switch(MIDI.getType()) { // Get the type of the message we caught
case ProgramChange: // If it is a Program Change
BlinkLed(MIDI.getData1()); // Blink the LED a number of times
// correponding to the program number
// (0 to 127, it can last a while..)
break;
// See the online reference for other message types
default:
break;
}
}
}
Anonyme
Moi le truc qui me paraît le plus louche c'est ça:
Des lors que j’affecte un potentiomètre a une fonction en midi (quand j'y arrive) la variation est très rapide
comme si je passai directement de 0 a 127 en tournant le potentiomètre
Hormi l'aspect "bruit" sur tes entrées qui est une chose à considérer, il y a d'autres problèmes dans le code.
christian_r
- en mode catch, le bouton tourne dans le vide jusqu'à atteindre la valeur pré-réglée sur le patch de son, et devient alors actif, donc sans saut de valeur mais avec une zone inactive.
- en mode jump, le bouton impose sa valeur dès qu'on le tourne, quel que soit le pré -réglage sur le synthé, donc produit un saut de valeur mais agit aussitôt.
- en mode relatif (peu utilisé) sa position s'ajoute au préréglage (mais en butée ça posera problème).
Christian
[ Dernière édition du message le 01/02/2019 à 20:53:13 ]
Beatless
Citation de christian
- en mode catch, le bouton tourne dans le vide jusqu'à atteindre la valeur pré-réglée sur le patch de son, et devient alors actif, donc sans saut de valeur mais avec une zone inactive.
C'est intéressant ça.
Tu peux donner des détails, un exemple de code?
S'il n'y a pas de solution, c'est qu'il n'y a pas de problème.
static volatile
Citation de Mat :
Citation :Il faut définir une tolérance, un écart
C'est la methode qui est utilsé par King C dans son programme ?
C'est ce qu'on a appelle un Hystersis il me semble
Ça n'est pas ce que King C fait, mais tu peux effectivement utiliser un seuil de variation en dessous duquel tu considères que le potentiomètre ne bouge pas.
EDIT: au post 9, oui c'est bien ce qu'il fait.
Ceci dit, en shiftant la valeur de l'ADC de 3 bits vers la droite (ou en divisant par 8, same difference), on ignore de toute manière les 3 bits faibles, la comparaison ne sert donc a rien (la perte de précision après division est supérieure au seuil de la comparaison).
Autrement dit, le delta entre deux mesures de l'ADC doit être supérieur a 8 pour que la valeur après division change.
Resistance is not futile... it's voltage divided by current
[ Dernière édition du message le 01/02/2019 à 23:12:40 ]
Anonyme
Autrement dit, le delta entre deux mesures de l'ADC doit être supérieur a 8 pour que la valeur après division change.
Et que se passe t-il si les valeurs entrantes fluctuent entre, disons, 7 et 9.... ?
C'est pour ça que je parle d'effet de seuil.
[ Dernière édition du message le 02/02/2019 à 00:29:54 ]
Rémy M. (chimimic)
Et que se passe t-il si les valeurs entrantes fluctuent entre, disons, 7 et 9.... ?
C'est pour ça que je parle d'effet de seuil.
+1
En effet, la simple division par 8 (SHR 3) ne suffit pas pour s'affranchir de ce petit soucis, qui à l'époque m'avait bien embêté moi aussi. Limiter les variations avec un filtrage passe-bas (par moyennage) améliore la situation, mais ne la résout pas totalement. Il faut jouer plus fin
Formateur en techniques sonores ; électronicien ; auteur @ sonelec-musique.com
[ Dernière édition du message le 02/02/2019 à 07:56:23 ]
static volatile
pot_0 = analogRead (A0); // lecture de l'entrée analogique en 10bits
if ( abs( pot_0 - old_pot_0) > 3) { // si la valeur absolue de la différence est supérieure à 3
old_pot_0 = pot_0;
pot_0 = pot_0 >> 3; // la valeur est encodée en 7 bits ( >> 3 équivaut à une division par 2^3 = 8 )
midiOut.sendControlChange( cc0 , pot_0, midi_Ch );
}
La comparaison ne sert a rien, vu que le seuil avant division est plus faible que la résolution après division, et ne garantit pas qu'on ne va pas envoyer deux fois de suite un CC identique.
Resistance is not futile... it's voltage divided by current
[ Dernière édition du message le 02/02/2019 à 08:42:30 ]
static volatile
- d'abord on s'assure de la validité des données entrantes (traitement contre le bruit)
- puis on imagine comment ne pas surcharger le bus en n'envoyant que les CC strictement nécessaires en prenant en considération la résolution d'un CC.
Resistance is not futile... it's voltage divided by current
Rémy M. (chimimic)
Formateur en techniques sonores ; électronicien ; auteur @ sonelec-musique.com
Anonyme
Ah, mais tout ce que j'ai dit c'est que dans l'extrait suivant (post 9):
pot_0 = analogRead (A0); // lecture de l'entrée analogique en 10bits
if ( abs( pot_0 - old_pot_0) > 3) { // si la valeur absolue de la différence est supérieure à 3
old_pot_0 = pot_0;
pot_0 = pot_0 >> 3; // la valeur est encodée en 7 bits ( >> 3 équivaut à une division par 2^3 = 8 )
midiOut.sendControlChange( cc0 , pot_0, midi_Ch );
}
La comparaison ne sert a rien, vu que le seuil avant division est plus faible que la résolution après division, et ne garantit pas qu'on ne va pas envoyer deux fois de suite un CC identique.
Bah oui et non. Oui il peut envoyer deux fois la même valeur quand le potentiomètre est en mouvement mais pas au repos.
Mais tu as raison, il faut mieux bien séparer les étapes.
Bon moi j'ai l'impression qu'on est loin de résoudre tout les soucis de MM, là il faudrait tester les choses en vrai pour les déboguer correctement...
[ Dernière édition du message le 02/02/2019 à 13:34:25 ]
- < Liste des sujets
- Charte