Geschrieben am

MIDI Controller Finale – Schaltplan & Arduino Sketch

Und wir sind fertig! 🙂 Unten findet Ihr einen vereinfachten Schaltplan. Der entspricht nicht einhundertprozentig meinem Controller, sollte euch aber besser helfen, euren Controller zu bauen und erweitern. Und natürlich gibt es auch den fertigen Programmcode für den Arduino.


Hardware: Schaltplan für alle Fälle

Hier ist der Schaltplan als einfache Verdrahtungs-Skizze:

schaltplan-gmd-midi-controller-korr

 

Wie bereits erwähnt, entspricht der Plan nicht genau meinem Controller sondern einer reduzierten, aber dafür übersichtlichen Version. Interessant ist sicher wie die Multiplexer weiterverdrahtet werden. Beachtet aber unbedingt, dass eine Menge Bauteile fehlen.

Checkt unbedingt zu allen Bauteilen nochmals das jeweilige Video-Tutorial!

Software: Der fertige Arduino Programmcode

Besonders viel hat sich am Code nicht mehr verändert. Ich speichere inzwischen alle Controller-Nummern (auch die für die Taster und Sensoren) in einem Array. So lassen sich die Nummern bequem gleich am Anfang des Sketches ändern. Beachtet bitte, dass dieser Code aber nicht direkt zum Schaltplan passt. Der Schaltplan ist universell – dieser Code ist 1:1 aus meinem Controller.

Neuheiten

Es sind zwei neue Befehle für Variablen hinzugekommen, die ich euch in der nächsten, neuen Serie ausführlich erkläre. Hier die Kurzfassung:

byte

Erzeugt eine 1 Byte große Variable (während „int“ eine 2 Byte große erzeugt).

boolean

Erzeugt eine Variable, die nur die beiden Zustände „wahr“ (true) oder „falsch“ (false) enthalten kann. In meinem Fall „Taste gedrückt“ oder „Taste nicht gedrückt“.

Arduino MIDI-Controller Programmcode V1.0

Hier gibt’s den Arduino Sketch zum Download:
GMD-MIDI-Controller-Sketch-v1.0 Download

Der Download enthält außerdem eine zweite Version, die ich zur Hilfe etwas ausführlicher kommentiert hab.

// *********************************************************
// Sketch für Götz Müller-Dürholts MIDI-Controller
// V 1.0
// Komplettes Anfänger-Video-Tutorial: https://goo.gl/I1ipZj
// Mehr Infos und Projekte: http://www.goetzmd.de
// *********************************************************

byte controlChange = 176;
byte controllerNummer[] = {20,21,22,23,24,25,26,27,28,29,30,71,72,73,74,75,76};

int potiWert[16];
byte controllerWert[16];
byte controllerWertAlt[16];

byte taste[] = {LOW, LOW};
byte tasteAlt[] = {LOW, LOW};
boolean tasteGedrueckt[] = {false, false};
byte tastePin[] = {8, 10};
byte tasteLEDPin[] = {9, 11};

byte bit1 = 0;
byte bit2 = 0;
byte bit3 = 0;


void setup() {
 //Select-Pins 4051s
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 pinMode(4, OUTPUT);
 
 //Sensoren
 pinMode(5, OUTPUT); //Trigger 1
 pinMode(6, INPUT); //Echo 1
 pinMode(7, OUTPUT); //Trigger 2
 pinMode(12, INPUT); //Echo 2
 
 pinMode(8, INPUT); // Taster 1
 pinMode(9, OUTPUT); // Taster 1 LED
 pinMode(10, INPUT); // Taster 2
 pinMode(11, OUTPUT);// Taster 2 LED
 
 Serial.begin(31250);
}

void loop() {
 // Schleife fragt alle Potis an den 4051 Multiplexern ab
 for (byte i = 0; i <= 7; i++) {
 bit1 = bitRead(i,0);
 bit2 = bitRead(i,1);
 bit3 = bitRead(i,2);
 
 digitalWrite(2, bit1);
 digitalWrite(3, bit2);
 digitalWrite(4, bit3);
 
 potisAbfragen(i,A0);
 potisAbfragen(i+8,A1);
 }

 sensorAbfragen(5, 6, controllerNummer[14]);
 sensorAbfragen(7, 12, controllerNummer[16]);

 tasteAbfragen(0 ,controllerNummer[12]);
 tasteAbfragen(1 ,controllerNummer[13]);
}


void potisAbfragen(byte zaehler, int analogPin) {
 potiWert[zaehler] = 0.2 * potiWert[zaehler] + 0.8 * analogRead(analogPin);
 controllerWert[zaehler] = map(potiWert[zaehler],0,1023,0,127);
 if (controllerWert[zaehler] != controllerWertAlt[zaehler]) {
 sendeMIDI(controlChange, controllerNummer[zaehler], controllerWert[zaehler]);
 controllerWertAlt[zaehler] = controllerWert[zaehler];
 }
}

void sensorAbfragen(byte triggerPin, byte echoPin, byte ctrlNummer) {
 digitalWrite(triggerPin, LOW);
 delayMicroseconds(2);
 digitalWrite(triggerPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(triggerPin, LOW);
 
 long sensorWert = pulseIn(echoPin, HIGH);

 if ( (sensorWert <= 2000) && (sensorWert >= 200)) {
 byte sensorMIDI = map(sensorWert,2000,200,0,127);
 sendeMIDI(controlChange, ctrlNummer, sensorMIDI);
 }
}

void tasteAbfragen(byte x, byte ctrlNummer) {
 taste[x] = digitalRead(tastePin[x]);
 
 if (taste[x] == HIGH && tasteAlt[x] == LOW) {
 if(tasteGedrueckt[x] == false){
 sendeMIDI(controlChange, ctrlNummer, 127);
 digitalWrite(tasteLEDPin[x], HIGH);
 tasteGedrueckt[x] = true;
 }
 else {
 sendeMIDI(controlChange, ctrlNummer, 0);
 digitalWrite(tasteLEDPin[x], LOW);
 tasteGedrueckt[x] = false;
 }
 }
 tasteAlt[x] = taste[x];
}

void sendeMIDI(byte statusByte, byte dataByte1, byte dataByte2) {
 Serial.write(statusByte);
 Serial.write(dataByte1);
 Serial.write(dataByte2);
}

 

31 Gedanken zu „MIDI Controller Finale – Schaltplan & Arduino Sketch

  1. Sieht ja heiss aus . Nu möchten wir aber auch gerne Live Action sehen.
    Also anschliessen und abjammen büdde 😉

    1. Ja, das müsste ich eigentlich noch mal machen… 🙂

      1. Hallo Götz,
        Auch ich hab mich von deiner Idee anstecken lassen und habe eine alte Singer Blechdose zum Midi-Controller (5 Drehpotis) erwachen lassen. Es hat mir sehr viel Spaß gemacht, obwohl ich vorher noch nie einen Lötkolben in der Hand hatte.Jedenfalls funktioniert alles prima! ich Danke die für deine inspirierenden Videos!
        mach weiter so!! Liebe Grüße aus Berlin, Daniel

        1. Danke, Daniel, das freut mich!
          Gruß zurück aus Köln
          Götz

  2. Hi Götz,

    ich habe mir jetzt alle Videos angesehen (vielen Dank!) und bin drauf und dran mir einen eigenen Midi Controller als Lichtpult zu bauen. Der würde allerdings ziemlich groß werden und ich habe deshalb noch folgende beiden Fragen:
    1. Ich habe in deinen Videos immer gesehen, dass die maximale Sketchgröße um die 32.000 Byte beträgt. Was passiert wenn ich über diesen Wert drüber komme? Brauche ich einen anderen Controller?
    2. Ich müsste wahrscheinlich so um die 48-64 Taster verwenden. Kann ich mehr Taster verwenden als der Arduino digitale Eingänge hat? Bzw. kann ich Taster einfach auf Analoge Eingänge hängen? Die Frage wurde so schon ein paarmal in den Kommentaren gestellt, ich habe aber leider keine Antwort darauf gefunden.

    Danke schonmal 🙂
    Und danke nochmal für die super Videos.

    Gruß Didda

    1. 1. Es gibt natürlich eine Tricks, den Sketch und die Variablen möglichst klein zu halten. Das einfachste ist sicher ein anderer Arduino wie z.B. ein Mega oder ein Teensy.
      2. Du kannst an den analogen Pins auch einen digitalRead machen, kein Problem. Der klassische Weg für mehr digitale Inputs ist übrigens ein Shift-Register: https://www.arduino.cc/en/Tutorial/ShiftIn

      1. Super, danke. Das schaue ich mir mal an.

  3. Hallo Götz,
    vielen Dank für die unglaubliche Arbeit, die Du geleistet hast.
    Ich habe 2 Fragen zur Stromversorgung.
    1: Wie hast Du den Arduino NANO (über Welche Pins und mit was für einen Netzteil versorgt).
    2: Hast Du die Bauteil, IC… direkt an dem Netzteil angeschlossen oder sie vom Arduino gespeist, wenn über Arduino, welechen Ausgang nimmt man bei NANO

    1. Danke, Asho!
      1) Der MIDI-Adapter wird ja über USB mit Strom versorgt. Davon habe ich mir VCC und GND abgezweigt und beim Nano an VIN (Pin 30) und GND (Pin 29) angelötet. Ein Netzteil braucht das ganze nicht, da die 500 mA von USB nicht überschritten werden.
      2) Von USB kommen ja bereits die 5 Volt. Kannst du entweder dort direkt abgreifen oder am Nano aus Pin 27 (5V) nehmen.

  4. Hi Götz,
    ich wollte an dieser Stelle einfach mal DANKE sagen. Deine Serie hatte mich dazu inspiriert einen MIDI Controller für den iPad Animoog zu bauen. Es hat ungefär ein Jahr gedauert, und manchmal hätte ich am liebsten alles in die Ecke geschmissen! Aber jetzt bin ich doch froh durchgehalten zu haben 🙂
    Hier übrigens der Controller im Einsatz:
    https://youtu.be/YIU-j6NJekA

    1. VIELEN DANK! 🙂
      Sieht super professionell aus dein Controller! Großartig!

  5. Hi Götz, vielen Dank für die Antwort. Ich werde später mein Controller nicht über USB treiben sondern mit einem externen Netzteit Midi-Out Buchse. Daher wie mache ich das.Also eigentlich die gleichen Fragen vom letzten Beitrag butte. Ich will soger ein Teensy benutzen.
    Gruß Asho.

  6. Nachtrag. Ich meine Netzteil und Midi Out Buchse.

  7. Hallo Götz,

    erst einmal ein dickes Lob für dieses Projekt!
    Mehr als 4 Stunden habe ich gerne Deinen Erläuterungen gelauscht und bin begeistert gewesen. Damit habe ich wirklich den Einstig in das Arduino programmieren hin bekommen! Danke dafür.

    Nun habe ich mich hinreissen lassen und versuche eine AfV Schaltung auf Basis dessen was ich bei dem MIDI Controller Projekt gesehen habe, mit meinem Yamaha 01V umzusetzen.
    Da dabei es mit einem einfachen Fader auf / Fader zu nicht getan ist -die Signale sollen sich ineinander überblenden- habe ich mit einer for sSchleife gespielt.
    Nach einigem hin und her bin ich auch in der Lage bei ankommendem GPI (Schliesser via Relais) einen Fader hochfahren zu lassen und dann dort zu halten (Controller Wert 101 = 0dB amFader), diesen dann zu halten und beim abfallen des GPI (Relais öffnet) wieder auf Fader -128dB zurück zu bringen.

    Nur wenn ich dann die die Schaltung um zumindest einen 2. Kanal erweitere, komme ich so nicht mehr weiter. Die Fade beeinflussen sich gegenseitig und es schaint auch, dass die for Schleife die Schaltung blockiert.

    Eine Idee wie man so etwas besser lösen könnte?

    hier mal mein Versuch;

    if (trigger1 == HIGH) {

    while (controllerWert <= 101) {
    for (controllerWert = 0; controllerWert = 0) {
    for (controllerWert = 101; controllerWert >= 0; controllerWert -=1){
    Serial.write(controlChange);
    Serial.write(controllerNummer1);
    Serial.write(controllerWert);
    delay(75);
    }
    }
    }
    }

    Beste Grüße,
    Christian

    1. Hallo Christian,
      vielen Dank für Dein Lob. Ähm… was ist denn eine AfV-Schaltung? Ich verstehe dein Vorhaben noch nicht so ganz. Ich vermute du möchtest per Tastendruck eine Fader-Fahrt auslösen, die dann langsam das Signal ein- oder ausblendet, richtig?

      Dann ist dein Problem bei einem zweiten Fader klar, denn mit der for-Schleife (in der du ja dann quasi feststeckst, bis diese abgelaufen ist) und dem delay blockierst du dir den Arduino. Hier würde ich mal versuchen mit „millis“ zu arbeiten und die for-Schleife wegzulassen. Immer wenn eine bestimmte Zeit vergangen ist (millis) erhöht/senkt der Arduino den Wert deines Faders. So kannst du gleichzeitig und/oder zeitversetzt Fader-Fahrten starten.

  8. Hi Götz,
    leider muss ich nochmal nerven. Verzeih mir.
    Ich habe mich gefragt, warum Du den Nano nicht über seinen eigenen USB (Min) Stecker mit Strom versorgt hast. Liegt es daran, dass Du einen anderen USB Stecker haben wolltest ? Theoretisch hätte doch der Ministecker sowohl für Midi als auch für die Stromversorgung gereicht oder ??
    Gruß, Asho

    1. Über USB wird lediglich der USB-MIDI-Adapter angeschlossen. Warum sollte ich dann von dort wieder einen USB-Stecker anlöten um den Nano anzuschließen, wenn ich doch nur die Stromversorgung auch direkt mit zwei Drähten anlöten kann?! Denk dran: der Nano macht kein MIDI über USB. USB wird beim Nano nur für die Programmierung gebraucht, danach nicht mehr.

      1. Danke. Alles klar.

  9. Hallo Götz,

    vielen Dank für Deine Antwort. Du hast das Prinzip derSchaltung genau richtig getroffen :-)!
    AfV steht für Audio follows Video. Letzlich bekomme ich aus einem Bildmischer GPIs die mit Signalen die OnAir gehen assoziiert sind und ich möchte diese via Relais auswerten, um dann über diesen „Taster“ den Fader in einer bestimmten Zeit auffahren zu lassen und entsprechend zu schliessen, wenn der nächste Kanal sein „Rotlicht“ sieht.
    Ich werde das mit den „millis“ am WE mal ausprobieren.

  10. hallo götz,
    erstmal vielen dank für die ganzen videos und die mühe die du dir damit immer machst!

    ich habe mir ein controller gebaut der 25 potis hat die über drei ic´s laufen, der 25. poti hängt extra am A3
    nach zwei wochen bauphase und einer weiteren woche fehlersuche scheint das gerät an sich jetz zu funktionieren und ich habe nur noch probleme mit dem programm
    da ich davon garkeine ahnung habe, habe ich dein sketch einfach kopiert und so umgeschrieben wie ich dachte das er für mein controller passt, dem scheint aber nicht so zu sein 😉
    deshalb wollte ich mal fragen ob du oder jemand anderes der das hier liest und ahnung davon hat, da kurz drüber gucken und mir helfen kann!?
    ich wäre euch sehr dankbar!!

    // Byte für ControlChange-Befehl auf MIDI Kanal 1
    byte controlChange = 176;
    // Meine Controllernummern
    byte controllerNummer[] = {21,22,23,24,25,26,27,28,29,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117};

    // Array für 3 achtfach Multiplexer = 24 Werte
    int potiWert[24];
    byte controllerWert[24];
    byte controllerWertAlt[24];

    // 3 Bits für den Zähler der Multiplexer
    byte bit1 = 0;
    byte bit2 = 0;
    byte bit3 = 0;

    void setup() {
    //Select-Pins 4051s
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);

    Serial.begin(9600);
    }

    void loop() {
    // Schleife fragt alle Potis an den 4051 Multiplexern ab
    for (byte i = 0; i <= 7; i++) {
    bit1 = bitRead(i,0);
    bit2 = bitRead(i,1);
    bit3 = bitRead(i,2);

    digitalWrite(2, bit1);
    digitalWrite(3, bit2);
    digitalWrite(4, bit3);

    potisAbfragen(i,A0);
    potisAbfragen(i+8,A1);
    potisAbfragen(i+16,A2);
    potisAbfragen(i,A3);
    }
    }

    void potisAbfragen(byte zaehler, int analogPin) {
    //Formel um ein Poti abzufragen und die Messwerte zu glätten
    potiWert[zaehler] = 0.2 * potiWert[zaehler] + 0.8 * analogRead(analogPin);
    controllerWert[zaehler] = map(potiWert[zaehler],0,1023,0,127);
    if (controllerWert[zaehler] != controllerWertAlt[zaehler]) {
    sendeMIDI(controlChange, controllerNummer[zaehler], controllerWert[zaehler]);
    controllerWertAlt[zaehler] = controllerWert[zaehler];
    }
    }

    // Funktion zum Verschicken eines MIDI-Befehls
    void sendeMIDI(byte statusByte, byte dataByte1, byte dataByte2) {
    Serial.write(statusByte);
    Serial.write(dataByte1);
    Serial.write(dataByte2);
    }

  11. Hallo Götz!
    Vielen Dank für die hervorragenden Tutorials! Habe viel gelernt und möchte gern einen Controller bauen mit 4 Potis und 16 Buttons!

    Habe mir in Fritzing ein Layout erstellt und wollte fragen, ob es von der Schaltung her korrekt ist.
    Fälschlicher Weise habe ich in der Skizze 4052s statt den 4051 und nur zwei von 16 Schaltern angeschlossen.
    Aber würde es im Prinzip so funktionieren?
    Link zur Schlatung: http://imgur.com/a/4E3bX

    mit freundlichen Grüßen
    Florian

    1. Hallo Florian,
      ich hab jetzt nicht jeden einzelnen Pin überprüft, sieht aber soweit okay aus. Allerdings verwendest du Multiplexer für die Taster. Hierfür würde man allerdings eher Shift-In-Register verwenden. Such mal nach „arduino shiftIn“ bei Google.
      Viel Erfolg
      Götz

  12. Hi Götz,
    ich würde gerne mit einen taster drei stufen schalten.

    einmal drücken sendeMIDI(controlChange, ctrlNummer, 127);
    zweitesmal drücken sendeMIDI(controlChange, ctrlNummer, 64);
    drittesmal drücken sendeMIDI(controlChange, ctrlNummer, 0);

    wie deklariere ich dann die Ctrlnummer?
    es ist leider so wenn ich die buttons wie in deinen Finalcode als schalter definiere habe habe ich ja nur 2 Zustände
    bei manchen vst instrumenten oder amps sind aber 3 stufen schaltbar

    Grüße Reiner

  13. Hallo.
    Ich finde deinen Blog genial. und bin gerade dabei zwei Midi Controller zu bauen.

    Einer mit 20 Potis und 9 Tastern und einen mit 3 Ultraschallsensoren.

    Bei den Ultraschallsensoren stehe ich vor einem Problem da ich das Programmieren noch nicht ganz verstehe.

    Könntest du mir eventuell weiterhelfen?

    Ich habe ein Arduino Uno,
    über die DigitalPins 8,10,12 laufen die 3 Echo Signale
    über die Pins 9,11,13 die 3 Trigger Signale.

    Die Sensoren sollen erst ab ca. 40cm ansprechen.

    Diese möchte ich dann auswerten um im Cubase zu verwenden.

    Es soll auch noch ein USB-2-Midi Converter eingebaut werden, so wie du es auch gezeigt hast.

    Danke schonmal und Frohe Ostern!

    Gruss Mikey

    1. Danke Mickey,

      schließ einfach mal einen Sensor an, frage ihn ab und gib die Werte über SerialPrint aus. Wie das geht findest du ja in der Folge zu den Sensoren. Mit der Hand probierst du aus, welche Bereich für dich bequem ist. Minimaler und maximaler Abstand. Im Serial-Monitor siehst du dazu die beiden Werte. In meinem Sketch ist es 200 und 2000.

      Deine beiden Werte trägst du dort statt 200 und 2000 ein:
      if ( (sensorWert < = 2000) && (sensorWert >= 200)) {
      byte sensorMIDI = map(sensorWert,2000,200,0,127);

      Und wenn du das Abfragen in eine Funktion auslagerst wie in meinem Sketch, kannst du auch easy im Loop einen dritten Sensor abfragen:
      sensorAbfragen(8, 9, controllerNummer[1]);
      sensorAbfragen(10, 11, controllerNummer[2]);
      sensorAbfragen(12, 13, controllerNummer[3]);

      Die Controller-Nummern kommen aus dem array – oder du trägst sie einfach direkt ein.

      Viel Erfolg
      Götz

  14. Hallo,
    deine Videos sind sehr informativ und hilfreich. Ich bin mitlerweile ein Fan von deinen Tutorials. Ich habe im Studium paar Semester Programmierung gehabt. Hätte der Professor diese Thematik halbwegs so gut erklärt wie Du, hätte ich bestimmt mehr Spaß dabei gehabt.
    Deine Tutorials haben mich sehr inspiriert selber einen DAW-Controller zu bauen. Das das Thema Motorfader nicht so einfach ist, hast Du ja schon beim Löt-Frühstück erzählt. Ich wollte das bei meinem Controller aber noch weiter treiben und unter den jeweiligen Spuren ein kleines Display verbauen, welches den Spurnamen anzeigt, hinterleuchtet mit der eingestellten Spurfarbe. Kannst Du mir sagen ob das überhaupt möglich ist diese Informationen von Cubase abzurufen und in einem Sketch einzubinden?
    Wirst Du noch ein Video zum Thema Motorfader machen? Mich würde sehr interessieren wie das in Kombination mit einer DAW funktioniert.

    Viele Grüße
    Stefan

    1. Hallo Stefan,
      vielen Dank für Dein Lob und Deine Begeisterung! 🙂
      Ja, das geht, allerdings müsste man sich dafür das Mackie HUI-Protokoll vornehmen. Das kann immerhin 4 Zeichen vom Kanalnamen übertragen. Ist aber nicht ganz einfach…
      Ich würde das natürlich schon gerne machen, plane das aber im Moment nicht, weil es unendlich viel aufwändiger ist, als z.B. unser Monotron Hack… Da fehlt mir dann einfach die Zeit. Aber man soll ja niemals nie sagen… 😉
      VG
      Götz

  15. Hallo Götz,
    sehr geiles Tutorial, mit das Beste was je gesehen hab!

    ich würde gern die Werte einiger MIDI Controller Werte (0-127) auf einem LCD anzeigen lassen.
    Wie kann ich diese abfragen und auf das LCD printen?

    VG
    Daniel

    1. Danke Daniel!
      In der aktuellen Serie zum Monotron Hack wird das erklärt. Es ist allerdings unendlich komplizierter die Daten aus deinem Computer raus zu bekommen. Schau dir dazu mal das „Lötfrühstück“ an – hier wird das erklärt!
      VG
      Götz

  16. Hallo Götz,

    respekt vor deiner Arbeit! Deine Videos sind wirklich das Beste, was ich bisher gesehen habe.
    Ich würde gern die Controller Werte an einem Display anzeigen lassen 80.127). Wie greife ich denn die Werte ab?

    Viele Grüße
    Daniel

    1. Danke dir! Siehe die Antwort davor!

Kommentar verfassen