Featured image of post Arduino Programm für das Pedal

Arduino Programm für das Pedal

Ein Pedal wird digital Teil 2

Einleitung

Bei meinem letzten Beitrag über den Umbau meines Orgelpedals habe ich versprochen, noch einmal das Programm für den Arduino zu teilen. Diesem Versprechen möchte ich nun endlich nachkommen. Den Code habe ich auf Github veröffentlicht unter https://github.com/klangpost/Orgelpedal/blob/main/code.ino

Im folgenden möchte ich diesen kurz erklären. Zum Anfang aber erst einmal die Grundüberlegung. Das Orgelpedal soll an einem Computer als MIDI Gerät erkannt werden und beim Drücken/Loslassen einer Taste ein entsprechendes MIDI Event senden. Da ich einen Arduino DUE verwende ist eine Tastenmatrix nicht notwendig. Die Reedschalter sind sofern eine Taste nicht gedrückt wird geschlossen. Die Reedschalter sind verbunden mit den Pin’s 22-52 und GND.

Variablen

Zuerst werden die Notwendigen Variablen erstellt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <MIDIUSB.h>
 
//Variablen für Pedaltasten
// Array mit Pinnummern
const int pedalPins[] = {
  22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
  42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
  52
};
 
// Midi Noten
const int midiNote[] = {
  36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
  46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
  56, 57, 58, 59, 60, 61, 62, 63, 64, 65
};
 
#define NUM_PEDALS (sizeof(pedalPins) / sizeof(int))  // Anzahl der Pedale berechnen
 
// Anzahl der Tasten ermitteln
bool pedalState[NUM_PEDALS];

#include <MIDIUSB.h> fügt die MIDIUSB Bibliothek hinzu, diese ermöglichst die Midi Funktionen über USB mit sehr wenig Aufwand. In der Konstante pedalPINS werden die Pinnummern eingetragen, an denen die Reedschalter angeschlossen sind und in midiNOTES befinden sich die dazugehörigen Midi Keycodes. Der tiefste Keycode mit der Nummer 36 entspricht dem Kontra C.

NUM_PEDALS enthält die Anzahl der Pedaltasten. Diese wird anhand der Arraygröße ermittelt. Bedeutet die Anzahl der verwendeten Pins aus pedalPINS ergibt die Anzahl der Tasten. Aus dieser Information wird auch noch das Array pedalState erstellt. Dieses beinhaltet die Information für jede Taste, ob diese nun gerade gedrückt ist, oder nicht.

Midi Funktionen

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**** Funktionen für MIDI ***************************************************/
void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}
 
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}
 
void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}
 
bool MidiButton(int pin, byte midisig, bool tasteAlt) {      //Button-Pin, Noten-Nummer
  bool taste = digitalRead(pin);
  if(tasteAlt == LOW && taste == HIGH){
    
    Serial.print("NoteON MidiNote: ");
    Serial.print(midisig);
    
    noteOn(0, midisig, 64);  
    MidiUSB.flush();
    tasteAlt = taste;
    delay(100);
    return tasteAlt;
  }
 
  if(tasteAlt == HIGH && taste == LOW){
    Serial.print("NoteOFF MidiNote: ");
    Serial.print(midisig);
    noteOff(0, midisig, 64);  
    MidiUSB.flush();
    tasteAlt = taste;
    delay(100);
    return tasteAlt;
  }
}

Um nicht den Rahmen zu sprengen erkläre ich hier nur die Funktion MidiButton. An diese Funktion wird der PIN der Taste, der Midi Keycode und der letzte bekannte Zustand übergeben. Dann wird der aktuelle Zustand des PINS gelesen und mit dem letzten bekannten verglichen. Ist dieser identisch, dann hat sich nicht verändert. Sollte er abweichen, dann wurde die gedrückte Taste losgelassen, oder die nicht gedrückte Taste gedrückt. Entsprechend dem neuen Zustand wird über die Funktion noteOff oder noteOn ein Midisignal gesendet und eine Debug Information ausgegeben.

Setup / Loop

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
void setup() {
  Serial.begin(9600); // Öffnet die serielle Schnittstelle bei 9600 Bit/s:
  Serial.print("Setup beginnt");
  Serial.println();
 
  // Setze alle Pedalpins als Eingang mit internen Pull-up-Widerständen (passe dies nach Bedarf an)
  for (int i = 0; i < NUM_PEDALS; i++) {
    pinMode(pedalPins[i], INPUT_PULLUP);
    pedalState[i] = HIGH;
  }
  
  Serial.print("Setup abgeschlossen");
  Serial.println();
}
 
void loop() {
  //Pedaltasten
  for (int i = 0; i < NUM_PEDALS; i++) {
    bool currentState = pedalState[i];
    pedalState[i] = MidiButton(pedalPins[i], midiNote[i], currentState);
  }
}

In der Funktion Setup wird zuerst eine serielle Schnittstelle geöffnet mit 9600 Bit/s. Danach werden alle angegebenen Pins als Eingang mit einem Pull-up-Widerstand gesetzt. Die loop Funktion ist sehr kompakt und geht nur endlos alle Pins durch um den Zustand zu ermitteln. Am Ende angekommen, geht es wieder von vorne los… Es gibt kein Ende 🙂

Dies sollte die einfachste Variante sein. Natürlich kann man dieses Projekt auch mit einem kleineren Arduino realisieren. Dann wäre aber eine Tastenmatrix aufzubauen mit Dioden. In meinem Fall war mir dies aber zu viel Arbeit. Eine 8×8 Matrix wäre z.B in der Lage mit nur 16 Pins 64 Tasten abzufragen. Bei einem Pedal mit 30 Tasten wäre auch eine 5×6 Matrix sinnvoll.

Zusätzlich wird in diesem Basisprogramm keine Taste entprellt. Das recht Hohe Delay von 100 Millisekunden ist recht hoch und da fällt in meinem Aufbau kein Prellen auf. Wer eine möglichst geringe Latenz möchte, der sollte die Tasten zusätzlich entprellen.

Vielleicht ist das Programm für den einen oder anderen nützlich. Nutzt es gerne und passt es an eure Bedürfnisse an.

Erstellt mit Hugo
Theme Stack gestaltet von Jimmy