M.I.D.I. Kontroller

Der M.I.D.I. Kontroller war ein Projekt am Sommeranfang 2017. Mit einem M.I.D.I. Signal werden Musiksignale auf dem Computer gesteuert. Dafür gibt es ein genormtes Protokoll. Die Logik übernimmt bei diesem Projekt ein Arduino Nano, der auch das M.I.D.I. Protokoll sprechen kann.

Das Signal wird über die Serielle Schnittstelle gesendet an einen M.I.D.I auf USB Konverter, da der Kontroller Universell an USB-Geräten einsetzbar sein soll. Mit diesem Kontroller können bis zu 20 Control-Change und 20 Key-On Signale gesendet werden. Dies geschieht über eine Channelauswahl. Eine aktive LED zeigt an, in welchem Channel man sich befindet.

Probleme

In diesem Projekt gab es eigentlich zwei Probleme. Zum einem war die Logik Platine zu groß. Dafür konnte die Platine aber Problemlos etwas in der Länge gekürzt werden. Zum anderen ist im Platinenlayout ein falscher Footprint für den Button, weshalb die Button mit kleinen Drähten neu verdrahtet werden mussten.

Bestellliste

Beschreibung Artikelnummer Anzahl Stückpreis Gesamtpreis
Hardware
Arduino Uno — — — 0 5,49 € – €
Arduino Nano — — — 1 3,98 € 3,98 €
USB-MIDI — — — 1 5,80 € 5,80 €
Bauteile
Schiebepoti (10k) RS60112-LIN10K 1 2,70 € 2,70 €
Schiebepoti Motor (10k) RS60N11M9-LIN5K 0 15,80 € – €
Drehpoti (10k) PO4M-LIN 10K 3 1,90 € 5,70 €
Taster TASTER 1032.1 9 1,20 € 10,80 €
LED (3mm) LED 3MM GE 5 0,09 € 0,45 €
Multiplexer 74HC 4051 0 0,37 € – €
Schieberegister SMD 4021 0 0,32 € – €
Distanzhülsen DI 5MM 4 0,09 € 0,36 €
Gehäuse
Kunststoffgehäuse TEKO 103 1 7,70 € 7,70 €
Schiebepoti Kappe KNOPF 4X1,2SW 1 0,52 € 0,52 €
Drehpoti Kappe KNOPF 14M-4 SW 3 1,35 € 4,05 €
Drehpoti Abdeckkappe DECKEL 14M SW 3 0,25 € 0,75 €
Versand
Reichelt — — — 1 5,00 € 5,00 €
Ebay Arduno Uno 0 1,50 € – €
Gesamtpreis
47,81 €

 

Schaltpläne

Gehäuse

 

Arduino Sketch

/*
 * @NAME: MIDI-Controller Arduino Nano Software
 * @AUTHOR: <admin@gurkengewuerz.de> Gurkengewuerz
 * @REVIEW: 08.06.2017
 * @VCS: https://git.ita15b.de/schuetrumpf/midi_controller
 */
 
// http://computermusicresource.com/MIDI.Commands.html
boolean debug = false;
 
byte midi_cmd_key_on = 144;
byte midi_cmd_key_off = 128;
byte midi_cmd_controll = 176;
 
byte potis[] = {
  16,
  17,
  18,
  19
};
// http://www.wavosaur.com/download/midi-note-hex.php
byte midiNote[] = {
  0x0C,
  0x0D,
  0x0E,
  0x0F,
  0x10,
  0x11,
  0x12,
  0x13
}; // 8 notes
byte lastPotiStates[] = {
  0,
  0,
  0,
  0
};
 
byte channel_count = 5;
byte channel_leds[] = {
  8,
  9,
  10,
  11,
  12
};
byte channel_current = 1;
 
// Keypad
const byte ROWS = 3;
const byte COLS = 3;
 
int col[] = {
  3,
  15,
  2
}; // Input
int row[] = {
  6,
  4,
  5
}; // Output
 
int last_row = -1;
int last_cols = -1;
unsigned long last = millis();
 
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
 
  // LEDS
  for (byte i = 0; i < channel_count; ++i) {
    pinMode(channel_leds[i], OUTPUT);
  }
 
  for (int i = 0; i < ROWS; i++) {
    pinMode(row[i], OUTPUT);
  }
 
  for (int i = 0; i < COLS; i++) {
    pinMode(col[i], INPUT_PULLUP);
  }
 
  // If Debug Mode: enter USB Mode
  if (debug) {
    Serial.begin(9600);
  } else {
    // MIDI baud rate 31250
    Serial.begin(31250);
  }
}
 
void loop() {
  for (int i = 0; i < channel_count; ++i) {
    if (i == (channel_current - 1)) {
      digitalWrite(channel_leds[i], HIGH);
    } else {
      digitalWrite(channel_leds[i], LOW);
    }
  }
 
  // Potis abfragen
  // TODO: Potis Testen
  for (byte i = 0; i < (sizeof(potis) / sizeof(byte)); ++i) {
    int val = getDebouncedAnalog(potis[i]);
    int perc = map(val, 0, 1023, 0, 127);
    // debugMsg("Poti (" + String(i) + "): " + String(potis[i]));
    if (!(lastPotiStates[i] > perc - 3 && lastPotiStates[i] < perc + 3)) {
      debugMsg("Poti => " + String(perc));
      sendMIDI(midi_cmd_controll + channel_current, midiNote[i], perc);
      lastPotiStates[i] = perc;
    }
  }
 
  for (int i = 0; i < ROWS; i++) {
    digitalWrite(row[0], HIGH);
    digitalWrite(row[1], HIGH);
    digitalWrite(row[2], HIGH);
    digitalWrite(row[i], LOW);
    for (int j = 0; j < COLS; j++) {
      int col_scan = digitalRead(col[j]);
      if (col_scan == LOW) {
        keypress(i, j);
        delay(100);
      }
    }
  }
}
 
void keypress(int i, int j) {
  String val = "x";
 
  debugMsg(String(i) + " => " + String(j));
 
  if (last_row == i && last_cols == j && millis() - last < 150) {
    val = "r";
    debugMsg("MILLIS: " + String(last) + " / " + String(millis()) + " = " + String(millis() - last) + "ms");
    last = millis();
  } else if (i == 0 && j == 0) {
    val = "1";
    channel_current = 1;
  } else if (i == 0 && j == 1) {
    val = "2";
    channel_current = 2;
  } else if (i == 0 && j == 2) {
    val = "3";
    channel_current = 3;
  } else if (i == 1 && j == 0) {
    val = "4";
    channel_current = 4;
  } else if (i == 1 && j == 1) {
    val = "5";
    channel_current = 5;
  } else if (i == 1 && j == 2) {
    val = "6";
    sendMIDI(midi_cmd_key_on + channel_current, midiNote[4], 0x45);
  } else if (i == 2 && j == 0) {
    val = "7";
    sendMIDI(midi_cmd_key_on + channel_current, midiNote[5], 0x45);
  } else if (i == 2 && j == 1) {
    val = "8";
    sendMIDI(midi_cmd_key_on + channel_current, midiNote[6], 0x45);
  } else if (i == 2 && j == 2) {
    val = "9";
    sendMIDI(midi_cmd_key_on + channel_current, midiNote[7], 0x45);
  }
 
  debugMsg(val);
 
  last = millis();
  last_row = i;
  last_cols = j;
}
 
// http://forum.arduino.cc/index.php?topic=190305.msg1408310#msg1408310
int getDebouncedAnalog(const byte pin) {
  static int previousReading = 0; // static is better than a global
  int newReading = analogRead(pin);
  if ((newReading - 1 > previousReading) || (newReading + 1 < previousReading)) {
    previousReading = newReading;
  }
 
  return previousReading;
}
 
// https://www.arduino.cc/en/Tutorial/Midi
// cmd - pitch - velocity
void sendMIDI(byte statusByte, byte dataByte1, byte dataByte2) {
  Serial.write(statusByte);
  Serial.write(dataByte1);
  Serial.write(dataByte2);
}
 
void debugMsg(String msg) {
  if (debug) {
    Serial.println(msg);
  }
}

 

Demo

M.I.D.I. Kontroller Demo

Schreiben Sie einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.