Rotary Encoder am Midi controller - brauche Hilfe

Hallo,

damit ich (oder andere) überhaupt eine Chance haben, wo hast du deine Libs her? Link bitte.
Und setze Code bitte in Code Tags, Button </>. Geht auch nachträglich.
Mal sehen was ich dann machen kann …

Hallo,

Sorry die Schaltfläche Code Tag habe ich übersehen :confused:

Hier der Link für die Midi Libary: Release Arduino MIDI Library v4.2 · FortySevenEffects/arduino_midi_library · GitHub

Hier der Link für die Encoder Libary: http://www.pjrc.com/teensy/td_libs_Encoder.html

Die encoder Libary steht zwar im Link unter teensy funktioniert aber auch unter UNO R3 oder MEGA 2560 (mehr konnte ich nicht testen habe nur die 2 Arduinos :slight_smile: )

Hallo,

vielleicht haben wir es schon ... Schalte mal "Compiler Warnungen" > [u]alle[/u] ein, dann wird sinnvollerweise Zeile 57 angemeckert.

void MyCCFunction2(byte channel, byte number, byte value){ //funktion zum Empfangen von midi daten
  switch (number) {
    case 13:
    MIDIvalue1old == value; //soll den Empfangenen Wert in MIDIvalue1old zwischenspeichern
    break;
  }
 }

== ist ein Vergleich du möchtest aber zuweisen, mach mal nur ein =

Hallo,

ja stimmt im komplett Modus hat er gemeckert, leider macht er noch nichts, meine Vermutung er kann mit Zeile 37 nichts anfangen, da es kein Midi befehl ist:

  if (newPosition < oldPosition) { // soll beim links drehen passieren
    MIDIvalue1 = (MIDIvalue1old - (oldPosition - newPosition)); //soll ausrechnen wie viel verringert wird
    sendeMIDI (176,13,MIDIvalue1); // vermutlich sendet er hier an der dritten Stelle einfach nichts!
    oldPosition = newPosition;

der Eigentliche Midi-Befehl wäre ja sendeMIDI(173,13,25) // die 25 ist hier nur ein Beispiel

Hallo,

so nach dem ich fast verzweifelt bin habe ich den Sketch nochmal komplett neu aufgesetzt und bekomme nun wenigstens etwas verändert. Allerdings fehlt hier noch der Rechen weg zwischen ausgelesenem Wert und ausgegebenen Wert, somit funktioniert es zur Zeit genauso wie ein Poti, aber immerhin ein Anfang ^^

#include <Encoder.h>
#include <MIDI.h>

Encoder enc_one(2,4);
int value;
int value2;

long enc_one_previous  = -999;
byte button_previous; 
MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
 Serial.begin(31250);
 MIDI.begin(MIDI_CHANNEL_OMNI);
 MIDI.setHandleControlChange(MyCCFunction);
}



void loop() {
  MIDI.read();
  value = (enc_one.read()/4);
  if(value > 127) {    
    enc_one.write(127);   
  }
  else if(value < 0) {    
    enc_one.write(0);  
  } 
 
  value = constrain(value, 0, 127);
  value2 = constrain(value, 0, 127);
  if (value != enc_one_previous) {    
    enc_one_previous = value;    
    MIDI.sendControlChange(1, value, 1);  
    }
 
}

void MyCCFunction(byte channel, byte number, byte value) {
  switch (number) {
    case 1:
      value2 = (value);
      break;
  }
}

Hallo,

ich habe mir mal die seriellen Daten ausgeben lassen, kannste auch mal machen. Da kommt nur Müll raus. Warum weis ich nicht. (Baudrate 9600). Midi read auskommentiert. Auch da nur Datenmüll. Dann habe ich das gesamte Midizeug rausgewurfen und nur den Encoder alleine laufen lassen, dass funktioniert. Der zählt richtig vor und zurück.

#include <Encoder.h>

long oldPosition  = -999;
long MIDIvalue1old = 0;
long MIDIvalue1 = 0;
long encoderDifferenz = 0;
  
Encoder myEnc(22, 23);

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}


void loop() {

  long newPosition = myEnc.read();
  Serial.println(newPosition); 

}

Irgendwie funkt die Midi Lib dazwischen. Keine Ahnung was die wie macht.

Edit:
hab gerade gesehen du hast neuen Code produziert. Gleich mal testen.

Hallo,

also mit dem Midi Zeug kann ich dir wirklich nicht weiterhelfen. Kenne mich da nicht aus und habe sowas auch nicht da. Mit dem Encoder solltest du dich nochmal einzeln befassen, damit du nur mit +1 oder -1 rechnen mußt. Aktuell ist das ein Zähler. Oder du setzt den Zähler immer wieder auf 0 zurück.

Hab dir mal einen seriellen Monitor eingebaut. Vielleicht hilft das weiter im Verständnis und Fehlersuche.

#include <Encoder.h>


Encoder enc_one(2, 4);
int value;


void setup() {
 Serial.begin(9600);
}

void loop() {
  
  value = (enc_one.read()/4);
  
  serieller_Monitor();
 
}  // loop Ende


// *** Funktionen *** //
void serieller_Monitor ()
{
  static unsigned int intervall = 500;
  static unsigned long prevMillis = 0;

  if (millis()-prevMillis<intervall) return; // Zeit noch nicht erreicht, Funktion abbrechen
  
  prevMillis+=intervall; 
  Ueberschriftszeile();
  Serial.print(value); Serial.print('\t');
  //Serial.print(IST); Serial.print('\t');
  //Serial.print(NEU); Serial.print('\t');
  Serial.println();
}


void Ueberschriftszeile ()
{
  static int counter = 33;

  counter++;
  
  if (counter<20) return; // Zeit noch nicht erreicht, Funktion abbrechen
  
  counter = 0; 
  Serial.print(F("Encoder")); Serial.print('\t');
  //Serial.print(F("S_IST")); Serial.print('\t');
  //Serial.print(F("F_NEU")); Serial.print('\t');
  Serial.println();
}

Hallo

Danke schonmal für deinen Hilfe. wie könnte ich es den hin bekommen das er nur +1 oder -1 herraus gibt, nachmöglichkeit auch nur wenn ich drehe, hatte anfangs das problem das er wenn ich nicht gedreht habe die letzte Zahl die er gezählt hatte dauernd ausgab, was in Cubase zu Problemen führt bei 2 Encodern einen anzulernen!? kenne mich leider da mit den encodern nicht wirklich aus!

Hallo,

so, hatte mich durch die fremde Lib in die Irre leiten lassen. Wenn du von der Encoder Lib das Bsp. Basic ausprobierst, dann siehst du das du damit schon genau den Zähler hast den du brauchst. Pro Dreh Tick wird um eins addiert oder subtrahiert. Zum nullen dieses Zählers mußte dich selbst kümmern. Denn der zählt immer in der Lib unbekümmert hoch und runter. Geht auch nicht anders. Du müßtest in deinem Programm dann immer die relative Null neu setzen, zum Bsp. immer nach Spurwechsel.

Das mit dem reinen +1 und -1 würde dir auch nicht weiterhelfen. Hatte meine eigene Lib schon kastriert und bemerkt das es niemals eine Null gibt. Nur die Richtungsanzeige durch +1 oder -1.

Also bleibt dir doch nichts anderes übrig als immer den alten Stand zu sichern um bei einer neuen Spur dieses Werte gegenzurechnen.

Noch eine Anmerkung. Wenn du dich mit Encodern nicht auskennst aber unbedingt benutzen möchtest, dann mußte dir das Wissen aneignen. Habe ich damals auch gemacht, genau mit den 2 geposteten Links worauf auch meine Lib basiert. Das ist keine Hexerei. Dann lernt man am schnellsten. Weil mit Worten gibts Missverständnisse, haste ja gemerkt. Wenigstens das Grundprinzip des Encoders solltest du verstehen lernen. Stichwort "Graycode".

Hallo,

alles klar und großen Dank für die Hilfen, dann werde ich mir das Wissen über Gaycode an eignen und schauen wie ich das verrechnet bekomme, wenn ich das Wissen habe.

Nochmals Danke

Hallo,

ich denke das dein Ansatz mit dem alten Wert speichern schon richtig war. Sorry das ich das nicht gleich erkannt hatte. Mit den Links aus #9 und weiteres suchen nach "Graycode" kommste sicher zum Ziel. In dem Forumslink labert einer blöd dazwischen. Nicht irre machen lassen. Peter D. hat immer recht. Tja und dazu das Bsp. "Basic" der Encoder Lib. Das Grundprinzip ist gleich, egal ob vom Peter oder von Paul. Ich denke dann haste das drauf. Wenn nicht - einfach nochmal fragen. Nur beim Thema Midi kann ich nicht mitreden.

Hallo,

alles klar, ja das Thema Midi ist da eh wieder ne ganz andere Sache, da habe ich zumindest das Prinzip verstanden wie ich etwas empfange und das empfangene Widergeben/zwischenspeichern kann und wie ich Werte versende so wie ich sie brauche, also bekomme ich das irgendwie hin. Ich danke dir recht herzlich für deine Tipps und werde hier auch den Code online stellen wenn er so läuft wie von mir gewünscht, sollte jemand ein ähnliches Projekt vorhaben :)

Hallo,

ich habe den ersten voll Funktionsfähigen Code fertig, dieser liest erst den Zustand des Reglers in der DAW aus, setzt diesen als Zähler und fängt dann erst an zu Regeln wenn man den Encoder dreht.

Hier mal das Script:

#include <Encoder.h>
//link: https://github.com/FortySevenEffects/arduino_midi_library/releases/tag/4.2

#include <MIDI.h>
//link: http://www.pjrc.com/teensy/td_libs_Encoder.html

#define LEDPWM1 3 //LED zur Veranschaulichung


Encoder enc_one(2,4); // Pins der Encoder-beinchen
int value1;
int value2;
int value2Alt;


long enc_one_previous  = -999;
MIDI_CREATE_DEFAULT_INSTANCE(); //starte eine neue MIDI instance (sehr wichtig ohne diesen Befehl läuft nichts!)

void setup() {
 Serial.begin(31250);
 MIDI.begin(MIDI_CHANNEL_OMNI); //startet die MIDI-Lesen-Funktion auf allen Kanälen (2 wäre z.B. nur auf Kanal 2)
 MIDI.setHandleControlChange(MyCCFunction2); //startet die Midi-Funktion
}



void loop() {
  MIDI.read();
  analogWrite(LEDPWM1, value2 * 2); // Led zum Anzeigen der ausgelesenen MIDI value (ist nicht Notwendig)
  if (value2 != value2Alt && value2 != value1) { //wenn die ausgelesenen Daten nicht mit dem Encoder Zähler über einstimmen,
  enc_one.write(value2);  // werden die ausgelesenen Daten in den Zähler geschrieben und
                                  // in den vergleichs Wert value2Alt
  value2Alt = value2;
  }  
  value1 = enc_one.read(); // standard Encoder zeile
  if(value1 > 127) {       // legt fest was passiert wenn der Wert über 127 steigt
    enc_one.write(127);   
  }
  else if(value1 < 0) {    // legt fest was passiert wenn der Wert unter 0 sinkt
    enc_one.write(0);  
  } 
 
  value1 = constrain(value1, 0, 127); // legt den Zählbereich für value1, von 0, bis 127 fest
  if (value1 != enc_one_previous && value1 != value2Alt) {   // wenn value1 nicht gleich enc_one_previous ist und value1 nicht gleich
    enc_one_previous = value1;    // value2Alt ist, dann wird enc_one_previous mit value1 gleich gesetzt
    MIDI.sendControlChange(1, value1, 1);  //und der MIDI Befehl auf ("Note" 1, errechnete value, Kanal1) wird versendet
    } 
}

void MyCCFunction2(byte channel, byte number, byte value) { //auslese Funktion für das Empfangen des Zustandes
  switch (number) {
    case 2:
      value2 = (value);
      break;
  }
}

P.s.: Wenn ich den Code etwas angepasst habe (Auflösung der Schaltsignale, da er zur zeit mit einer umdrehung knapp 1dB verändert ist mir das etwas zu grob) werde ich diesen Code hier ebenfalls Posten!

Hallo,

sehr schön und ich wollte dir gerade ein Bsp. von mir liefern. Aber so geht das auch und du kannst bei deiner nun schon gewohnten Lib bleiben. Wegen deiner Auflösung. Höher aufgelöst geht nicht. Du darfst nicht in Umdrehungen denken. Pro Encoder Tick gehts eins plus oder minus. Wieviel Ticks das pro Umdrehungen sind hängt vom Encoderaufbau ab. Je größer der im Durchmesser ist, umso mehr Pulswechsel können untergebracht werden. Die Frage lautet eher ist dir die Feinfühligkeit deines Encoders zu fein oder zu grob. Du kannst dir auch einen eigenen Encoder bauen. Große runde Pappscheibe mit versetzten Löchern drin. Aufbau und Funktion solltest du nun erlesen haben denke ich. Dazu 2 Lichtschranken. Dann kannste dir die Pulsbreite und damit die Empfindlichkeit wie weit du für eins rauf oder runter zählen drehen mußt selbst festlegen. Oder wenn beim jetzigen bleibst und der zu empfindlich ist, teilste den Zähler immer durch 4. Dann zählst du mit vier Ticks eins hoch/runter. Der Vorteil vom Encoder ist ja der das man keinen mechanischen Anschlag hat wie beim Poti. Man kann leiern wie man möchte.