Weiterentwicklung einer Software zur Funktionsreife

Das ist schick :wink:
Ich hab mich aber dazu entschieden, die Veränderbarkeit der Einträge mit dem Drehencoder nicht zu machen - bzw. wenn dann als Letztes.
Der Punkt ist noch drin - aber wenn Du deine Texte änderst, willst die auch speichern, sonst gehn die ja verloren beim ausschalten / reset. Da kommt dann noch der EEprom dazu ;(

Hm.. ja, kann man.
Ob das sinnvoll ist, muss man sehen. Ich bau das mal bis heute abend noch, das Du die Ausgabe auf dem SerMon bekommst, das er 2 Leerzeilen schreibt.
Wie gesagt, ich mach das hier nur, weil ich zeigen will, das man sowas auch nur mit dem SerMon bauen kann - darum ist der Code auch etwas größer, da ich die Ausgabe immer nur auf eine begrenzen muss :wink:
Na denn...

Alles gut - ich will nur wissen, ob ich mit meinem Gedankengang richtig bin...

Sag mal, das Teil ist 20x2. Du hattest doch die joyit-lib schon am machen - was hat denn da nicht gepasst?

das Display hat nämlich einen .off modus. (Datenblatt)
Der wird von der lib auch bedient.

Ich find das mit der Leerzeile unsinnig.

Ich jetzt auch, danke für die Links.

Möglicherweise kommt die "Leerzeile" von mir, weil ich von den mir bekannten OLEDs ausgegangen bin, die man nicht ausschalten kann, nur überschreiben. Das verwendete ist aber "HD44780-LIKE" mit SPI-Schnittstelle. Wenn es da ein OFF gibt, dann sollte man den auch verwenden :slightly_smiling_face:

Dann ist das der aktuelle Stand - aus dem ändern der Bezeichner kommst nur mit nem langen klick raus.
Die "Platzhalter" kurzer klick -> sendet dauerhaft -> kurzer Klick Ende
Alles andere dürfte stimmen. incl. Mute-Button.
[edit] StartSequenz noch für @fftransformation aktiviert :slight_smile: [/edit]

// 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;

const char chars[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz1234567890"};

// Inhalt
struct inhalt
{
  char name[lcdSpalten];
  char hid[2];
};

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;
bool isWlan = 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()
{
  const uint8_t maxPos = sizeof(MySetup) / sizeof(inhalt) - 1;
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = maxPos + 1;
  static int8_t menuPos = 0;
  uint32_t sekunde = 0;
  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
      isWlan = !isWlan;
      sendHid(MySetup[rotaryPos].hid);
      if (isWlan)
        ausgabe(MySetup[rotaryPos].name, " ausgelöst");
      else
        ausgabe(MySetup[rotaryPos].name, " gestoppt");
      menuPos = 0;
      break;
    case 3:
      // Namen ändern....
      menuPos = setMyName(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;
  }
  if (isTasteLang)
  {
    isMenu = true; isSetup = false;
    isTasteLang = false;
  }
  if (!isDisplay)
  {
    menuPos = 0;
    rotaryPos = 0;
  }
}

uint8_t setMyName(uint8_t menuWert)
{
  uint8_t maxPos = 10;
  //static byte pos = 0;
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = maxPos + 1;
  static int8_t menuPos = 0;
  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, "");
    }
  }
  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(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(lastZeileOben);
  }
  if (strcmp(lastZeileUnten, zeile2))
  {
    memset(lastZeileUnten, '\0', lcdSpalten);
    strcpy(lastZeileUnten, zeile2);
    Serial.print(F("Zeile 2: "));
    Serial.println(lastZeileUnten);
  }
}

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()
{
  static uint32_t lastmillis = 0;
  static uint32_t pressTime = 0;
  static bool isPressed = 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++;
    }
  }
}

Ehrlich gesagt kann ich mich an den joyit part überhaupt nicht erinnern...
Ich hatte auf jeden Fall schnell auf den 4 Bit Mode ungeswitcht, das funktionierte auch einwandfrei:

#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);

int Variable = 1234;

void setup() {
  lcd.begin(20, 2);
  lcd.print("12345678901234567890");
}
void loop() {
  lcd.setCursor(7, 1);
  lcd.print(Variable);
}

Das sollte nur als Gedächtnisstütze dienen und/ oder zur Vereinfachung sein...

Boa, via SPI hatte ich das nie gescheit zum laufen gebracht, die Zeichen waren einfach über die Digit-Blöcke der Oled random verteilt.

Musst ja nicht.
Der kann ja 4-bit 8080 und 4-bit 6800.

Also nochmal zurück in den alten Thread und nachschauen, was mit der joy-IT-Vorgabe war.
Die lib gibt m.E. alles her, was Du brauchst.

Zur Gedächtnisauffrischung schau mal hier:

Mein Vorschlag: Wir nutzen die Bibliothek NoiascaLiquidCrystal.h zum Testen, wir sparsam mit I²C, Du eventuell paralllel mit vielen Leitungen oder Du hast noch einen PCF8574 rumliegen. Der Umstieg auf die Bibliothek iwi_SPI_RS0010 und SPI dürfte für Dich nicht so schwierig sein :slightly_smiling_face:

?
er benutzt doch 4 bit - die IST0010 auch. Da ist kein SPI drin.
Ich will wissen, warum die IST0010 nicht geht, oder was sie ihn nicht machen lässt. Dann haben wir gleiche Möglichkeiten, da die mit der LyquidCrystal Controller-kompatibel ist.

Ja, sieht gut aus :smiley:

Aber wie Du weißt, schaue ich genau:

  1. Ich kann "Auswahl?" nirgendwo in MenüCode finden.
  2. Das Increment der Displayzeit funktioniert nicht. Ich drehe am Encoder und nichts ändert sich. Innerhalb der Menüpunkte funktioniert Increment und Decrement. Ursache konnte ich noch nicht entdecken.
  3. Wenn ich die veränderte Displayzeit mit einem kurzen Klick bestätige, bleibt die Zeit weiter angezeigt. Beim Drehen geht es aber zu WLAN. Da fände ich es besser, wenn die Anzeige verschwindet.

Mein Testprogramm für 20x4 LCD an I²C, aber nur zwei Zeilen genutzt:

#include <Wire.h>
#include <NoiascaLiquidCrystal.h>        // use the library downloaded from https://werner.rothschopf.net/202009_arduino_liquid_crystal_intro.htm/
#include <NoiascaHW/lcd_PCF8574.h>       // include the proper IO interface
LiquidCrystal_PCF8574 lcd(0x27, 20, 4);  // create lcd object - with support of special characters

// 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;

const char chars[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz1234567890"};

// Inhalt
struct inhalt
{
  char name[lcdSpalten];
  char hid[2];
};

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;
bool isWlan = false;

void setup()
{
  Wire.begin();                        // start I2C library
  lcd.begin();                         // initialize the LCD
  lcd.backlight();                     // turn on backlight

  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()
{
  const uint8_t maxPos = sizeof(MySetup) / sizeof(inhalt) - 1;
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = maxPos + 1;
  static int8_t menuPos = 0;
  uint32_t sekunde = 0;
  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
      isWlan = !isWlan;
      sendHid(MySetup[rotaryPos].hid);
      if (isWlan)
        ausgabe(MySetup[rotaryPos].name, " ausgelöst");
      else
        ausgabe(MySetup[rotaryPos].name, " gestoppt");
      menuPos = 0;
      break;
    case 3:
      // Namen ändern....
      menuPos = setMyName(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;
  }
  if (isTasteLang)
  {
    isMenu = true; isSetup = false;
    isTasteLang = false;
  }
  if (!isDisplay)
  {
    menuPos = 0;
    rotaryPos = 0;
  }
}

uint8_t setMyName(uint8_t menuWert)
{
  uint8_t maxPos = 10;
  //static byte pos = 0;
  static int8_t rotaryPos = 0;
  static int8_t lastRotaryPos = maxPos + 1;
  static int8_t menuPos = 0;
  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, "");
    }
  }
  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(char *zeichen)
{
  Serial.print(F("HID: "));
  Serial.println(zeichen);
}

void ausgabe(const char *zeile1, const char *zeile2)
{
  char buf[21] = {'\0'};
  snprintf( buf, sizeof(buf), "%s                    ", zeile1 );
  lcd.setCursor(0, 0);
  lcd.print(buf);
  snprintf( buf, sizeof(buf), "%s                    ", zeile2 );
  lcd.setCursor(0, 1);
  lcd.print(buf);

  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(lastZeileOben);
  }
  if (strcmp(lastZeileUnten, zeile2))
  {
    memset(lastZeileUnten, '\0', lcdSpalten);
    strcpy(lastZeileUnten, zeile2);
    Serial.print(F("Zeile 2: "));
    Serial.println(lastZeileUnten);
  }
}

void setDisplayLight()
{
  if (millis() - displayTick > displayZeit && !isMute)
  {
    if (isDisplay)
    {
      Serial.println(F("Display aus!"));
      lcd.setBacklight(0);
      isDisplay = false;
    }
  }
  else
  {
    if (!isDisplay)
    {
      Serial.println(F("Display an!"));
      lcd.setBacklight(255);
      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 uint32_t pressTime = 0;
  static bool isPressed = 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++;
    }
  }
}

Das ist der Haken, den ich schon weiter oben beschrieb - der unlogisch ist.
Du kannst ja nur drehen und Menupunkte auswählen.
Wenn Du aus dem "Hauptmenu" einmal LANG drückst, kommst ins setup. Erster Eintrag ist die Displayzeit.
einmal kurz drücken - Wert ändern - kurz drücken, kommst wieder zurück.
Der Wert wird während des drehens schon geändert - ich spare mir ein "Speichern beim zurückkommen"

Ich hatte nur sie SPI von Joy-it probiert, aber ich kann natürlich gerne die 4 Bit Vorgabe von Joy testen.

@my_xy_projekt
Ich bin da gar nicht mehr drauf gekommen, dass das PDF von Joy-it war :slight_smile:

Ja bitte.
Du hast einen funktionierenden Aufbau - der muss nach dem Austausch der lib genauso funktionieren.

Punkt 2 kannst Du streichen, lag an meinem Testprogramm. So geht es:

void ausgabe(const char *zeile1, const char *zeile2)
{
  char buf[21] = {'\0'};
  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(lastZeileOben);
    snprintf( buf, sizeof(buf), "%s                    ", zeile1 );
    lcd.setCursor(0, 0);
    lcd.print(buf);
  }
  if (strcmp(lastZeileUnten, zeile2))
  {
    memset(lastZeileUnten, '\0', lcdSpalten);
    strcpy(lastZeileUnten, zeile2);
    Serial.print(F("Zeile 2: "));
    Serial.println(lastZeileUnten);
    snprintf( buf, sizeof(buf), "%s                    ", zeile2 );
    lcd.setCursor(0, 1);
    lcd.print(buf);
  }
}

Zu 3. Da fehlt mir das Löschen der zweiten Zeile:

gedreht
Display an!
rechts gedreht
menu 1
Zeile 2: Filter 1
lang
setup
0
Zeile 1: Displayzeit
Zeile 2:
kurz
Zahl geändert:
10
Zeile 2: 10
rechts gedreht
Zahl geändert:
11
Zeile 2: 11
rechts gedreht
Zahl geändert:
12
Zeile 2: 12
kurz
Zeile 2: << das Löschen der 2. Zeile fehlt mir, weil man ja eine Ebene höher kommt
rechts gedreht
setup
1
Zeile 1: Wlan
Zeile 2:
rechts gedreht
setup
2
Zeile 1: Filternamen
lang
menu 1
Zeile 1: Filter wählen
Zeile 2: Filter 1

  1. Ginge auch case0:?
  switch (menuPos)
  {
    case 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, "");
      }
      break;
1 Like

Aah.. Du machst das schon mit Display!
Ich mach das nur auf dem SerMon. Ich hab noch keine gemeinsame Grundlage für Display.
Wenn das Serial ausgegeben läuft, würde ich die Ausgabe wieder zentrieren. Dazu gehört dann in der Ausgabe noch einwenig Rechnerei rein :wink:

Naja, da bleibt der Wert stehen. Der gehört zur ersten Zeile. Weg muss er, wenn sich der Rotary dreht. Schau ich drauf.

Ja.. Da bin ich auch am überlegen.
Ich trau dem noch nicht ganz, das der Einstieg so bleibt.

Danke fürs drauf schaun!
:grinning:

Da kann ich es mir besser vorstellen.

Da schlage ich NoiascaLiquidCrystal als gemeinsame Bibliothek vor. Später kann der TO auf was auch immer wechseln.

Anstelle "Filter 2" einfach " Filter 2 " erspart Rechnerei :slightly_smiling_face:

aber kostet Speicher :wink:
Und Zahlen in der Mitte müssen ja dann doch irgendwie gebaut werden :wink:

na mal sehn, wie das aussieht, wenn der 4bitter durchgeht. Dann wird auf Display gebaut und das serielle runtergekürzt.

Ich hab zumindest geschafft, das komplett ohne zu bauen - war ne Herausforderung, aber geht.
Beweis erbracht :wink:

Wenn der Text änderbar sein soll, brauchst Du doch sowieso die maximal möglichen 21 Zeichen. Oder?

Das las ich mal noch immer aussen vor...
Na denne...

Die geht genau so wie die LiquidCrystal.h (eher etwas stabiler) ... aber das "shifting" bei der IST0010 tut nichts bewirken:

#include <IST0010_OLED16x2.h>

IST0010_OLED16x2 oled(/* RS: */ 4, /* Enable: */ 5, /* RW: */ 6 /* , characterset: default EUROPEAN_I, character height: default 8*/);

void setup() {
    oled.init_4bit_6800(/* D4: */ 7, /* D5: */ 8, /* D6: */ 9, /* D7 */ 10);

    oled.print("Joy-IT_8901234567890");
    oled.setCursor(0,1);
    oled.print("Joy-IT_8901234567890");
    delay (2000);
    oled.clear();

    oled.firstPosition();
    oled.blinkingCursor();
    delay(2000);
    oled.deactivateCursor();

    oled.shiftDisplay(Direction::RIGHT);
    oled.shiftDisplay(Direction::RIGHT);
    oled.print("shifting");
    delay(5000);

    oled.shiftDisplay(Direction::LEFT);
    oled.shiftDisplay(Direction::LEFT);
    oled.clear();
    oled.firstPosition();
    oled.turnOff();
}

void loop() {
    //nothing
}