360 RotaryEncoder und 4051 Multiplexer

Hallo Liebe Community,
Kann man RotaryEncoder vernünftig mit 4051 Multiplexer betreiben?

Mein Gedanken ist für 8 Encoder 3 Multiplexer einzusetzen

Je ein Multiplexer für Out A, Out B und Switch.

Es soll für einen MIDI-Kontroller eingesetzt werden.

Hallo m8rix
Ich verstehe Dein Problem nicht.
Hast Du es versucht und es funktioniert nicht oder hast Du es gar nicht versucht?
Grüße Uwe

Was "vernünftig" ist kommt auf die zeitlichen Anforderungen an. Wenn es egal ist, wenn ab und zu ein Schritt verloren geht, dann geht alles, wie z.B. bei einer Maus.

Hallo,

auch bei einer Maus ist es nicht egal. Es ist nämlich nie egal. Ich kenne für mich genügend Gerätschaften wo der Encoder spinnt, weil schlampig programmiert. Am Ende springt der Zähler wild hin und her. Wem gefällt das schon.

Hallo Uwe,
danke für deine Hilfe.
Ich habe es versucht und es ist langsam und es fehlen werte ohne ende.

Hallo,

wenn man für ein Hand bedienten Encoder annimmt, dass man aller 1ms die Signale eines Encoders abfragt, dann müssen mit Multiplexer eben alle Encoder innerhalb dieser 1ms abgefragt werden. Die Frage lautet also, bekommst du das hin deinen Multiplexer entsprechend schnell zu bedienen?

Danke Dir,
Und es ist leider nicht egal.

Dann lasse ich es so wie es ist mit I2C.
Ein Leonardo(Slave) mit einen Mega(Master).
Geschwindigkeit ist gut und Werte gehen auch keine verloren.
Alle Potis mit Multiplexer am Leonardo und die Taster sowie Encoder am Mega.
Jetzt wir leider nur das Gehäuse etwas dicker!!!

Allerdings ein schönes slim Gehäuse währe toll!

Gibt es da etwas wie ich an mehr PINs komme?

Ich brauche mindestens 38 PIns am besten 40Pins und USB/MIDI!!!

Ich bin absoluter Neuling!
Und ich denke NEIN.

Hallo,

ein Mega hat doch über 40 Pins.
Eingangs gings nur um den einen Multiplexer. Soweit war das Thema klar.
Aktuell ist es zu konfus für klare Antworten.
Ich meine wenn die Pins ausgehen und kein anderer Arduino in Frage kommt, dann helfen nur Portexpander bzw. Multiplexer.
Die Frage lautet also. Worin liegt genau dein Problem?

Noch eine ganz andere Frage:
Wozu dienen die Encoder? Die sind ja kein Selbstzweck sondern Teil eines größeren Ganzen was macht dieses "Ganze"?
Je nachdem was dein Projekt insgesamt macht gibt es möglicherweise noch ganz andere Lösungsmöglichkeiten.

vgs

Stimmt hat er!
Allerdings würde ich den gerne weglassen da ich sonnst das Gehäuse dicker gestallten muss!!
Von daher hätte ich gerne nur den Leonardo somit kam die Idee mit den Multiplexern.
Allerding ist das Ergebnis bei mir schlecht. Somit meine fragen:

Geht es vernünftig mit Multiplexer? So wie ich es verstanden habe NEIN.
Mit Leonardo und Mega geht es! - Nachteil dickeres Gehäuse.

Somit meine Frage wie kann ich die Pins erhöhen sodass ich mehr Pins habe oder einspare.

Für MIDI gehen ja nur Bords mit ATmega32u4.

Mit den Encoder steuere ich Menüs, Loops, FX, Dummys, Device Control, Session Navigation, Track Navigation, etc.

Soweit klar.

Es hat niemand behauptet das es mit Multiplexer nicht funktioniert.
Du musst ihn nur schnell genug ansprechen, umschalten, abfragen.
Deine Antwort darauf lautet wiederholt. "Funktioniert schlecht."
Nun stell dir mal die Frage wie wir dir helfen sollen ... vielleicht kommst du selbst drauf.

Kann man den CODE von RotaryEncoder Lib nutzen?
Und wenn ja was muss ich da tun?

// +++ Mega: Haupt TAB +++ //

#include <Arduino.h>
#include <RotaryEncoder.h>
#include <Wire.h>

int PIN_IN1 = 22; //Gelb
int PIN_IN2 = 23; //Weiß

int ROTARYSTEPS = 3;
int ROTARYMIN = -3;
int ROTARYMAX = 127;

byte midiKanal = 0;
byte controllerNummer = 0;
int controllerWert;

// Setup a RotaryEncoder with 4 steps per latch for the 2 signal input pins:
// RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::FOUR3);

// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);

// Last known rotary position.
int lastPos = -1;

// This interrupt routine will be called on any change of one of the input signals
void checkPosition(){
encoder.tick(); // just call tick() to check the state.
}

void setup(){
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000L);
while (! Serial);
Serial.println("LimitedRotator example for the RotaryEncoder library.");
encoder.setPosition(10 / ROTARYSTEPS); // start with the value of 10.

attachInterrupt(PIN_IN1, checkPosition, CHANGE);
attachInterrupt(PIN_IN2, checkPosition, CHANGE);
}

// Read the current position of the encoder and print out when changed.
void loop(){
rotaryEncoder();
}

// +++ Mega: rotaryEncoder TAB +++ //

void rotaryEncoder(){
encoder.tick();

// get the current physical position and calc the logical position
int newPos = encoder.getPosition() * ROTARYSTEPS;

if (newPos < ROTARYMIN) {
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN;

} else if (newPos > ROTARYMAX) {
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX;
}

if (lastPos != newPos) {
Serial.print(newPos);
Serial.println();
lastPos = newPos;
controllerWert = newPos;
sendI2C(midiKanal, controllerNummer, controllerWert);
}
}

// +++ Mega: I2C TAB +++ //

byte i2cStatus = 0;

void sendI2C(byte command, byte firstByte, byte secondByte) {

Wire.beginTransmission(8);

byte i2cBuffer[3] = {command, firstByte, secondByte};
Wire.write(i2cBuffer, 3);
i2cStatus = Wire.endTransmission();
}

Hallo,

lass mal alles weg was du für den Encoder nicht benötigst. Interrupts benötigst du dafür auch nicht. Das Bsp. SimplePollRotator ist laut meiner Meinung nach genau richtig, auch in Hinblick auf den späteren Multiplexer.
Das heißt du pollst die Abfragen des Encoders. Genauer gesagt muss hier die Methode tick() schnell genug aufgerufen werden. Das heißt irgendwelche harten delays darfst du nirgends im Code verwenden. Irgendwelche zeitlichen Intervalle, falls notwendig, müssen mittels millis programmiert werden.

Ich habe dir zwei Bsp. Code programmiert, wie das bei mir aussehen könnte/würde.
002 sieht noch etwas "klassisch" aus.
003 ist noch eine Stufe mehr ineinander verflochten. Damit erschlägt man alles mit einer Array Iteration.
Wie man letztlich iterieren möchte hängt von ab ob man die Indexnummer für eine Ausgabe benötigt oder nicht.
Zum debuggen vielleicht sinnvoll.
Am Ende kannste die Daten aller Encoder ebenfalls mit so einer for Schleife zwischen den Arduinos übertragen.

Wenn das klappt probierst du das mit dem Multiplexer.

Erst wenn das mit den Encodern für sich bei dir funktioniert, bauste das in dein bisherigen Code ein. Unter Beachtung von no delays.

SimplePollRotator_002.ino (1,8 KB)
SimplePollRotator_003.ino (1,8 KB)

Bei einer Maus zählt niemand die Ticks, sondern bewegt sie bis der Mauszeiger an der richtigen Stelle steht. Auch bei Lautstärke oder Kanalwahl dreht man so lange weiter, bis die richtige Lautstärke oder Kanal erreicht ist.

Zudem vermute ich, daß der Encoder mechanische Kontakte hat, die entprellt werden müssen. Wenn man das nicht richtig hinbekommt, dann muß man sich über falsche Werte nicht wundern. Dabei kann man die Zeit für 1 Scan zum Entprellen nutzen, und Interrupts sind da fehl am Platz.

Danke für deine Mühen.
Es dürfen keine Informationen verloren gehen die Kurven der Signal in der DAW müssen sauber und gleichmäßig sein. Es soll ja Musik gemacht werden also das einblenden eines neuen Loops zB. oder es soll ein FX auf gedreht werden das soll ja eine saubere kurve haben.

Der Encoder ist mechanisch.
Allerdings ist der ja super entprellt durch die Lib von Matthias Hertel und wenn
ich den Herrn richtig verstanden habe kommt der Interrupt nur dann zum Einsatz wenn
der Encoder nicht bewegt wird um den Prozessor zu entlasten.

Danke!
Läuft super genau! So wie es soll.

Ich denke dank deiner Hilfe bekomme ich mein Problem gelöst.

Warum soll ich die Daten am ende mit eine for Schleife versenden und
nicht an der stelle wo sich der Wert ändert?:

if (lastPos != newPos) {
lastPos = newPos;
controllerWert = newPos;
sendI2C(midiKanal, controllerNummer, controllerWert);
}

Hallo,

@ m8trix:
laut deiner Beschreibung dachte ich das die Encoder an dem einem Arduino angeschlossen werden und auf dem anderen verarbeitet. Dazwischen ist die I2C Verbindung. Wenn das so nicht ist, dann eben nicht. Du wirst schon wissen was du machst.

@ Diettrich:
Wie oft müssen wir das denn noch behandeln. Es ist völlig egal welche Kontakte ein Encoder hat. Wenn man die Signale richtig auswertet können die prellen wie sie sollen, dass korrigiert der Code automatisch.

Die hier verwendete Lib nutzt eine Tabelle, damit wird gleichzeitig entprellt. Siehe P. Dannegger.

Desweiteren ist es nicht egal wenn Werte verloren gehen. Der Wert könnte auch schnell mal springen. Niemand fummelt gern an einem Regler rum bis endlich der Wert stimmt. Auf eine bestimmte Aktion muss die erwartete Reaktion kommen. Kauf dir mal ein DAB Radio von Philips. Da sind 2 "Encoder" dran zum Zeiten etc. einstellen. Wenn du daran drehst springen die Zahlen wild hin und her. Das willst du doch nicht wirklich? Es will auch niemand an einem Mausrad solange drehen bis man an endlich gewünschter Position ist. Über solche Aussage kann ich nur den Kopf schütteln.

Drehgeber - mikrocontroller Artikel - P. Dannegger