4 Bit Display, Rotary und USB HID (Arduino Uno), Menü auswählen und USB HID senden

:wink:

Ich würde das nicht alles mit if irgendwas machen.
Die Abfragebedingung war vielleicht ungünstig ausgewählt.
Allerdings was hindert Dich daran erst encoderPos 4 und dann encoderpos 5 auszuwerten? da muss dann der Bereich erweitert werden...

Aber vielleicht, wenn Du so weiter machen willst:

  if (encoderPos == 4)
  {
    static bool merker = false;
    if (!digitalRead(encoderPinSW))
    {
      if (!merker)
      {
        lcd.setCursor(6, 1);
        lcd.print("  Mute*  ");
        merker = true;
      }
      else
      {
        lcd.setCursor(6, 1);
        lcd.print("--Mute-- ");
        merker = false;
      }
    }
  }

Ich habe es mal reinkopiert, aber genau das gleiche Problem hatte ich auch, als ich versucht hatte den letzten Zustand in einer Variable zu speichern:
Beim drücken der Tasters switcht es so schnell zwischen den beiden MUTE´s hin und her, dass man es nur flickern sieht.
Deswegen hab ich es aufgegeben und gepostet, ich dachte vielleicht gibt es wirkungsvoller Lösungsansätze.
Man müsste irgendwie nur einen Tastemdruck zulassen und dann dürfte erst ein neuer was auslösen.
Wäre es nicht möglich nur eine Flanke auszuwerten? Aber wie?

AAHH!
Na dann sperren!

JaJa, genau das passiert jetzt.
Dein Switch prellt! Du brauchst eine Sperre für xx ms. Nennt sich bounce...

Mal schaun...

if (encoderPos == 4)
{
  static bool merker = false;
  static unsigned long lastmillis=0;
  if (!digitalRead(encoderPinSW))
  {
    if (!merker)
    {
      lastmillis = millis();
      lcd.setCursor(6, 1);
      lcd.print("  Mute*  ");
      merker = true;
    }
    else if (millis() - lastmillis > 30)
    {
      lcd.setCursor(6, 1);
      lcd.print("--Mute-- ");
      merker = false;
    }
  }
}

wirklich nicht schick - aber testweise um das prellen zu killen.

Also das Problem besteht nach wie vor.
Ich hoffe ich interpretiere das richtig:
Ich vermute, dass es nicht Prellen ist, sondern das Programm rolliert immer zwischen Mute* und Mute--- durch solange ich den Taster drücke.
Für den Prozessor ist mein Drücken unendlich lange, daher wechselt es zig mal zwischen dem einen und dem anderen Menü hin und her.
Man bräuchte dann eine Toggle Funktion oder eine Flanke vom meinen Tastendruck auswerten, jedoch kein High oder Low vom Tastendruck.
Zum Test hab ich mal eine Toggle Funktion mit einem Delay rein gemacht und ja es wechselt dann immer nur langsam:

if (encoderPos == 4)
 {
  static bool merker = false;
  while (digitalRead(encoderPinSW)){}
  
    if (merker == false)
    {
      lcd.setCursor(6, 1);
      lcd.print("  Mute*  ");
      merker = true;
    }
    else
    {
      lcd.setCursor(6, 1);
      lcd.print("--Mute-- ");
      merker = false;
    
    }
  delay(200);
 }
}

vermutlich.

Dann sperren auf eine andere Art:

  if (encoderPos == 4)
  {
    static bool tik = false;
    static bool tak = false;
    if (!digitalRead(encoderPinSW))
    {
      if (!tik && !tak)
      {
        tik = true;
        tak = true;
        lcd.setCursor(6, 1);
        lcd.print("  Mute*  ");
      }
      else if (!tik && tak)
      {
        tik = true;
        tak = false;
        lcd.setCursor(6, 1);
        lcd.print("--Mute-- ");
      }
    }
    else
    {
      tik = false;
    }
  }

Ob das funktioniert... Keinen Plan.

Das ist schon sehr nah dran, aber ich glaube jetzt prellt der Taster, ab und an kommt es dennoch mal dazu, dass 2x das Mute bei einem Druck gewechselt wird.

Ich hab jetzt noch ein Monoflop eingebaut:

{
  const char * text[5] = {"Filter 1", "Filter 2", "Filter 3", "Filter 4", "  Mute  "};
  const uint8_t code[5][8] = {
    {0, 0,  8, 40, 0, 0, 0, 0},
    {0, 0, 21, 40, 0, 0, 0, 0},
    {0, 0, 23, 40, 0, 0, 0, 0},
    {0, 0, 28, 40, 0, 0, 0, 0},
    {0, 0, 29, 40, 0, 0, 0, 0}
  };
  rotating = true;  // reset the debouncer
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt;
  const uint32_t intervall = 5000;  // Abschaltzeit nach Inaktivität in ms
  uint32_t jetzt2 = millis();
  static uint32_t vorhin2 = jetzt2;
  const uint32_t intervall2 = 50;  // Abschaltzeit nach Inaktivität in ms
  if (lastReportedPos != encoderPos)
  {
    lastReportedPos = encoderPos;
    vorhin = jetzt; // Monoflop retriggern
    lcd.setCursor(0, 0);
    lcd.print("12345678901234567890");
    //    lcd.setCursor(6, 1);
    //    lcd.print("                    ");
    lcd.setCursor(6, 1);
    if (encoderPos < 0) encoderPos = 0;
    if (encoderPos > 4) encoderPos = 4;
    lcd.print(text[encoderPos]);
    neuePosition = true;
  }
  if ( neuePosition && !digitalRead(encoderPinSW) )  // nur beim Tastendruck des Encoders werden die Zeichen verschickt
  {
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();

  }
  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
  }
  if (encoderPos == 4)
  {
    static bool tik = false;
    static bool tak = false;
    if (!digitalRead(encoderPinSW))
      {
        if (!tik && !tak)
          {
            vorhin2 = jetzt2; // Monoflop retriggern
            tik = true;
            tak = true;
            lcd.setCursor(6, 1);
            lcd.print("  Mute*  ");
          }
            else if (!tik && tak && jetzt2 - vorhin2 >= intervall2)
          {
            tik = true;
            tak = false;
            lcd.setCursor(6, 1);
            lcd.print("--Mute-- ");
          }
      }
         else
          {
            tik = false;
          }
  }
}

Jetzt tut es wie es soll :+1: :+1:

Nun muss ich es nur noch schaffen, dass Zeichen auch beim 2ten mal Mute Drücken versendet werden.
Das gibt wieder was :upside_down_face:

Ich habs einen Thread obendrüber editiert, hatte sich mit deiner Antwort überschnitten

Schick, aber die ganzen if's find ich schon grenzwertig...
Na denne.

Warum wird das dann instabil?

Ich habe jetzt noch eingebaut, dass auch nur Zeichen versendet werden, wenn das Display an ist.
Und
Wenn man in der Mute* schleife ist erst wieder andere Menüs anwählen kann, wenn man nochmals Mute betätigt hat. (Bei Mute* und Mute werden nun auch Zeichen per HID versendet.

Ich habe allerdings das Problem, dass nun nur noch durch drehen das Display angeht (und dann auch Zeichen versendet werden können), schick wäre, wenn ein Tastendruck auch das Display einschalten würde, ich bekomme das aber nicht hin...
Hier der ganze Code inzwischen:

#include <LiquidCrystal.h>
const int rs = 4, en = 5, d4 = 6, d5 = 7, d6 = 8, d7 = 9;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const byte encoderPinA = 2;
const byte encoderPinB = 3;
const byte encoderPinSW = 10;
volatile int8_t encoderPos = 0;          // a counter for the dial
int8_t lastReportedPos = -1;             // change management
bool rotating = false;                   // debounce management
bool neuePosition = false;
boolean A_set = false;                   // interrupt service routine vars
boolean B_set = false;                   // interrupt service routine vars
int8_t lastMutePos = 0;
bool displayOff = true;

void setup() {
  lcd.begin(20, 2);

  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderPinSW, INPUT_PULLUP);

  attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)

  Serial.begin(9600);                     // output
}

void loop()
{
  const char * text[5] = {"Filter 1", "Filter 2", "Filter 3", "Filter 4", "  Mute  "};
  const uint8_t code[5][8] = {
    {0, 0,  8, 40, 0, 0, 0, 0},
    {0, 0, 21, 40, 0, 0, 0, 0},
    {0, 0, 23, 40, 0, 0, 0, 0},
    {0, 0, 28, 40, 0, 0, 0, 0},
    {0, 0, 29, 40, 0, 0, 0, 0}
    };
  rotating = true;  // reset the debouncer
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt;
  const uint32_t intervall = 5000;        // Abschaltzeit nach Inaktivität in ms
  uint32_t jetzt2 = millis();
  static uint32_t vorhin2 = jetzt2;
  const uint32_t intervall2 = 20;         // Entprellen
  if (lastReportedPos != encoderPos)
  {
    lastReportedPos = encoderPos;
    vorhin = jetzt; // Monoflop retriggern
    displayOff = true;
    lcd.setCursor(0, 0);
    lcd.print("12345678901234567890");
    //    lcd.setCursor(6, 1);
    //    lcd.print("                    ");
    lcd.setCursor(6, 1);
    if (encoderPos < 0 && lastMutePos == 0) encoderPos = 0;
    if (encoderPos <= 3 && lastMutePos == 1) encoderPos = 4;                
    if (encoderPos > 4) encoderPos = 4;
    if (lastMutePos == 0)
    lcd.print(text[encoderPos]);
    neuePosition = true;
    if (encoderPos >3 && lastMutePos == 1)
    {
    lcd.print("  Mute*  ");
    }
  }
  if (displayOff && encoderPos <= 3 && lastMutePos == 0 && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
  {
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();

  }
  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOff = false;
  }
  if (encoderPos > 3)
  {
    static bool tik = false;
    static bool tak = false;
    if (!digitalRead(encoderPinSW))
      {
        if (!tik && !tak)
          {
            vorhin2 = jetzt2;              // Monoflop retriggern für Entprellen
            tik = true;
            tak = true;
            lcd.setCursor(6, 1);
            lcd.print("  Mute* ");
            Serial.write(code[encoderPos], 8);
            releaseKey();
            lastMutePos = 1;
          }
            else if (!tik && tak && jetzt2 - vorhin2 >= intervall2)
          {
            tik = true;
            tak = false;
            lcd.setCursor(6, 1);
            lcd.print("  Mute  ");
            Serial.write(code[encoderPos], 8);
            releaseKey();
            lastMutePos = 0;
          }
      }
         else
          {
            tik = false;
          }
  }
}
void releaseKey() {
  uint8_t keyNone[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  Serial.write(keyNone, 8);                  // Send Release key
}

                                             
void doEncoderA()                            // Interrupt on A changing state
{
  if ( rotating ) delay (1);                 // wait a little until the bouncing is done
  if ( digitalRead(encoderPinA) != A_set ) 
  { // debounce once more
    A_set = !A_set;                                      
    if ( A_set && !B_set )                   // adjust counter + if A leads B
      encoderPos += 1;
    rotating = false;                        // no more debouncing until loop() hits again
  }
}

                                             
void doEncoderB()                            // Interrupt on B changing state, same as A above
{                         
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != B_set ) 
  {
    B_set = !B_set;                                   
    if ( B_set && !A_set )                   //  adjust counter - 1 if B leads A
      encoderPos -= 1;
    rotating = false;
  }
}

Vielleicht hat ja jemand einen Tipp :slight_smile:

Pff.
Warum nennst Du die Variable displayOff und setzt sie true, wenn Du damit Inhalt anzeigen willst?

Vermutlich hier wird sich das finden, was Du willst:

  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOff = false;
  }
  else if // Hier jetzt Bedingung auf den Encoder setzen
  {
    // displayOff ????
  }

Ok displayOff ist etwas unglücklich gewählt, aber ich sende ja nur Zeichen wenn displayOff = true ist, dann wird nach dem Monofloptimeout displayOff = false; gesetzt und nach dem retriggern des Monoflop wieder auf displayOff = true;, so dass man bei neuePosition = true; wieder senden kann.

Ich verstehe aber nicht worauf du mit else if hinausmöchtest?

Also ich versuche nochmal zu definieren, was ich eigentlich vor habe.
Im Grunde macht ja alles was es soll, wenn rotiert wird, dann geht das Display an, ist es an können Zeichen versendet werden, wenn nicht, dann kann man nichts versenden.

Ich würde jetzt gerne durch den Tastendruck ebenfalls das Display einschalten und danach soll der Vorgang wie zuvor fortgesetzt werden.
(Rotieren und bei Tastendruck Zeichen versenden)

Ich habe jetzt die Variable DisplayOff auf DisplayOn umgeändert (machte wirklich kein Sinn es doppelt zu verneinen)

Hier der aktuelle Code:

#include <LiquidCrystal.h>
const int rs = 4, en = 5, d4 = 6, d5 = 7, d6 = 8, d7 = 9;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const byte encoderPinA = 2;
const byte encoderPinB = 3;
const byte encoderPinSW = 10;
volatile int8_t encoderPos = 0;          // a counter for the dial
int8_t lastReportedPos = -1;             // change management
bool rotating = false;                   // debounce management
bool neuePosition = false;
boolean A_set = false;                   // interrupt service routine vars
boolean B_set = false;                   // interrupt service routine vars
int8_t lastMutePos = 0;
bool displayOn = true;

void setup() {
  lcd.begin(20, 2);

  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderPinSW, INPUT_PULLUP);

  attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)

  Serial.begin(9600);                     // output
}

void loop()
{
  const char * text[5] = {"Filter 1", "Filter 2", "Filter 3", "Filter 4", "  Mute  "};
  const uint8_t code[5][8] = {
    {0, 0,  8, 40, 0, 0, 0, 0},
    {0, 0, 21, 40, 0, 0, 0, 0},
    {0, 0, 23, 40, 0, 0, 0, 0},
    {0, 0, 28, 40, 0, 0, 0, 0},
    {0, 0, 29, 40, 0, 0, 0, 0}
    };
  rotating = true;  // reset the debouncer
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt;
  const uint32_t intervall = 5000;        // Abschaltzeit nach Inaktivität in ms
  uint32_t jetzt2 = millis();
  static uint32_t vorhin2 = jetzt2;
  const uint32_t intervall2 = 20;         // Entprellen
  if (lastReportedPos != encoderPos)
  {
    lastReportedPos = encoderPos;
    vorhin = jetzt; // Monoflop retriggern
    displayOn = true;
    lcd.setCursor(0, 0);
    lcd.print("12345678901234567890");
    //    lcd.setCursor(6, 1);
    //    lcd.print("                    ");
    lcd.setCursor(6, 1);
    if (encoderPos < 0 && lastMutePos == 0) encoderPos = 0;
    if (encoderPos <= 3 && lastMutePos == 1) encoderPos = 4;                
    if (encoderPos > 4) encoderPos = 4;
    if (lastMutePos == 0)
    lcd.print(text[encoderPos]);
    neuePosition = true;
    if (encoderPos >3 && lastMutePos == 1)
    {
    lcd.print("  Mute*  ");
    }
  }
  if (displayOn && encoderPos <= 3 && lastMutePos == 0 && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
  displayOn = true;
  {
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();

  }
  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOn = false;
  }
  if (encoderPos > 3)
  {
    static bool tik = false;
    static bool tak = false;
    if (!digitalRead(encoderPinSW))
      {
        if (!tik && !tak)
          {
            vorhin2 = jetzt2;              // Monoflop retriggern für Entprellen
            tik = true;
            tak = true;
            lcd.setCursor(6, 1);
            lcd.print("  Mute* ");
            Serial.write(code[encoderPos], 8);
            releaseKey();
            lastMutePos = 1;
          }
            else if (!tik && tak && jetzt2 - vorhin2 >= intervall2)
          {
            tik = true;
            tak = false;
            lcd.setCursor(6, 1);
            lcd.print("  Mute  ");
            Serial.write(code[encoderPos], 8);
            releaseKey();
            lastMutePos = 0;
          }
      }
         else
          {
            tik = false;
          }
  }
}
void releaseKey() {
  uint8_t keyNone[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  Serial.write(keyNone, 8);                  // Send Release key
}

                                             
void doEncoderA()                            // Interrupt on A changing state
{
  if ( rotating ) delay (1);                 // wait a little until the bouncing is done
  if ( digitalRead(encoderPinA) != A_set ) 
  { // debounce once more
    A_set = !A_set;                                      
    if ( A_set && !B_set )                   // adjust counter + if A leads B
      encoderPos += 1;
    rotating = false;                        // no more debouncing until loop() hits again
  }
}

                                             
void doEncoderB()                            // Interrupt on B changing state, same as A above
{                         
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != B_set ) 
  {
    B_set = !B_set;                                   
    if ( B_set && !A_set )                   //  adjust counter - 1 if B leads A
      encoderPos -= 1;
    rotating = false;
  }
}

Was ich nun überhaupt nicht verstehe, ich setze hier bei Display timeout abgelaufen die Variable

DisplayOn = true

if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOn = false;
  }

Ich muss die dann ja wieder beim Tastendruck auf

DisplayOn = true

setzen
Das habe ich mal hier versucht:

}
  if (displayOn && encoderPos <= 3 && lastMutePos == 0 && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
  displayOn = true;
  {

Egal wo ich das tue, es werden dann immer Zeichen dauerhaft versendet???
Ich verstehe einfach nicht warum.

Bist Du Dir sicher, das das richtig ist?
Ich würd mal meinen, das Du die Klammer nach oben setzen solltest.

Ich komme einfach nicht mit, meinst Du so:

  {
    lastReportedPos = encoderPos;
    vorhin = jetzt; // Monoflop retriggern
    displayOn = true;
    lcd.setCursor(0, 0);
    lcd.print("12345678901234567890");
    //    lcd.setCursor(6, 1);
    //    lcd.print("                    ");
    lcd.setCursor(6, 1);
    if (encoderPos < 0 && lastMutePos == 0) encoderPos = 0;
    if (encoderPos <= 3 && lastMutePos == 1) encoderPos = 4;                
    if (encoderPos > 4) encoderPos = 4;
    if (lastMutePos == 0)
    lcd.print(text[encoderPos]);
    neuePosition = true;
    if (encoderPos >3 && lastMutePos == 1)
    {
    lcd.print("  Mute*  ");
    }
  }
  {
    if (displayOn && encoderPos <= 3 && lastMutePos == 0 && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
    displayOn = true;
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();

Auch hier werden immer sofort eeeeeeeeeeee ausgegeben, ohne Tastendruck.
Irgendwie habe ich mit dem einfügen von dem

displayOn = true;

den Tastendruck ausgehebelt, komme aber nicht drauf wie.

Es wird immer das erste Zeichen sofort ausgegeben eeeeeeeeeeeeeeeeeeeeeeeeeeee usw.

das habe ich gemeint

So? :

  if (displayOn && encoderPos <= 3 && lastMutePos == 0 && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
  {
    displayOn = true;
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();

  }
  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOn = false;

Das bringt nichts.. Aber ich glaube ich verstehe dich auch einfach nicht.
Versuchs bitte mal so, zeige mir meinen Code und dann den von dir editierten, so kann ich die Unterschiede sofort erkennen.

Moin,

ich hab nochmal gelesen...

Na dann prüfe doch, ob der Display aus ist und die Taste gedrückt wurde.... Wennja, mach ihn an.
Ist jetzt in Zeile 46 bis 49

#include <LiquidCrystal.h>
const int rs = 4, en = 5, d4 = 6, d5 = 7, d6 = 8, d7 = 9;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const byte encoderPinA = 2;
const byte encoderPinB = 3;
const byte encoderPinSW = 10;
volatile int8_t encoderPos = 0;          // a counter for the dial
int8_t lastReportedPos = -1;             // change management
bool rotating = false;                   // debounce management
bool neuePosition = false;
boolean A_set = false;                   // interrupt service routine vars
boolean B_set = false;                   // interrupt service routine vars
int8_t lastMutePos = 0;
bool displayOn = true;

void setup()
{
  lcd.begin(20, 2);
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderPinSW, INPUT_PULLUP);
  attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)
  Serial.begin(9600);                     // output
}

void loop()
{
  const char *text[5] = {"Filter 1", "Filter 2", "Filter 3", "Filter 4", "  Mute  "};
  const uint8_t code[5][8] =
  {
    {0, 0,  8, 40, 0, 0, 0, 0},
    {0, 0, 21, 40, 0, 0, 0, 0},
    {0, 0, 23, 40, 0, 0, 0, 0},
    {0, 0, 28, 40, 0, 0, 0, 0},
    {0, 0, 29, 40, 0, 0, 0, 0}
  };
  rotating = true;  // reset the debouncer
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt;
  const uint32_t intervall = 5000;        // Abschaltzeit nach Inaktivität in ms
  uint32_t jetzt2 = millis();
  static uint32_t vorhin2 = jetzt2;
  const uint32_t intervall2 = 20;         // Entprellen
  if (!displayOn && !digitalRead(encoderPinSW))
  {
    displayOn = true;
  }
  if (lastReportedPos != encoderPos)
  {
    lastReportedPos = encoderPos;
    vorhin = jetzt; // Monoflop retriggern
    displayOn = true;
    lcd.setCursor(0, 0);
    lcd.print("12345678901234567890");
    //    lcd.setCursor(6, 1);
    //    lcd.print("                    ");
    lcd.setCursor(6, 1);
    if (encoderPos < 0 && lastMutePos == 0) encoderPos = 0;
    if (encoderPos <= 3 && lastMutePos == 1) encoderPos = 4;
    if (encoderPos > 4) encoderPos = 4;
    if (lastMutePos == 0)
      lcd.print(text[encoderPos]);
    neuePosition = true;
    if (encoderPos > 3 && lastMutePos == 1)
    {
      lcd.print("  Mute*  ");
    }
  }
  if (displayOn && encoderPos <= 3 && lastMutePos == 0 && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
    displayOn = true;
  {
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();
  }
  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOn = false;
  }
  if (encoderPos > 3)
  {
    static bool tik = false;
    static bool tak = false;
    if (!digitalRead(encoderPinSW))
    {
      if (!tik && !tak)
      {
        vorhin2 = jetzt2;              // Monoflop retriggern für Entprellen
        tik = true;
        tak = true;
        lcd.setCursor(6, 1);
        lcd.print("  Mute* ");
        Serial.write(code[encoderPos], 8);
        releaseKey();
        lastMutePos = 1;
      }
      else if (!tik && tak && jetzt2 - vorhin2 >= intervall2)
      {
        tik = true;
        tak = false;
        lcd.setCursor(6, 1);
        lcd.print("  Mute  ");
        Serial.write(code[encoderPos], 8);
        releaseKey();
        lastMutePos = 0;
      }
    }
    else
    {
      tik = false;
    }
  }
}
void releaseKey()
{
  uint8_t keyNone[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  Serial.write(keyNone, 8);                  // Send Release key
}


void doEncoderA()                            // Interrupt on A changing state
{
  if ( rotating ) delay (1);                 // wait a little until the bouncing is done
  if ( digitalRead(encoderPinA) != A_set )
  {
    // debounce once more
    A_set = !A_set;
    if ( A_set && !B_set )                   // adjust counter + if A leads B
      encoderPos += 1;
    rotating = false;                        // no more debouncing until loop() hits again
  }
}


void doEncoderB()                            // Interrupt on B changing state, same as A above
{
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != B_set )
  {
    B_set = !B_set;
    if ( B_set && !A_set )                   //  adjust counter - 1 if B leads A
      encoderPos -= 1;
    rotating = false;
  }
}

Musst Du sehen, ob es das ist, was Du willst...

Erst mal danke fürs ansehen und Du hast natürlich recht, das muss viel weiter oben passieren, nicht da wo man schon mitten im Ablauf ist...
Leider ist die Lösung nicht ganz so einfach, es führt zum selben Ergebnis wie zuvor "eeeeeeeeeeeeee"
Aber Du hast mich in die richtiger Richtung geschubst:

if (encoderPos <= 3 && !digitalRead(encoderPinSW))
  {
    vorhin = jetzt; // Monoflop retriggern
    lcd.setCursor(0, 0);
    lcd.print(text2[encoderPos]);
  }

  
  if (lastReportedPos != encoderPos)
  {

natürlich braucht man noch ein weiteres Array:

  const char * text2[5] = {"Menueauswahl treffen", "Menueauswahl treffen", "Menueauswahl treffen", "Menueauswahl treffen", "Menueausw Test"};

Dennoch hab ich noch ein paar Problemchen, wie dass -wenn man Mute aktiviert hat- und dabei rotiert > "Menueausw Test" dann auftaucht, anstelle von > " Mute aktiv " -der Text aus der Muteposition - angezeigt wird, da muss ich noch schauen ob ich das auch lösen kann.

Hier dann der nun komplette aktuelle Code:

#include <LiquidCrystal.h>
const int rs = 4, en = 5, d4 = 6, d5 = 7, d6 = 8, d7 = 9;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const byte encoderPinA = 2;
const byte encoderPinB = 3;
const byte encoderPinSW = 10;
volatile int8_t encoderPos = 0;          // a counter for the dial
int8_t lastReportedPos = -1;             // change management
bool rotating = false;                   // debounce management
bool neuePosition = false;
boolean A_set = false;                   // interrupt service routine vars
boolean B_set = false;                   // interrupt service routine vars
bool mutePos = false;
bool displayOn = true;

void setup() {
  lcd.begin(20, 2);

  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderPinSW, INPUT_PULLUP);

  attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)

  Serial.begin(9600);                     // output
}

void loop()
{
  const char * text[5] = {"     Filter  1      ", "     Filter  2     ", "     Filter  3    ", "    Pass through    ", "        Mute        "};
  const char * text2[5] = {"Menueauswahl treffen", "Menueauswahl treffen", "Menueauswahl treffen", "Menueauswahl treffen", "Menueausw Test"};
  const uint8_t code[5][8] = {
    {0, 0,  8, 40, 0, 0, 0, 0},
    {0, 0, 21, 40, 0, 0, 0, 0},
    {0, 0, 23, 40, 0, 0, 0, 0},
    {0, 0, 28, 40, 0, 0, 0, 0},
    {0, 0, 29, 40, 0, 0, 0, 0}
    };
  rotating = true;  // reset the debouncer
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt;
  const uint32_t intervall = 5000;        // Abschaltzeit nach Inaktivität in ms
  uint32_t jetzt2 = millis();
  static uint32_t vorhin2 = jetzt2;
  const uint32_t intervall2 = 20;         // Entprellen
  if (encoderPos <= 3 && !digitalRead(encoderPinSW))
  {
    vorhin = jetzt; // Monoflop retriggern
    lcd.setCursor(0, 0);
    lcd.print(text2[encoderPos]);
  }

  
  if (lastReportedPos != encoderPos)
  {
    lastReportedPos = encoderPos;
    vorhin = jetzt; // Monoflop retriggern
    displayOn = true;
    lcd.setCursor(0, 1);
    if (encoderPos < 0 && mutePos == false) encoderPos = 0;
    if (encoderPos <= 3 && mutePos == true) encoderPos = 4;                
    if (encoderPos > 4) encoderPos = 4;
    if (mutePos == false)
    lcd.print(text[encoderPos]);
    if (encoderPos <= 3)
    lcd.setCursor(0, 0);
    lcd.print(text2[encoderPos]);
    neuePosition = true;
    if (encoderPos >3 && mutePos == true)
    {
    lcd.print("     Mute aktiv     ");
    }
  }
  if (displayOn && encoderPos <= 3 && mutePos == false && neuePosition && !digitalRead(encoderPinSW)) // nur beim Tastendruck des Encoders werden die Zeichen verschickt
  {
    neuePosition = false;
    Serial.write(code[encoderPos], 8);
    releaseKey();

  }
  if (encoderPos <= 3 && jetzt - vorhin >= intervall)
  {
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    lcd.setCursor(0, 0);
    lcd.print("                    ");
    displayOn = false;
  }
  if (encoderPos == 4)
  {
    static bool tik = false;
    static bool tak = false;
    if (!digitalRead(encoderPinSW))
      {
        if (!tik && !tak)
          {
            vorhin2 = jetzt2;              // Monoflop retriggern für Entprellen
            tik = true;
            tak = true;
            lcd.setCursor(0, 1);
            lcd.print("     Mute aktiv     ");
            lcd.setCursor(0, 0);
            lcd.print(" Mute Deaktivieren! ");
            Serial.write(code[encoderPos], 8);
            releaseKey();
            mutePos = true;
          }
            else if (!tik && tak && jetzt2 - vorhin2 >= intervall2)
          {
            tik = true;
            tak = false;
            lcd.setCursor(0, 1);
            lcd.print("  Mute deaktiviert  ");
            lcd.setCursor(0, 0);
            lcd.print("  Mute deaktiv Test ");
            Serial.write(code[encoderPos], 8);
            releaseKey();
            mutePos = false;
          }
      }
         else
          {
            tik = false;
          }
  }
}
void releaseKey() {
  uint8_t keyNone[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  Serial.write(keyNone, 8);                  // Send Release key
}

                                             
void doEncoderA()                            // Interrupt on A changing state
{
  if ( rotating ) delay (1);                 // wait a little until the bouncing is done
  if ( digitalRead(encoderPinA) != A_set ) 
  { // debounce once more
    A_set = !A_set;                                      
    if ( A_set && !B_set )                   // adjust counter + if A leads B
      encoderPos += 1;
    rotating = false;                        // no more debouncing until loop() hits again
  }
}

                                             
void doEncoderB()                            // Interrupt on B changing state, same as A above
{                         
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != B_set ) 
  {
    B_set = !B_set;                                   
    if ( B_set && !A_set )                   //  adjust counter - 1 if B leads A
      encoderPos -= 1;
    rotating = false;
  }
}

Ich glaube hier liegt das Problem, anstelle von 4 muss eine 3 sein, kanns aber jetzt grad nicht testen:

lcd.setCursor(0, 1);
    if (encoderPos <= 3 && mutePos == true) encoderPos = 4;