2 Item Menu + RotaryEncoder + Button + OLED

I am trying to build a 2 Item Menu controlled by a Rotary Encoder, a Button and displayed by an OLED.

So far so good. But when i add a Variable in the Second Menu "//Display & SerialMonitor" it is not changing the "menuVal". I am stuck in what ever Menu i am at the start. Which is also odd. It changes the "menuVal" each time i reset the Arduino.
I have no clue why it is doing that. As long as i am not printing any Values i am fine.

Thx!!

//RotaryEncoder
#define inputCLK 2
#define inputDT 5
int aState;
int aLastState;

//TimerFunktion
int counter = 30;

//CountDownFunktion
int countDown = 30;

//RotaryEncoderSwitch
#define inputSW 4
int sw;  //SwitchValue

//Button
#define button 7
int buttonVal = 1;
int menuVal = 1;
int buttonPeriod = 100;

//SerialPrint intervall
int serialPrintPeriod = 1000;

//Screen
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

//Heater
int relayPin = 6;         //relayPin Pin
int HeaterButton = 4000;  // Length of the HeaterControllerButton necessary to be HIGH

//millis
unsigned long timeOld;


void setup() {

  Serial.begin(9600);
  pinMode(inputCLK, INPUT);
  pinMode(inputDT, INPUT);
  pinMode(inputSW, INPUT_PULLUP);  //SwitchPin
  pinMode(relayPin, OUTPUT);       //relayPin
  digitalWrite(relayPin, HIGH);    //relayPin
  pinMode(button, INPUT);          //ButtonPin

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();

  aLastState = digitalRead(inputCLK);
}

void loop() {

  //buttonRead
  if (millis() - timeOld >= serialPrintPeriod) {
    buttonVal = digitalRead(button);
    Serial.print("buttonVal ");
    Serial.println(buttonVal);
    Serial.print("menuVal ");
    Serial.println(menuVal);
    Serial.print("counter ");
    Serial.println(counter);
    Serial.print("CountDown ");
    Serial.println(countDown);
    timeOld = millis();
  }
  //buttonVal
  if (buttonVal == 1) {
    menuVal = menuVal + 1;
  }
  //menuVal
  if (menuVal >= 3) {
    menuVal = 1;
  }
  //Menu1+2
  if (menuVal == 1) {
    //Display & SerialMonitor
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 10);
    display.print("Timer - ");
    display.print(counter);
    display.println(" Minutes");
    display.display();
    //Rotary
    aState = digitalRead(inputCLK);
    if (aState != aLastState) {
      if (digitalRead(inputDT) != aState) {
        counter = counter - 5;
      } else {
        counter = counter + 5;
      }
    }
    aLastState = aState;
    //Timer Funktion
    sw = digitalRead(inputSW);
    if (sw == 0) {
      Serial.println(counter * 60ul * 1000ul);
      digitalWrite(relayPin, LOW);
      delay(HeaterButton);
      digitalWrite(relayPin, HIGH);
      delay(counter * 60ul * 1000ul);
      digitalWrite(relayPin, LOW);
      delay(HeaterButton);
      digitalWrite(relayPin, HIGH);
    }
  } else {
    //Display & SerialMonitor
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 10);
    display.println("CountDown ");
    display.print(countDown);
    display.println("CountDown ");
    display.display();
  }
}

how did you wire this button?

You only read your button state once every second - way too slow. You should be reading it every time through loop() and debouncing it.

But then, every time through loop(), this happens:

so imagine this scenario. You press the button, it reads HIGH. buttonVal is now HIGH so you increment menuVal. Next time through loop(), it is not time to read the button but it is still HIGH so you increment menuVal again. This happens very rapidly until you get to 3 and then resets back to 1. Repeat.

Your logic needs a bit of re-work.

to pin 7. the other side is "plus" and "negativ" + 1k ohm Resistor.

Please post a schematic. Written descriptions are always more ambiguous than a drawing. Hand drawn, photographed and posted is fine.

i debounced the button in my code.

now it works!

//RotaryEncoder
#define inputCLK 2
#define inputDT 5
int aState;
int aLastState;

//TimerFunktion
int counter = 30;

//CountDownFunktion
int countDown = 30;

//RotaryEncoderSwitch
#define inputSW 4
int sw;  //SwitchValue

//Button
#define button 7
int buttonVal;
int lastButtonVal = 0;
int menuVal = 1;
int buttonPeriod = 100;

//SerialPrint intervall
int serialPrintPeriod = 1000;

//Screen
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

//Heater
int relayPin = 6;         //relayPin Pin
int HeaterButton = 4000;  // Length of the HeaterControllerButton necessary to be HIGH

//millis
unsigned long timeOld;


void setup() {

  Serial.begin(9600);
  pinMode(inputCLK, INPUT);
  pinMode(inputDT, INPUT);
  pinMode(inputSW, INPUT_PULLUP);  //SwitchPin
  pinMode(relayPin, OUTPUT);       //relayPin
  digitalWrite(relayPin, HIGH);    //relayPin
  pinMode(button, INPUT);          //ButtonPin

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();

  aLastState = digitalRead(inputCLK);
}

void loop() {

  //Serial.Print
  if (millis() - timeOld >= serialPrintPeriod) {
    Serial.print("buttonVal ");
    Serial.println(buttonVal);
    Serial.print("menuVal ");
    Serial.println(menuVal);
    Serial.print("counter ");
    Serial.println(counter);
    Serial.print("CountDown ");
    Serial.println(countDown);
    timeOld = millis();
  }
  //Buttonfunktion
  buttonVal = digitalRead(button);
  if (lastButtonVal == 0 && buttonVal == 1) {
    menuVal++;
    if(menuVal >= 3){
      menuVal = 1;
    }
  }
  lastButtonVal = buttonVal;
  delay(100);

  //Menu1+2
  if (menuVal == 1) {
    //Display & SerialMonitor
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 10);
    display.print("Timer - ");
    display.print(counter);
    display.println(" Minutes");
    display.display();
    //Rotary
    aState = digitalRead(inputCLK);
    if (aState != aLastState) {
      if (digitalRead(inputDT) != aState) {
        counter = counter - 5;
      } else {
        counter = counter + 5;
      }
    }
    aLastState = aState;
    //Timer Funktion
    sw = digitalRead(inputSW);
    if (sw == 0) {
      Serial.println(counter * 60ul * 1000ul);
      digitalWrite(relayPin, LOW);
      delay(HeaterButton);
      digitalWrite(relayPin, HIGH);
      delay(counter * 60ul * 1000ul);
      digitalWrite(relayPin, LOW);
      delay(HeaterButton);
      digitalWrite(relayPin, HIGH);
    }
  } else {
    //Display & SerialMonitor
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 10);
    display.print("CountDown ");
    display.println(countDown);
    display.display();
  }
}

thx everyone

I would suggest to use libraries for the encoder and the buttons, it will make your coding easier for example with:

1 Like

An easier way to wire up your button is to connect one corner to your pin and the other corner to ground and then make the pin an INPUT_PULLUP. No need for external resistors or connecting it to power.

If you do have a 4 leg button like your image suggests, it is always best to use the diagonal corners for connection points. That way, you can rotate the button 90 degrees and it will still work fine. No chance or the wrong orientation.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.