So, hier habe ich euch mal den Sketch für den Dreh-Encoder eingehängt:
/*
* Konstruktion eines eigenen Midi-Controllers für Final Cut Pro X
* für einen Arduino Mega
*
* mit 6 großen Dreh-Encodern (keine externen Widerstände nötig, sind im Encoder eingebaut),
* (Anschluss an 2-3, 4-5, 6-7, 8-9, 10-11, 12-13)
* 7 kleinen Dreh-Encodern (externe Pullup-Widerstände 10K nach 5V)
* (Anschluss an 14-15, 16-17, 18-19, 20-21, 22-23, 24-25, 26-27)
* und 40 Tast-Schaltern (externe Pulldown-Widerstände 10K nach GND)
* (Anschluss an 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, 53,
* A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)
*
* Die Eingänge A0 bis A13 werden also gleichfalls als digitale Eingänge genutzt.
* Somit sind bis auf A14 und A15 sämtliche I/O-Möglichkeiten des Mega genutzt
*
* Ausgegeben werden pro Element 3 Bytes an Midi-Werten:
* Als erstes Byte für alle gleich der Wert 176 - Codierung des ControlChange-Befehls für Midi-Kanal 1,
* als zweites Byte die Controller-Nummer (hier von 1 - 52),
* als drittes Byte entweder 0 oder 127.
* Der Sketch liefert die Werte an den Mac - Midi-Treiber "Hairless Midi-Bridge",
* der auf dem Mac die Daten dann weiter an das Programm "Midi-Translator" liefert.
* Dieses übersetzt die Midi-Informationen in Tastaturbefehle für Final Cut Pro X.
*/
// =============== Initialisierung der Werte ===============================
// ------ Für Funktion 1 (Encoder): 13 Dreh-Encoder einrichten --------------------
// Große Dreh-Encoder:
// Ausgänge: A, B, GND und 5V
// Lage: eindeutig beschriftet
// Kleine Dreh-Encoder:
// Ausgänge: A, B und GND
// Lage: Von hinten gesehen, Anschlussfahnen unten: A - rechts, B - links, GND - Mitte
//
// Eingänge am Arduino: Pins 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
int EncoderPinA [] = {2,4,6,8,10,12,14,16,18,20,22,24,26}; // Pins A der Encoder
int EncoderPinB [] = {3,5,7,9,11,13,15,17,19,21,23,25,27}; // Pins B der Encoder
int EncoderPos[] = {0,0,0,0,0,0,0,0,0,0,0,0,0}; // Position der Encoder
int EncoderPinALast[] = {LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW};
int n = LOW;
int ControlChange = 176; // Midi-Kanal 1 Control-Change - Befehl
int ControllerNummer[] = {1,2,3,4,5,6,7,8,9,10,11,12,13}; // 13 Dreh-Encoder mit den Midi-Controller-Nummern 1 - 13
int ControllerWert[] = {0,0,0,0,0,0,0,0,0,0,0,0,0}; // Controller-Werte initialisieren
int ControllerWertAlt[] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
int e = 0; // Zähler für die Encoder
// -------- Für Funktion 2 (Tasten): 39 Taster einrichten ----------------
// 39 einfache Taster, 2-polig: 1. Anschluss direkt an 5V
// 2. Anschluss direkt an Arduino-Digitalpin: 28 - 53 und A1 - A11
// Dieser 2. Anschluss geht über einen 10K Widerstand auch auf GND.
// 39 Taster mit den Midi-Controller-Nummern 14 - 52
int tasterPin[] = {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,53,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13}; // Pin Nummern der Taster
int ControlChangeT = 176; // Midi-Kanal 1 Control-Change - Befehl
int TControlNr[] = {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,41,42,43,44,45,46,47,48,49,50,51,52,53};
int tasterStatus[] = {LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW};
int tasterGedrueckt[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int entprellZeit = 50; // Zeit für Entprellung, anpassen!
unsigned long tasterZeit = 0;
int t = 0; // Zähler für die Taster
// -------------------------------------------------------------
// =========================================================================
void setup() // ========== Setup - Routine ================================
{
// ------ Für Funktion 1 (Encoder) : 13 Dreh-Encoder initialisieren -------------------
pinMode (EncoderPinA[e],INPUT); // Pins A der Encoder als Input setzen
pinMode (EncoderPinB[e],INPUT); // Pins B der Encoder als Input setzen
/*
// ------ Für Funktion 2 (Tasten) vorbereiten ---------------------
pinMode(tasterPin[t], INPUT); // Taster Pin wird als Eingang gesetzt
// ------------------------------------------------------------------------
*/
Serial.begin (9600); // Serielle Ausgabe für Midi vorbereiten
}
// ========================================================================
void loop() // =============== Haupt - Programm =========================
{
DrehEncoder(); // ------ Aufruf von Funktion 1: Dreh-Encoder abfragen ---------
Tasten(); // ------ Aufruf von Funktion 2: Tasten abfragen -------------
}
// ========================================================================
void DrehEncoder() // ======== Funktion 1: 13 Dreh-Encoder abfragen ================
{
for (e=0;e<13;e++)
{
n = digitalRead(EncoderPinA[e]); // Dreh-Encoder abfragen
if ((EncoderPinALast[e] == LOW) && (n == HIGH))
{
if (digitalRead(EncoderPinB[e]) == LOW)
{
EncoderPos[e]--;
ControllerWert[e] = 127;
Serial.write(ControlChange); // Ausgabe des Wertes 176 für Midi-Kanal 1
Serial.write(ControllerNummer[e]); // Controller-Nummer für Drehencoder
Serial.write(ControllerWert[e]); // Letztes Byte des Control-Change-Befehls
}
else
{
EncoderPos[e]++;
ControllerWert[e] = 0; // Ausgabe an Midi-Programm über Hairless Midi-Treiber
Serial.write(ControlChange); // Ausgabe des Wertes 176 für Midi-Kanal
Serial.write(ControllerNummer[e]); // Controller-Nummer für Drehencoder
Serial.write(ControllerWert[e]); // Letztes Byte des Control-Change-Befehls
}
}
EncoderPinALast[e] = n;
}
}
// ==================================================================================
// ========================= Funktion 2: 40 Tasten abfragen =====================================
void Tasten()
{
for (t=0;t<40;t++)
{
tasterStatus[t] = digitalRead(tasterPin[t]); // Lesen der Tasterpins
if (tasterStatus[t] == HIGH) // wenn der Taster gedrückt ist..
{
tasterZeit = millis(); // aktualisiere tasterZeit
tasterGedrueckt[t] = 1; // speichert, dass Taster gedrückt wurde
}
if ((millis() - tasterZeit > entprellZeit) && tasterGedrueckt[t] == 1) // wenn die gewählte Zeit vergangen ist und der Taster gedrückt war.
{
Serial.write (ControlChangeT);
Serial.write (TControlNr[t]);
Serial.write (0);
tasterGedrueckt[t] = 0; // setzt gedrückten Taster zurück
}
}
}
// ==================================================================================
Das ist der gesamte Code, für mehrere Dreh-Encoder und eine Menge von Schaltern.
Wer nur einen Encoder braucht, kann natürlich erst mal die Funktion "Tasten" komplett
rauswerfen, auch deren Aufruf im Hauptprogramm,
und bei den Encodern erübrigt sich dann auch das Array...
Die Anschluss-Belegung ist im Sketch dokumentiert, für den von mir vorgestellten großen "Edel-Encoder"
gelten die Werte für die 6 großen Drehencoder am Anfang der Dokumentation.
Für die Abfrage nur eines Encoders vereinfacht man also den Sketch radikal.
Man muss seinen Sketch nur um die zentralen Punkte
der Encoderabfrage herum aufbauen.
Ich habe diesen Sketch zum Teil aus Einzelelementen im Netz zusammengebaut,
was die Encoder-Abfrage angeht, da ich damit auch erst am Anfang meiner Lernkurve stehe.....
HG