Drehencoder (Rotary Encoder) mehrere Werte eingeben

Hallo zusammen, Ich möchte mit einem Drehencoder (Rotary Encoder KY-040) nacheinander 4 Werte beim Programmstart eingeben.

Ich hätte mir das so vorgestellt:

Programmstart
1 Wert am Drehregler einstellen (am OLED Display ablesbar) und mit dem integrierten Taster bestätigen
2 Wert einstellen und bestätigen
3. Wert .....
4. Wert ....
und ab hier dann mit den eingestellten Werten weiter.

Der Regler funktioniert soweit einwandfrei bei einem Beispielprogramm, wo der Wert nur im Seriellen Monitor angezeigt wird. Hab leider keine Idee wie ich das jetzt umbauen könnte, um die 4 Parameter nacheinander einzustellen. Könnt Ihr mir da Bitte einen kleinen schubs in die richtige Richtung geben. Oder brauche ich dafür 4 einzelne Regler?

Ich bin noch sehr neu beim Thema Arduino und habe noch nicht viel mehr als Totorials und eine kleine automatische Bewässerung gemacht. Finde das ganze aber unheimlich interessant und möchte da noch etwas mehr machen.

Schon mal vielen Dank für eure Hilfe
Syndi

Array mit 4 Elementen. Bei jeder Bestätigung index um eins erhöhen.
Sind die 4 Werte eingetragen zum rest des Programms "springen"
Grüße Uwe

Im setup()? dann musst Du auf den ersten Tastendruck warten,
dann befüllst den Wert und schliesst mit Tastendruck ab.
Dann den nächsten befüllt etc. bis alle 4 voll sind.
Zeig mal Deinen Einstieg, damit man etwas hat auf das man aufbauen kann.

ich habe leider keine Kristallkugel in der ich deinen Beispielcode sehen kann.

drei Schritte um den Code schön als code formatiert zu posten:

In der Arduino-IDE

  1. Tastenkombination Ctrl-T drücken um den Code zu formatieren
  2. Rechtsklick mit der Maus und Option für Forum kopieren anklicken
  3. Tastenkombination Ctrl-V drücken um den Code samt code-tags in ein posting einzufügen

vgs

Entschuldigung, ich bin wirklich noch ein absoluter Anfänger. habe bis jetzt leider nur das Beispielprogramm und versucht den Wert abzugreifen, aber leider bekomme ich dann immer einen Fehler.

#include <Encoder.h>    // Verwendung der  Bibliothek 

const int CLK = 4;      // Definition der Pins. CLK an D6, DT an D5.
const int DT = 3;
const int SW = 2;       // Der Switch wird mit Pin D2 Verbunden. ACHTUNG : Verwenden Sie einen interrupt-Pin!
long altePosition = -999;  // Definition der "alten" Position (Diese fiktive alte Position wird benötigt, damit die aktuelle Position später im seriellen Monitor nur dann angezeigt wird, wenn wir den Rotary Head bewegen)

Encoder meinEncoder(DT, CLK); // An dieser Stelle wird ein neues Encoder Projekt erstellt. Dabei wird die Verbindung über die zuvor definierten Varibalen (DT und CLK) hergestellt.


void setup()   // Beginn des Setups

{
  Serial.begin(9600);

  pinMode(SW, INPUT);   // Hier wird der Interrupt installiert.

  attachInterrupt(digitalPinToInterrupt(SW), Interrupt, CHANGE); // Sobald sich der Status (CHANGE) des Interrupt Pins (SW = D2) ändern, soll der Interrupt Befehl (onInterrupt)ausgeführt werden.
}


void loop()

{

  long neuePosition = meinEncoder.read();  // Die "neue" Position des Encoders wird definiert. Dabei wird die aktuelle Position des Encoders über die Variable.Befehl() ausgelesen.

  if (neuePosition != altePosition)  // Sollte die neue Position ungleich der alten (-999) sein (und nur dann!!)...
  {
    altePosition = neuePosition;
    Serial.println(neuePosition);      // ...soll die aktuelle Position im seriellen Monitor ausgegeben werden.
  }

}


void Interrupt() // Beginn des Interrupts. Wenn der Rotary Knopf betätigt wird, springt das Programm automatisch an diese Stelle. Nachdem...

{
  Serial.println("Switch betaetigt"); //... das Signal ausgegeben wurde, wird das Programm fortgeführt.

}

Was für Fehler?
Bei mir kompiliert sauber

Wenn ich versuche, das Programm für mich anzupassen, dann klappt es nicht mehr.
Das war bis jetzt mein bester Versuch, es läuft, aber ich kann keine Werte mehr einstellen. Im seriellen Monitor läuft nur noch Zeit 1 bis 4 immer ganz schnell durch.

#include <Encoder.h>    // Verwendung der  Bibliothek 

const int CLK = 4;      // Definition der Pins. CLK an D6, DT an D5.
const int DT = 3;
const int SW = 2;       // Der Switch wird mit Pin D2 Verbunden. ACHTUNG : Verwenden Sie einen interrupt-Pin!
long altePosition = -999;  // Definition der "alten" Position (Diese fiktive alte Position wird benötigt, damit die aktuelle Position später im seriellen Monitor nur dann angezeigt wird, wenn wir den Rotary Head bewegen)

Encoder meinEncoder(DT, CLK); // An dieser Stelle wird ein neues Encoder Projekt erstellt. Dabei wird die Verbindung über die zuvor definierten Varibalen (DT und CLK) hergestellt.

int Zeit1 = 0;
int Zeit2 = 0;
int Zeit3 = 0;
int Zeit4 = 0;

int Index = 0;

void setup()   // Beginn des Setups

{
  Serial.begin(9600);

  pinMode(SW, INPUT);   // Hier wird der Interrupt installiert.

  attachInterrupt(digitalPinToInterrupt(SW), Interrupt, CHANGE); // Sobald sich der Status (CHANGE) des Interrupt Pins (SW = D2) ändern, soll der Interrupt Befehl (onInterrupt)ausgeführt werden.
}


void loop()

{
  Serial.print("Zeit1:");
  Serial.println(Zeit1);
  Serial.print("Zeit2:");
  Serial.println(Zeit2);
  Serial.print("Zeit3:");
  Serial.println(Zeit3);
  Serial.print("Zeit4:");
  Serial.println(Zeit4);

  long neuePosition = meinEncoder.read();  // Die "neue" Position des Encoders wird definiert. Dabei wird die aktuelle Position des Encoders über die Variable.Befehl() ausgelesen.

  if (neuePosition != altePosition)  // Sollte die neue Position ungleich der alten (-999) sein (und nur dann!!)...
  {
    altePosition = neuePosition;
    Serial.println(neuePosition);      // ...soll die aktuelle Position im seriellen Monitor ausgegeben werden.
  }

}


void Interrupt() // Beginn des Interrupts. Wenn der Rotary Knopf betätigt wird, springt das Programm automatisch an diese Stelle. Nachdem...
{

  if (Index == 0 )
  {
    Zeit1 = altePosition;
    Index = ++Index;
  }

  if (Index == 1 )
  {
    Zeit2 = altePosition;
    Index = ++Index;
  }

  if (Index == 2 )
  {
    Zeit3 = altePosition;
    Index = ++Index;
  }

  if (Index == 3 )
  {
    Zeit4 = altePosition;
    Index = ++Index;
  }

  Serial.println("Switch betaetigt"); //... das Signal ausgegeben wurde, wird das Programm fortgeführt.

}

Denk mall drüber nach was macht Arduino im loop.
Dan haste deine Antwort warum das so ist :wink:

prima das du den Demo-Sketch als code-section gepostet hast.

Als Anfänger kann man das nicht wissen: Es gibt eine Menge Demo-Codes online die diverse grobe Schnitzer enthalten.

Bei diesem Democode besteht der grobe Schnitzer darin, dass da in einer Interruptroutine auf die serielle Schnittstelle Daten ausgegeben werden.

In so einem Demoprogramm mag das gerade noch gut gehen. Sobald der Code darüber hinausgeht sind da Probleme quasi "vorprogrammiert"

OK jetzt sollte ich darauf zu sprechen kommen wie macht man es besser.
du möchtest das auf einem OLED-Display der sich ändernde Zahlenwert ausgeben wird.
Datenausgabe auf einem LED-Display dauert (vergleichsweise) lange weil da so viele Pixel übertragen werden müssen. Das verträgt sich eher nicht mit einer Encoderabfrage die polling macht.
Polling meint, dein Hauptprogramm muss mit hoher Geschwindigkeit die Schaltkontakte des Drehencoders abfragen um keine Impulse zu verpassen.

Den Taster kann man per Polling abfragen, weil ein Tastendruck wenigstens eine halbe Sekunde lang ist.

Ich empfehle eine library die die beiden Encoderkanäle per Interrupt auswertet.
NewEncoder. Die library NewEncoder kann man nicht über den library-manager installieren sondern muss sie als ZIP-library hinzufügen
Hier ist eine Anleitung mit vielen Screenshots die erklärt wie man das macht

Die NewEncoder-library bietet

  • einstellbare Unter- und Obergrenze für den Zahlenwert
  • Zahlenwert auf dem der Encoder steht auch während das Programm läuft neu setzen
  • einfache Abfrage des Zahlenwerts zusätzlich Abfrage der Drehrichtung

hier ist ein erster Demo-Code der zeigt wie man den Wert abfragen kann und wie Drehrichtungsabfrage funktioniert

#include "Arduino.h"
#include "NewEncoder.h"

const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal = -20;
const int maxVal =  20;
const int startVal = 0;

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  NewEncoder::EncoderState myCurrentEncoderState;

  // store actual values into variable myCurrentEncoderState
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;


      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

Um den Button eines Encoders abzufragen muss man eigenen Code hinzufügen
Das könnte ein erster Schritt sein, das zu Programmieren
vgs

Ausnahmsweise Code mal als Bild damit die grafische Ergänzung im Bild ist

Die Befehle in der rosa Schleife werden die ganze Zeit wiederholt.
Das ist Sinn und Zweck der function loop()

Der serielle Monitor ist arbeitet nicht wie ein Bildschirm sondern eher wie ein Kassenbondrucker
Immer wenn Zeichen empfangen werden drucken
Wenn ein Befehl "neue Zeile" kommt "Papier" etwas hochschieben

Beim seriellen Monitor sollte man nur dann etwas ausgeben wenn sich irgendwo ein Zahlenwert geändert hat.

Dazu dient diese If-Bedinung:

if (neuePosition != altePosition)  // Sollte die neue Position ungleich der alten (-999) sein (und nur dann!!)...
  {
    altePosition = neuePosition; // Variable altePosition updaten damit die obige If-Bedingung false wird
    Serial.println(neuePosition);      // ...soll die aktuelle Position im seriellen Monitor ausgegeben werden.
  }

Das ist in meinem Democode genauso

// if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;

.
.
Deine Zeilen

  Serial.print("Zeit1:");
  Serial.println(Zeit1);
  Serial.print("Zeit2:");
  Serial.println(Zeit2);
  Serial.print("Zeit3:");
  Serial.println(Zeit3);
  Serial.print("Zeit4:");
  Serial.println(Zeit4);

werden ohne Bedingung bei jedem Schleifendurchlauf ausgegeben.

Jetzt ist erst einmal die Frage was man denn dann sinnvollerweise ausgeben sollte

So hier kommt ein Demo-Code der den seriellen Monitor durch einen Trick zum "statischen" Bildschirm macht.
Alle 0,2 Sekunden
Durch die Ausgabe von 50 Leerzeilen die bisherige Ausgabe aus dem sichtbaren Bereich schieben und dann neu ausgeben. Mit nicht-blockierendem Timing damit loop() für das Pollen des Encoders schnell genug durchläuft.

Das Encoder-Button drücken ist entprellt.
Die vier Zeiten werden in einem Array gespeichert.

Achtung der Encoderbutton ist auf IO-pin 4. Für eine Buttonabfrage braucht man nur ganz selten einen interrupt.

#include <Encoder.h>    // Einbinden der Bibliothek 

const int CLK = 2;      
const int DT = 3;
const int SW = 4;       
long altePosition = -999;  // Definition der "alten" Position (Diese fiktive alte Position wird benötigt, damit die aktuelle Position später im seriellen Monitor nur dann angezeigt wird, wenn wir den Rotary Head bewegen)

Encoder meinEncoder(DT, CLK); 

int Zeit[4] = {0, 0, 0, 0}; // array mit 4 Elementen Indexzahlen 0 bis 3
/*
  Zeit[0] entspricht Zeit1
  Zeit[1] entspricht Zeit2
  Zeit[2] entspricht Zeit3
  Zeit[3] entspricht Zeit4
*/
int Index = 0;

unsigned long MyPrintTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 13;

long neuePosition;
byte myButtonState;
byte lastMyButtonState;

#define pressed LOW
#define released HIGH


void setup() {
  Serial.begin(115200);
  Serial.println( F("Setup-Start") );
  PrintFileNameDateTime();

  // internen Pullup-Widerstand aktivieren für EINDEUTIGE Schaltzustände
  pinMode(SW, INPUT_PULLUP); 
}


// loop MUSS schnell durchlaufen werden damit alle Schaltimpulse
// des Encoders erfasst werden. 
// während die Encoderabfrage aktiv ist ist die Verwendung von delay()
// VERBOTEN!! Wenn man doch delay() verwendet gehen Encoder-Impulse verloren

void loop() {
  BlinkHeartBeatLED(OnBoard_LED, 250);

  neuePosition = meinEncoder.read();  // Die "neue" Position des Encoders wird definiert. Dabei wird die aktuelle Position des Encoders über die Variable.Befehl() ausgelesen.
  // mein Encoder zählt immer gleich 4 weiter deshalb geteilt durch 4  
  neuePosition = neuePosition / 4;    

  // ATTENTION !" the line below must be REPEATED called very fast /
  // very often to make it work !
  manageButtonPresses();

  // NICHT-blockierendes Timing = loop läuft superschnell im Kreis
  if ( TimePeriodIsOver(MyPrintTimer, 200) ) { // Prüfe ob 200 Millisekunden vergangen sind
    // wenn WIRKLICH 200 Millisekunden vergangen sind
    printZeit1_4();
  }
}


// *.ino-Dateiname, Datum und Uhrzeit des Compilierens ausgeben
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}


void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}


void printZeit1_4() {

  // Trick um den seriellen Monitor wie eine LCD-Anzeige zu betreiben
  for (int i = 0; i < 50; i++) { // 50 mal
    Serial.println();            // leere Zeile ausgeben
  }
  // Effekt: die folgenden Zeilen stehen immer am unteren Bildschirmrand
  // weil die zuvor ausgegebenen Zeilen durch die 50 Leerzeilen
  // aus dem sichtbaren Fensterbereich hinausgeschoben wurden
  if (Index == 0) {
    Serial.print(">");
  }
  Serial.print("Zeit1:");
  Serial.println (Zeit[0]);


  if (Index == 1) {
    Serial.print(">");
  }
  Serial.print("Zeit2:");
  Serial.println(Zeit[1]);


  if (Index == 2) {
    Serial.print(">");
  }
  Serial.print("Zeit3:");
  Serial.println(Zeit[2]);


  if (Index == 3) {
    Serial.print(">");
  }
  Serial.print("Zeit4:");
  Serial.println(Zeit[3]);

  Serial.print("Encoder:");
  Serial.println(neuePosition);
}


// function for debouncing a button
byte buttonPressedForSomeTime(byte buttonPin) {

  // Variables will change:
  static byte buttonState;             // the current reading from the input pin
  static byte lastButtonState;// = LOW;   // the previous reading from the input pin

  // the following variables are unsigned longs because the time, measured in
  // milliseconds, will quickly become a bigger number than can be stored in an int.
  static unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
  const unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

  static byte debouncedState = 0;
  static byte reading;
  // read the state of the switch into a local variable:
  reading = digitalRead(buttonPin);
  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:
    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // ButtonState does state-CHANGE-detection
      if (buttonState == HIGH) {
        debouncedState = 1;
      }

      if (buttonState == LOW) {
        debouncedState = 0;
      }
    }
  }

  // save the reading. Next time through the loop, it'll be the lastButtonState
  lastButtonState = reading;
  return debouncedState;
}


void manageButtonPresses() {  
  myButtonState = buttonPressedForSomeTime(SW);  // debounced Tasterabfrage

  if (lastMyButtonState != myButtonState) { // prüfe ob sich Schaltzustand des Tasters geändert hat
    // nur wenn sich Schaltzustand des Tasters WIRKLICH geändert hat
    lastMyButtonState = myButtonState; // Variable lastMyButtonState updaten

    if (myButtonState == pressed) { // wenn Taster gedrückt
      Zeit[Index] = neuePosition;   // Zahl speichern
      Index++;                      // Index erhöhen

      if (Index > 3) {              // Index im Kreis 0,1,2,3,0,1,2....
        Index = 0;
      }
    }
  }
}

vgs

Vielen Dank für deine schnelle Hilfe. ich hab inzwischen den NewEncoder. Sieht ganz gut aus. Ich bin jetzt dabei, es mit dem oled Display zu kombinieren. ich schaue mir morgen auch dienen neuen post noch genauer an. Vielen Dank erstmal, ich melde mich dann morgen Abend wieder.
Viele Grüße

Wollte mich nur kurz für die Hilfe bedanken und Bescheid geben das mein Programmstart erst mal so funktioniert. Habe es mit deinem ersten Lösungsansatz "if (currentValue != prevEncoderValue)" gemacht. Werde mich in den nächsten Tagen an das restliche Programm noch herantasten und falls ich nochmal Probleme bekomme mich wieder bei euch hier im Forum melden.
Vielen Dank für die schnelle Hilfe!
Anbei noch das Programm, falls es jemand sehen möchte

#include "Arduino.h"
#include "NewEncoder.h"

#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3C
SSD1306AsciiWire oled;

int abbruchtaster = 0;
int tasterstatus = 0;
int Zeit1 = 0;
int Zeit2 = 0;
int Zeit3 = 0;
int Zeit4 = 0;
int Index = 1;
int Startindex = 0;

const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal =   0;
const int maxVal =  20;
const int startVal = 0;




// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;

  Wire.begin();
  Wire.setClock(400000L);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);

  oled.setFont(System5x7); // Auswahl der Schriftart
  oled.clear(); //Löschen der aktuellen Displayanzeige

  pinMode(4, INPUT);
  pinMode(1, INPUT);

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {

  if (Startindex == 0)
  {
    oled.clear();
    oled.println("ready to start");
    Startindex = 1;
    delay(200);
  }

  abbruchtaster = digitalRead(1);
  if (abbruchtaster == LOW)
  {
    delay(3000);
    abbruchtaster = digitalRead(1);
    if (abbruchtaster == LOW)
    {
      tasterstatus = 0;
      Zeit1 = 0;
      Zeit2 = 0;
      Zeit3 = 0;
      Zeit4 = 0;
      Index = 1;
      Startindex = 0;
      oled.println("Abbruch durch Taster");
      delay(2000);
      oled.clear();
      oled.println("Abbruch durch Taster");
      oled.println("/");
      oled.println("restart in 5 sek");
      delay(5000);
    }
  }

  if (Index == 5)
  {
    oled.clear();
    oled.println("check settings");
    oled.print("Zeit 1: ");
    oled.print(Zeit1);
    oled.println(" Minuten");
    oled.print("Zeit 2: ");
    oled.print(Zeit2);
    oled.println(" Minuten");
    oled.print("Zeit 3: ");
    oled.print(Zeit3);
    oled.println(" Minuten");
    oled.print("Zeit 4: ");
    oled.print(Zeit4);
    oled.println(" Minuten");
    delay(3000);
    oled.println("press ok if they fit");
    Index = ++Index;
  }

  if (Index <= 4)
  {
    NewEncoder::EncoderState myCurrentEncoderState;
    // store actual values into variable myCurrentEncoderState
    if (myEncoderObject.getState(myCurrentEncoderState)) {
      if (Index == 1)
      {
        oled.clear();
        oled.print("-> Zeit 1: ");
        oled.println(Zeit1);
        oled.print("Zeit 2: ");
        oled.println(Zeit2);
        oled.print("Zeit 3: ");
        oled.println(Zeit3);
        oled.print("Zeit 4: ");
        oled.println(Zeit4);
      }
      if (Index == 2)
      {
        oled.clear();
        oled.print("Zeit 1: ");
        oled.println(Zeit1);
        oled.print("-> Zeit 2: ");
        oled.println(Zeit2);
        oled.print("Zeit 3: ");
        oled.println(Zeit3);
        oled.print("Zeit 4: ");
        oled.println(Zeit4);
      }
      if (Index == 3)
      {
        oled.clear();
        oled.print("Zeit 1: ");
        oled.println(Zeit1);
        oled.print("Zeit 2: ");
        oled.println(Zeit2);
        oled.print("-> Zeit 3: ");
        oled.println(Zeit3);
        oled.print("Zeit 4: ");
        oled.println(Zeit4);
      }
      if (Index == 4)
      {
        oled.clear();
        oled.print("Zeit 1: ");
        oled.println(Zeit1);
        oled.print("Zeit 2: ");
        oled.println(Zeit2);
        oled.print("Zeit 3: ");
        oled.println(Zeit3);
        oled.print("-> Zeit 4: ");
        oled.println(Zeit4);
      }
      oled.print("Encoder: ");
      currentValue = myCurrentEncoderState.currentValue;

      // if currentValue has REALLY changed print new currentValue
      if (currentValue != prevEncoderValue) {
        Serial.println(currentValue);
        oled.println(currentValue);
        prevEncoderValue = currentValue;

        // if currentValue stayed the same because the number is at upper/lower limit
        // check if encoder was rotated by using the UpClick / DownClick-values
      } else
        switch (myCurrentEncoderState.currentClick) {
          case NewEncoder::UpClick:
            oled.println("to high");
            break;

          case NewEncoder::DownClick:
            oled.println("to low");
            break;

          default:
            break;
        }
    }
    tasterstatus = digitalRead(4);
    if (tasterstatus == LOW && Index == 4)
    {
      Zeit4 = currentValue;
      Serial.print("Zeit 4: ");
      Serial.println(Zeit4);
      oled.print("Zeit 4: ");
      oled.println(Zeit4);
      Index = ++Index;
      delay(500);
    }
    if (tasterstatus == LOW && Index == 3)
    {
      Zeit3 = currentValue;
      Serial.print("Zeit 3: ");
      Serial.println(Zeit3);
      oled.print("Zeit 3: ");
      oled.println(Zeit3);
      Index = ++Index;
      delay(500);
    }
    if (tasterstatus == LOW && Index == 2)
    {
      Zeit2 = currentValue;
      Serial.print("Zeit 2: ");
      Serial.println(Zeit2);
      oled.print("Zeit 2: ");
      oled.println(Zeit2);
      Index = ++Index;
      delay(500);
    }
    if (tasterstatus == LOW && Index == 1)
    {
      Zeit1 = currentValue;
      Serial.print("Zeit 1: ");
      Serial.println(Zeit1);
      oled.print("Zeit 1: ");
      oled.println(Zeit1);
      Index = ++Index;
      delay(500);
    }
  }



}