Weiterentwicklung einer Software zur Funktionsreife

Könnte sein:

Ah Danke!

@fftransformation
willst mal was probieren?
Du bauchst nur den Rotary.
Der Switch hat einen eingebauten PULLUP.
Das ganze ist nicht kommentiert, aber gaanz viel Serielleer Output.
Die Drei Pins für den Encoder musste anpassen.
Alles andere müsste so bleiben können.

Du kannst damit durch die filter rollen, den HID-Buchstaben ausgeben und warten, bis das "virtuelle" Display ausgeht.
Die Ausgabe Display an, kommt dann wieder, wenn Du an dem Rotary drehst, oder drückst.

Die encoderlib hab ich angehangen.

// Rotary
#include <rotary.h>
Rotary r = Rotary(45, 43);
const byte rotBut = 41;

// LCD
const byte lcdSpalten = 20;
const byte lcdZeilen = 2;

// Inhalt
struct inhalt
{
  const char *name;
  const char *hid;
};

constexpr inhalt MyFilter[]
{
  {"Filter 1", "a"}, {"Filter 2", "s"}, {"Filter 3", "d"}, {"Filter 4", "f"}
};
constexpr inhalt MySetup[]
{
  {"Displayzeit", ""}, {"Wlan", "g"}
};

uint32_t displayZeit = 1000UL * 10; // Zeit in ms
uint32_t displayTick = 0;
bool isDisplay = true; // Hilfsvariable


bool isMenu = true;
bool isSetup = !isMenu;
bool isTasteKurz = false;
bool isTasteLang = false;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode (rotBut, INPUT);
}

void loop()
{
  if (isMenu) myMenu();
  if (isSetup) mySetup();
  getRotaryButton();
  setDisplayLigth();
}

void myMenu()
{
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = 100;
  const uint8_t maxPos = 3;
  rotaryPos = getRotary(rotaryPos);
  if (rotaryPos != lastRotaryPos)
  {
    if (rotaryPos > maxPos) rotaryPos = 0;
    else if (rotaryPos < 0) rotaryPos = maxPos;
    lastRotaryPos = rotaryPos;
    Serial.println(rotaryPos);
    ausgabe(MyFilter[rotaryPos].name);
  }
  if (isTasteKurz)
  {
    sendHid(MyFilter[rotaryPos].hid);
    isTasteKurz = false;
  }
}


void mySetup()
{
}

void sendHid(const char *zeichen)
{
  Serial.print(F("HID: "));
  Serial.println(zeichen);
}

void ausgabe(const char *zeile)
{
  Serial.println(zeile);
}

void setDisplayLigth()
{
  if (millis() - displayTick > displayZeit)
  {
    if (isDisplay)
    {
      Serial.println(F("Display aus!"));
      isDisplay = false;
    }
  }
  else
  {
    if (!isDisplay)
    {
      Serial.println(F("Display an!"));
      isDisplay = true;
    }
  }
}

void getRotaryButton()
{
  const uint32_t bounceTime = 60; // zeit in ms
  static uint32_t lastmillis = 0;
  static bool isPressed = false;
  if (!digitalRead(rotBut) && !isPressed)
  {
    isPressed = true;
    displayTick = millis();
    lastmillis = millis();
  }
  else if (millis() - lastmillis > bounceTime)
  {
    if (digitalRead(rotBut) && isPressed)
    {
      if (millis() - lastmillis < 500)
      {
        isTasteKurz = true;
        Serial.println(F("kurz"));
      }
      else
      {
        isTasteLang = true;
        Serial.println(F("lang"));
      }
      isPressed = false;
    }
  }
}

uint8_t getRotary(uint8_t posValue)
{
  unsigned char val = r.process();
  if (val)
  {
    if (val == r.clockwise() && isDisplay)
    {
      Serial.print(F("rechts"));
      posValue++;
    }
    else if (val == r.counterClockwise() && isDisplay)
    {
      Serial.print(F("links"));
      posValue--;
    }
    Serial.println(F(" gedreht"));
    displayTick = millis();
  }
  return posValue;
}

Rotary.zip (6,4 KB)

Ja gerne, nur vor Wochenende werde ich vermutlich nicht dazu kommen..
Danke für die Mühe vorab!

Du meinst vermutlich setDisplayLight(); :bulb:

So funktioniert es bei mir besser:

// Enable this to emit codes twice per step.
//#define HALF_STEP

// Enable weak pullups
#define ENABLE_PULLUPS 

Ein einzelner Tastendruck wird manchmal als doppelter erkannt:

13:28:33.999 -> rechts gedreht
13:28:33.999 -> 1
13:28:33.999 -> Filter 2
13:28:35.256 -> kurz
13:28:35.256 -> HID: s
13:28:35.303 -> kurz
13:28:35.303 -> HID: s

Bin gespannt, wie es mit der Hardware des TO aussieht.

BounceTime verändern?

Ansonsten ja, ich hatte ja geschrieben, das ich die die Pullups als Hardware habe.

Möchtest Du den mal mit der Vorlage vergleichen?
Und wenn Du auch Aufbau gemacht hast... :slight_smile:
Ich hab das im mySetup geändert, weil ich nicht wusste, wie er rauskommen will, wenn er die displayTime geändert hat.

Ist nur roh - also nicht so genau hinschaun ...
Das "Booting hab ich im setup auskommentiert :wink:
Mute ist auch mit drin, aber ich lasse den display in der Zeit an.

// Rotary
#include <rotary.h>
Rotary r = Rotary(45, 43);
const byte rotBut = 41;
const byte mutBut = 2;
const byte mutLed = LED_BUILTIN;

const uint32_t bounceTime = 20; // zeit in ms

// LCD
const byte lcdSpalten = 20;
const byte lcdZeilen = 2;

// Inhalt
struct inhalt
{
  const char *name;
  const char *hid;
};

inhalt MyFilter[]
{
  {"Auswahl?", ""}, {"Filter 1", "a"}, {"Filter 2", "s"}, {"Filter 3", "d"}, {"Filter 4", "f"}
};

inhalt MySetup[]
{
  {"Displayzeit", ""}, {"Wlan", "g"}, {"Filternamen", ""}, {"Platzhalter 1", "j"}, {"Platzhalter 2", "k"},
  {"Platzhalter 3", "l"}, {"Platzhalter 4", "q"}, {"Platzhalter 5", "w"}, {"exit", ""},
};

uint32_t displayZeit = 1000UL * 10; // Zeit in ms
uint32_t displayTick = 0;
bool isDisplay = true; // Hilfsvariable


bool isMenu = true;
bool isSetup = !isMenu;
bool isTasteKurz = false;
bool isTasteLang = false;
bool isMute = false;
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  //startSequenz();
  pinMode (rotBut, INPUT);
  pinMode (mutBut, INPUT_PULLUP);
  pinMode (mutLed, OUTPUT);
}

void loop()
{
  if (isMute)
  {
    heartbeat(500);
  }
  else
  {
    if (digitalRead(mutLed)) digitalWrite(mutLed, LOW);
    if (isMenu) myMenu();
    if (isSetup) mySetup();
    getRotaryButton();
  }
  getMute();
  setDisplayLigth();
  if (!isDisplay)
  {isMenu = true; isSetup = false;}
}

void myMenu()
{
  const char displayZeileOben[] = "Filter wählen";
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = 100;
  const uint8_t maxPos = sizeof(MyFilter) / sizeof(inhalt) - 1;
  rotaryPos = getRotary(rotaryPos);
  if (rotaryPos != lastRotaryPos)
  {
    if (rotaryPos > maxPos) rotaryPos = 0;
    else if (rotaryPos < 0) rotaryPos = maxPos;
    lastRotaryPos = rotaryPos;
    Serial.print(F("menu "));
    Serial.println(rotaryPos);
    ausgabe(displayZeileOben, MyFilter[rotaryPos].name);
  }
  if (isTasteKurz)
  {
    sendHid(MyFilter[rotaryPos].hid);
    isTasteKurz = false;
  }
  if (isTasteLang)
  {
    isMenu = false; isSetup = true;
    isTasteLang = false;
    lastRotaryPos = 1000;
  }
  if (!isDisplay) rotaryPos = 0;
}

void mySetup()
{
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = 100;
  const uint8_t maxPos = sizeof(MySetup) / sizeof(inhalt) - 1;
  static int8_t menuPos = 0;
  uint32_t sekunde = 0;
  static bool isNew = false;
  if (menuPos == 0)
  {
    rotaryPos = getRotary(rotaryPos);
    if (rotaryPos != lastRotaryPos)
    {
      if (rotaryPos > maxPos) rotaryPos = 0;
      else if (rotaryPos < 0) rotaryPos = maxPos;
      lastRotaryPos = rotaryPos;
      Serial.println(F("setup "));
      Serial.println(rotaryPos);
      ausgabe(MySetup[rotaryPos].name, "");
    }
  }
  switch (menuPos)
  {
    case 1:
      {
        sekunde = displayZeit / 1000;
        menuPos = setupZahl(sekunde, menuPos);
        if (sekunde < 5) sekunde = 5;
        else if (sekunde > 84600) sekunde = 84600;
        char buf[6] = {'\0'};
        sprintf(buf, "%ld", sekunde);
        ausgabe(MySetup[rotaryPos].name, buf);
        displayZeit = 1000UL * sekunde;
      }
      break;
    case 2:
      // Wlan
      ausgabe(MySetup[rotaryPos].name, " ausgelöst");
      sendHid(MySetup[rotaryPos].hid);
      break;
    case 3:
      // Namen ändern....
      menuPos = setMyName(isNew, menuPos);
      break;
    case 4 ... 8:
      sendHid(MySetup[rotaryPos].hid);
      break;
    case maxPos+1:
      menuPos = 0;
      rotaryPos = 0;
      isMenu = true;
      isSetup = false;
      isTasteKurz = false;
      break;
  }
  if (isTasteKurz)
  {
    if (menuPos == 0)
      menuPos = rotaryPos + 1;
    else
      menuPos = 0;
    isTasteKurz = false;
    isNew = true;
  }
  if (isTasteLang)
  {
    isMenu = true; isSetup = false;
    isTasteLang = false;
  }
  if (!isDisplay)
  {
    menuPos = 0;
    rotaryPos = 0;
  }
}

uint8_t setMyName(bool &myNew, uint8_t menuWert)
{
  if (isTasteLang)
  {
    menuWert = 0;
    isTasteLang = false;
  }
  return menuWert;
}


uint8_t setupZahl(uint32_t &aenderZahl, uint8_t menuWert )
{
  static uint32_t lastZahl = 0;
  aenderZahl = getRotary(aenderZahl);
  if (aenderZahl != lastZahl)
  {
    lastZahl = aenderZahl;
    Serial.println(F("Zahl geändert: "));
    Serial.println(aenderZahl);
  }
  if (isTasteKurz)
  {
    menuWert = 0;
    isTasteKurz = false;
  }
  return menuWert;
}

void sendHid(const char *zeichen)
{
  if (isPrintable(zeichen))
  {
    Serial.print(F("HID: "));
    Serial.println(zeichen);
  }
}

void ausgabe(const char *zeile1, const char *zeile2)
{
  static char lastZeileOben[lcdSpalten] = {'\0'};
  static char lastZeileUnten[lcdSpalten] = {'\0'};
  if (strcmp(lastZeileOben, zeile1))
  {
    memset(lastZeileOben, '\0', lcdSpalten);
    strcpy(lastZeileOben, zeile1);
    Serial.print(F("Zeile 1: "));
    Serial.println(zeile1);
  }
  if (strcmp(lastZeileUnten, zeile2))
  {
    memset(lastZeileUnten, '\0', lcdSpalten);
    strcpy(lastZeileUnten, zeile2);
    Serial.print(F("Zeile 2: "));
    Serial.println(zeile2);
  }
}

void setDisplayLigth()
{
  if (millis() - displayTick > displayZeit && !isMute)
  {
    if (isDisplay)
    {
      Serial.println(F("Display aus!"));
      isDisplay = false;
    }
  }
  else
  {
    if (!isDisplay)
    {
      Serial.println(F("Display an!"));
      isDisplay = true;
    }
  }
}

void getMute()
{
  static uint32_t lastmillis = 0;
  static bool isPressed = false;
  if (!digitalRead(mutBut) && !isPressed)
  {
    isPressed = true;
    displayTick = millis();
    lastmillis = millis();
    isMute = !isMute;
    if (isMute) ausgabe("Mute aktiv", "");
    sendHid("e");
  }
  else if ((millis() - lastmillis > bounceTime) &&
           (digitalRead(mutBut) && isPressed))
  {
    isPressed = false;
  }
}

void getRotaryButton()
{
  static uint32_t lastmillis = 0;
  static bool isPressed = false;
  if (!digitalRead(rotBut) && !isPressed)
  {
    isPressed = true;
    displayTick = millis();
    lastmillis = millis();
  }
  else if ((millis() - lastmillis > bounceTime) &&
           (digitalRead(rotBut) && isPressed))
  {
    if (millis() - lastmillis < 500)
    {
      isTasteKurz = true;
      Serial.println(F("kurz"));
    }
    else
    {
      isTasteLang = true;
      Serial.println(F("lang"));
    }
    isPressed = false;
  }
}

uint32_t getRotary(uint32_t posValue)
{
  unsigned char val = r.process();
  if (val)
  {
    if (val == r.clockwise() && isDisplay)
    {
      Serial.print(F("rechts"));
      posValue++;
    }
    else if (val == r.counterClockwise() && isDisplay)
    {
      Serial.print(F("links"));
      posValue--;
    }
    Serial.println(F(" gedreht"));
    displayTick = millis();
  }
  return posValue;
}

void heartbeat(const uint32_t tik)
{
  static uint32_t lasttik = 0;
  if (millis() - lasttik >= tik)
  {
    lasttik += tik;
    digitalWrite(mutLed, !digitalRead(mutLed));
  }
}
void startSequenz()
{
  uint32_t startTime = millis();
  ausgabe("Willkommen", "");
  while (millis() - startTime < 1500) {}
  startTime = millis();
  ausgabe("Booting", "");
  char zeile2[lcdSpalten] = {'\0'};
  uint8_t pos = 0;
  while (pos < lcdSpalten - 1)
  {
    if (millis() - startTime > 1000)
    {
      displayTick = millis();
      zeile2[pos] = '*';
      ausgabe("Booting", zeile2);
      startTime = millis();
      pos++;
    }
  }
}

bounceTime = 20;

15:05:38.553 -> rechts gedreht
15:05:38.553 -> menu 0
15:05:38.553 -> Zeile 2: Auswahl?
15:05:39.356 -> kurz
15:05:39.409 -> kurz
15:05:41.764 -> rechts gedreht
15:05:41.764 -> menu 1
15:05:41.818 -> Zeile 2: Filter 1

bounceTime = 100;

15:06:47.233 -> rechts gedreht
15:06:47.233 -> menu 2
15:06:47.233 -> Zeile 2: Filter 2
15:06:48.785 -> kurz
15:06:48.885 -> kurz
15:06:50.042 -> rechts gedreht
15:06:50.042 -> menu 3
15:06:50.042 -> Zeile 2: Filter 3

Kurze bounceTime führt zu selteneren Doppelklicks, das verstehe ich gerade nicht :thinking:

Das Drehen geht sicherer als bei meiner italienischen Kaffeemaschine :coffee:

Ich ja. Das hängt mit dem Timing zusammen, was ich mir beim drücken der Taste und setzen derVariable isPressed ausschliesse.
Im Falle des bouncen wird der nicht erkannt und lastmillis bleibt auf den ersten Kontakt stehen.
Wenn die Bedingung da jetzt raus ist, sollte es gehen.

Und hab den Code mal aufgeräumt...

// Rotary
#include <rotary.h>
Rotary r = Rotary(45, 43);
const byte rotBut = 41;
const byte mutBut = 2;
const byte mutLed = LED_BUILTIN;

const uint32_t bounceTime = 20; // zeit in ms

// LCD
const byte lcdSpalten = 20;
const byte lcdZeilen = 2;

// Inhalt
struct inhalt
{
  const char *name;
  const char *hid;
};

inhalt MyFilter[]
{
  {"Auswahl?", ""}, {"Filter 1", "a"}, {"Filter 2", "s"}, {"Filter 3", "d"}, {"Filter 4", "f"}
};

inhalt MySetup[]
{
  {"Displayzeit", ""}, {"Wlan", "g"}, {"Filternamen", ""}, {"Platzhalter 1", "j"}, {"Platzhalter 2", "k"},
  {"Platzhalter 3", "l"}, {"Platzhalter 4", "q"}, {"Platzhalter 5", "w"}, {"exit", ""},
};

uint32_t displayZeit = 1000UL * 10; // Zeit in ms
uint32_t displayTick = 0;
bool isDisplay = true; // Hilfsvariable


bool isMenu = true;
bool isSetup = !isMenu;
bool isTasteKurz = false;
bool isTasteLang = false;
bool isMute = false;
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  //startSequenz();
  pinMode (rotBut, INPUT);
  pinMode (mutBut, INPUT_PULLUP);
  pinMode (mutLed, OUTPUT);
}

void loop()
{
  if (isMute)
  {
    heartbeat(500);
  }
  else
  {
    if (digitalRead(mutLed)) digitalWrite(mutLed, LOW);
    if (isMenu) myMenu();
    if (isSetup) mySetup();
    getRotaryButton();
  }
  getMute();
  setDisplayLight();
  if (!isDisplay)
  {isMenu = true; isSetup = false;}
}

void myMenu()
{
  const char displayZeileOben[] = "Filter wählen";
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = 100;
  const uint8_t maxPos = sizeof(MyFilter) / sizeof(inhalt) - 1;
  rotaryPos = getRotary(rotaryPos);
  if (rotaryPos != lastRotaryPos)
  {
    if (rotaryPos > maxPos) rotaryPos = 0;
    else if (rotaryPos < 0) rotaryPos = maxPos;
    lastRotaryPos = rotaryPos;
    Serial.print(F("menu "));
    Serial.println(rotaryPos);
    ausgabe(displayZeileOben, MyFilter[rotaryPos].name);
  }
  if (isTasteKurz)
  {
    sendHid(MyFilter[rotaryPos].hid);
    isTasteKurz = false;
  }
  if (isTasteLang)
  {
    isMenu = false; isSetup = true;
    isTasteLang = false;
    lastRotaryPos = 100;
  }
  if (!isDisplay) rotaryPos = 0;
}

void mySetup()
{
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = 100;
  const uint8_t maxPos = sizeof(MySetup) / sizeof(inhalt) - 1;
  static int8_t menuPos = 0;
  uint32_t sekunde = 0;
  static bool isNew = false;
  if (menuPos == 0)
  {
    rotaryPos = getRotary(rotaryPos);
    if (rotaryPos != lastRotaryPos)
    {
      if (rotaryPos > maxPos) rotaryPos = 0;
      else if (rotaryPos < 0) rotaryPos = maxPos;
      lastRotaryPos = rotaryPos;
      Serial.println(F("setup "));
      Serial.println(rotaryPos);
      ausgabe(MySetup[rotaryPos].name, "");
    }
  }
  switch (menuPos)
  {
    case 1:
      {
        sekunde = displayZeit / 1000;
        menuPos = setupZahl(sekunde, menuPos);
        if (sekunde < 5) sekunde = 5;
        else if (sekunde > 84600) sekunde = 84600;
        char buf[6] = {'\0'};
        sprintf(buf, "%ld", sekunde);
        ausgabe(MySetup[rotaryPos].name, buf);
        displayZeit = 1000UL * sekunde;
      }
      break;
    case 2:
      // Wlan
      ausgabe(MySetup[rotaryPos].name, " ausgelöst");
      sendHid(MySetup[rotaryPos].hid);
      break;
    case 3:
      // Namen ändern....
      menuPos = setMyName(isNew, menuPos);
      break;
    case 4 ... 8:
      sendHid(MySetup[rotaryPos].hid);
      break;
    case maxPos+1:
      menuPos = 0;
      rotaryPos = 0;
      isMenu = true;
      isSetup = false;
      isTasteKurz = false;
      break;
  }
  if (isTasteKurz)
  {
    if (menuPos == 0)
      menuPos = rotaryPos + 1;
    else
      menuPos = 0;
    isTasteKurz = false;
    isNew = true;
  }
  if (isTasteLang)
  {
    isMenu = true; isSetup = false;
    isTasteLang = false;
  }
  if (!isDisplay)
  {
    menuPos = 0;
    rotaryPos = 0;
  }
}

uint8_t setMyName(bool &myNew, uint8_t menuWert)
{
  if (isTasteLang)
  {
    menuWert = 0;
    isTasteLang = false;
  }
  return menuWert;
}


uint8_t setupZahl(uint32_t &aenderZahl, uint8_t menuWert )
{
  static uint32_t lastZahl = 0;
  aenderZahl = getRotary(aenderZahl);
  if (aenderZahl != lastZahl)
  {
    lastZahl = aenderZahl;
    Serial.println(F("Zahl geändert: "));
    Serial.println(aenderZahl);
  }
  if (isTasteKurz)
  {
    menuWert = 0;
    isTasteKurz = false;
  }
  return menuWert;
}

void sendHid(const char *zeichen)
{
  Serial.print(F("HID: "));
  Serial.println(zeichen);
}

void ausgabe(const char *zeile1, const char *zeile2)
{
  static char lastZeileOben[lcdSpalten] = {'\0'};
  static char lastZeileUnten[lcdSpalten] = {'\0'};
  if (strcmp(lastZeileOben, zeile1))
  {
    memset(lastZeileOben, '\0', lcdSpalten);
    strcpy(lastZeileOben, zeile1);
    Serial.print(F("Zeile 1: "));
    Serial.println(zeile1);
  }
  if (strcmp(lastZeileUnten, zeile2))
  {
    memset(lastZeileUnten, '\0', lcdSpalten);
    strcpy(lastZeileUnten, zeile2);
    Serial.print(F("Zeile 2: "));
    Serial.println(zeile2);
  }
}

void setDisplayLight()
{
  if (millis() - displayTick > displayZeit && !isMute)
  {
    if (isDisplay)
    {
      Serial.println(F("Display aus!"));
      isDisplay = false;
    }
  }
  else
  {
    if (!isDisplay)
    {
      Serial.println(F("Display an!"));
      isDisplay = true;
    }
  }
}

void getMute()
{
  static uint32_t lastmillis = 0;
  static bool isPressed = false;
  if (!digitalRead(mutBut) && !isPressed)
  {
    isPressed = true;
    displayTick = millis();
    lastmillis = millis();
    isMute = !isMute;
    if (isMute) ausgabe("Mute aktiv", "");
    sendHid("e");
  }
  else if ((millis() - lastmillis > bounceTime) &&
           (digitalRead(mutBut) && isPressed))
  {
    isPressed = false;
  }
}

void getRotaryButton()
{
  const uint32_t bounceTime = 60; // zeit in ms
  static uint32_t lastmillis = 0;
  static uint32_t pressTime = 0;
  static bool isPressed = false;
  //  isTasteKurz = false; isTasteLang = false;
  if (!digitalRead(rotBut))
  {
    if (!isPressed)
    {
      pressTime = millis();
      isPressed = true;
    }
    lastmillis = millis();
    displayTick = millis();
  }
  else if (millis() - lastmillis > bounceTime)
  {
    if (isPressed)
    {
      if (millis() - pressTime < 500)
      {
        isTasteKurz = true;
        Serial.println(F("kurz"));
      }
      else
      {
        isTasteLang = true;
        Serial.println(F("lang"));
      }
      isPressed = false;
    }
  }
}

uint32_t getRotary(uint32_t posValue)
{
  unsigned char val = r.process();
  if (val)
  {
    if (val == r.clockwise() && isDisplay)
    {
      Serial.print(F("rechts"));
      posValue++;
    }
    else if (val == r.counterClockwise() && isDisplay)
    {
      Serial.print(F("links"));
      posValue--;
    }
    Serial.println(F(" gedreht"));
    displayTick = millis();
  }
  return posValue;
}
void heartbeat(const uint32_t tik)
{
  static uint32_t lasttik = 0;
  if (millis() - lasttik >= tik)
  {
    lasttik += tik;
    digitalWrite(mutLed, !digitalRead(mutLed));
  }
}
void startSequenz()
{
  uint32_t startTime = millis();
  ausgabe("Willkommen", "");
  while (millis() - startTime < 1500) {}
  startTime = millis();
  ausgabe("Booting", "");
  char zeile2[lcdSpalten] = {'\0'};
  uint8_t pos = 0;
  while (pos < lcdSpalten - 1)
  {
    if (millis() - startTime > 1000)
    {
      displayTick = millis();
      zeile2[pos] = '*';
      ausgabe("Booting", zeile2);
      startTime = millis();
      pos++;
    }
  }
}

Mal sehn, ob nachher noch Zeit bleibt, dann versuch ich mich noch was zu basteln. Vielleicht bekomm ich es ja doch gebaut - und das ganz ohne Display :wink:
Und ich weiss auch wer Schuld ist...

Das ist gut, das Ergebnis noch ohne Tadel:

15:28:57.314 -> Start...Start...
15:28:57.314 -> menu 0
15:28:57.314 -> Zeile 1: Filter wählen
15:28:57.314 -> Zeile 2: Auswahl?
15:29:01.079 -> rechts gedreht
15:29:01.079 -> menu 1
15:29:01.079 -> Zeile 2: Filter 1
15:29:03.587 -> kurz
15:29:03.587 -> HID: a
15:29:04.738 -> rechts gedreht
15:29:04.738 -> menu 2
15:29:04.738 -> Zeile 2: Filter 2
15:29:05.855 -> kurz
15:29:05.855 -> HID: s
15:29:07.059 -> rechts gedreht
15:29:07.059 -> menu 3
15:29:07.059 -> Zeile 2: Filter 3
15:29:08.162 -> kurz
15:29:08.162 -> HID: d
15:29:09.165 -> rechts gedreht
15:29:09.212 -> menu 4
15:29:09.212 -> Zeile 2: Filter 4
15:29:10.416 -> kurz
15:29:10.416 -> HID: f
15:29:11.319 -> rechts gedreht
15:29:11.319 -> menu 0
15:29:11.319 -> Zeile 2: Auswahl?
15:29:12.322 -> kurz
15:29:12.322 -> HID: 
15:29:13.178 -> rechts gedreht
15:29:13.178 -> menu 1
15:29:13.178 -> Zeile 2: Filter 1
15:29:14.583 -> kurz
15:29:14.583 -> HID: a
15:29:15.793 -> rechts gedreht
15:29:15.793 -> menu 2
15:29:15.793 -> Zeile 2: Filter 2
15:29:16.981 -> kurz
15:29:16.981 -> HID: s
15:29:17.730 -> rechts gedreht
15:29:17.730 -> menu 3
15:29:17.730 -> Zeile 2: Filter 3
15:29:18.686 -> kurz
15:29:18.686 -> HID: d
15:29:19.489 -> rechts gedreht
15:29:19.489 -> menu 4
15:29:19.489 -> Zeile 2: Filter 4
15:29:20.392 -> kurz
15:29:20.392 -> HID: f
15:29:21.442 -> rechts gedreht
15:29:21.442 -> menu 0
15:29:21.442 -> Zeile 2: Auswahl?
15:29:22.398 -> kurz
15:29:22.398 -> HID: 
15:29:23.201 -> rechts gedreht
15:29:23.201 -> menu 1
15:29:23.201 -> Zeile 2: Filter 1
15:29:24.552 -> kurz
15:29:24.552 -> HID: a
15:29:25.408 -> rechts gedreht
15:29:25.408 -> menu 2
15:29:25.408 -> Zeile 2: Filter 2
15:29:26.358 -> kurz
15:29:26.358 -> HID: s
15:29:27.160 -> rechts gedreht
15:29:27.160 -> menu 3
15:29:27.160 -> Zeile 2: Filter 3
15:29:28.164 -> kurz
15:29:28.164 -> HID: d
15:29:28.966 -> rechts gedreht
15:29:28.966 -> menu 4
15:29:28.966 -> Zeile 2: Filter 4
15:29:29.922 -> kurz
15:29:29.922 -> HID: f
15:29:30.672 -> rechts gedreht
15:29:30.672 -> menu 0
15:29:30.672 -> Zeile 2: Auswahl?
15:29:32.176 -> kurz
15:29:32.229 -> HID: 
15:29:34.584 -> rechts gedreht
15:29:34.584 -> menu 1
15:29:34.584 -> Zeile 2: Filter 1
15:29:35.662 -> kurz
15:29:35.662 -> HID: a
15:29:36.411 -> rechts gedreht
15:29:36.411 -> menu 2
15:29:36.411 -> Zeile 2: Filter 2
15:29:37.615 -> kurz
15:29:37.615 -> HID: s
15:29:38.317 -> rechts gedreht
15:29:38.317 -> menu 3
15:29:38.317 -> Zeile 2: Filter 3
15:29:39.220 -> kurz
15:29:39.220 -> HID: d
15:29:40.076 -> rechts gedreht
15:29:40.076 -> menu 4
15:29:40.076 -> Zeile 2: Filter 4
15:29:40.925 -> kurz
15:29:40.925 -> HID: f
15:29:41.527 -> rechts gedreht
15:29:41.527 -> menu 0
15:29:41.527 -> Zeile 2: Auswahl?
15:29:42.383 -> kurz
15:29:42.383 -> HID: 
15:29:43.032 -> rechts gedreht
15:29:43.032 -> menu 1
15:29:43.032 -> Zeile 2: Filter 1
15:29:43.988 -> kurz
15:29:43.988 -> HID: a
15:29:49.605 -> kurz

Weitermachen :slightly_smiling_face:


Wenn Du es Dir etwas einfacher machen möchtest, die MobaTools haben kurz, lang und doppelt bei den Tasten "eingebaut".

Nicht vergessen, letztlich soll sowas übertragen werden:

{0, 0,  8, 40, 0, 0, 0, 0}

Was da nachher übertragen wird, ist mir eigentlich egal.
Er will ein Zeichen gefolgt von \r\n senden.
Wie das gelöst wird kann m.E. dann in der Funktion sendHid() zusammengebaut und ggfls. auch aufgefüllt werden. Zuerst muss das setzen der jeweiligen Positionen zuverlässig klappen.
Dann die Abhängigkeiten auf Display an/aus und dann der Inhalt dort.

Ich glaub die TastenFunktion reicht so - ich hatte das vorhin auf 20ms fürs debounce gesetzt und denke, das ist i.O. - es geht ja nur um lang oder kurz drücken.
Wenn es dann später auch noch mehr werden sollen, kann das machen wer will :wink:
Da ich im mySetup() nur noch das editieren der Bezeichner hätte, mal schaun...

Zeichen "a"+"Enter" über HID versenden soll den Tastencode für "a" verschicken, nicht das Zeichen. Zumindest habe ich das so in Erinnerung, kann mich täuschen :roll_eyes:

Mich erinnert das an das Thema Lichtpultsoftware Fernbedienung mit Drehencoder und Programmierbaren Tasten über USB .

Stimmt, da war was... :innocent:
Aber geht doch.
Ich übergebe das Zeichen und der Rest wird in der Funktion zusammengebaut.
Ich für mich will nur sicherstellen, das immer nur ein Zeichen gesendet wird - bei MUTE oder WLAN würde das sonst schlecht aussehen.
Ich schau morgen mal, ob sich das mit doppelten Zeichen wiederholen lässt - wenn nicht, denke ich, das es ok geht.

Wenn das funktioniert, würde mir - wenn mich nicht alles täuscht - nur noch das Ändern der Bezeichner fehlen.

Frage: Wenn das *char im struct const ist, lässt sich das inhalt MyFilter doch garnicht mehr ändern? Oder?

Dann mach es doch variabel, dann kann der Text geändert werden.

Dann hilf mir mal
Nein natürlich nicht - Blödmann wie ich bin... Ich muss natürlich sagen, wie groß das Feld wird...

   char name[lcdSpalten];

Na denn...

Eher lcdSpalten + 1 wegen des Zeichenkettenabschlusses.

War ja nur nen "wie es ohne Fehlermeldung geht"
...
Na mal abwarten was unser TO nach #27 so sagt...
Vielleicht hat sich ja auch schon wer gefunden, der ihm das gebaut hat. - Fertig bekomm ich das nicht.

Ne wars nicht.
Ich hab das lange drücken damit unterschlagen.

Ich hab mal den Code nochmal umgeschrieben - damit geht jetzt kurz und lang.
Wenn Du Lust hast - dann einmal das Tabellenblatt ablaufen.

Kurze Antwort nach 2x 12 Stunden Meeting :roll_eyes:
Nein, ich habe noch niemanden gefunden der mir die SW entwickeln will..

Werde ich auf jeden Fall ausprobieren!

Habe ich, aber erst später am Tag.

Ich habe ein Oled Display, ich hatte im alten Thread schon mal den Tipp bekommen, dass man das Display auch einfach "Leer" schreiben kann.