Help Getting Button Presses Recognised

I'm writing some code where I want a menu system to display on an OLED screen. I have written the following code, but I'm having difficulty getting the three buttons to be recognised. On the Oled.cpp tab you can see some code I've written where I'm trying to get the up button state to be read and to move a cursor accordingly:

main.ino

#include "PushButton.h"
#include "Oled.h"


#define selectButton 3
#define upButton 4
#define downButton 5


PushButton select(selectButton, true, true);
PushButton up(upButton, true, true);
PushButton down(downButton, true, true);



OLEDDisplay Oled;


void setup() {
  Serial.begin(115200);

  Oled.init();

}

void loop() {
  Oled.homeScreen();

//  if (enterButton.isPressed()) {
//    Serial.println("Enter Button is pressed");
//  }
//  else {
//  if (upButton.isPressed()) {
//    //Serial.println(menuItem);
//    Serial.println("Up Button is pressed");
//  }
//  else {
//    if (downButton.isPressed()) {
//    Serial.println("Down Button is pressed");
//    }
//  }
//  }


}

PushButton.h

//INTERFACE

#ifndef PUSH_BUTTON_H
#define PUSH_BUTTON_H

#include <Arduino.h>


class PushButton
{
  private:
    byte pin;
    byte state;

    bool isPullUp;
    bool internalPullUpActivated;
    unsigned long lastTimeStateChanged;
    unsigned long debounceDelay;



    void readState();

  public:
//THE CONSTRUCTOR
//What do I need to be able to interact with the button?
  PushButton() {}       //do not use
  PushButton(byte pin, bool isPullUp, bool internalPullUpActivated);

  void init();
  

  bool isPressed();
};



#endif

PushButton.cpp

//THE IMPLEMENTATION

#include "PushButton.h"

PushButton::PushButton(byte pin,bool isPullUp, 
                bool internalPullUpActivated)
{
  this->pin = pin;
  this->isPullUp = isPullUp;
  this->internalPullUpActivated = internalPullUpActivated;
//  this->selectButton = selectButton;
//  this->upButton = upButton;
//  this->downButton = downButton;

  lastTimeStateChanged = millis();
  debounceDelay = 50;
}

void PushButton::init()            //Data type, class, name of function
{
  if (isPullUp && internalPullUpActivated) {
    pinMode(pin, INPUT_PULLUP);
  }
  else {
    pinMode(pin, INPUT);
  }
  
  
  state = digitalRead(pin);
}

void PushButton::readState()
{
  unsigned long timeNow = millis();
  if (timeNow - lastTimeStateChanged > debounceDelay) {
    byte newState = digitalRead(pin);
    if (newState != state) {
      state = newState;
      lastTimeStateChanged = timeNow;
    }
  }
  state = digitalRead(pin);
  return state ;                   //to store the state inside the class
}

bool PushButton::isPressed()
{
  readState();
  if(isPullUp) {
    return (state == LOW);
  }
  else {
    return (state == HIGH);
  }
}

Oled.h

//INTERFACE


//Header guard
#ifndef OLED_H
#define OLED_H

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "PushButton.h"


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1


class OLEDDisplay {

private:
  Adafruit_SSD1306 display;

  int menuItem = 1;
  int page = 1;
  
  PushButton selectButton;
  PushButton upButton;
  PushButton downButton;

//  bool selectButton = false;
//  bool upButton = false;
//  bool downButton = false;

//YOU MAY NEED TO DELETE THIS
int downButtonState = 0;
int upButtonState = 0;
int selectButtonState = 0;
int lastDownButtonState = 0;
int lastSelectButtonState = 0;
int lastUpButtonState = 0;
volatile boolean select = false;
volatile boolean up = false;
volatile boolean down = false;

public:
//CONSTRUCTOR
  OLEDDisplay() {};

  OLEDDisplay(PushButton &selectButton, PushButton &upButton, PushButton &downButton);
  //OLEDDisplay(bool  selectButton, bool  upButton, bool  downButton, int menuItem, int page);

  void init();

  void menu();

  void homeScreen();

  void updateOLED();

  void option1();

  void option2();

  void option3();
  
};


#endif

Oled.cpp

//IMPLEMENTATION

#include "Oled.h"
#include "PushButton.h"


OLEDDisplay::OLEDDisplay(PushButton &selectButton, PushButton &upButton, PushButton &downButton)
{
  display = Adafruit_SSD1306 (SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

  this->selectButton = selectButton;
  this->upButton = upButton;
  this->downButton = downButton;
  this->menuItem = menuItem;
  this->page = page;



}



void OLEDDisplay::init()
{
  selectButton.init();
  upButton.init();
  downButton.init();
  delay(100);
  
  Serial.begin(115200);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 15);
  display.print(">");
  display.display();
  //Serial.println(menuItem);

}

void OLEDDisplay::homeScreen()
{
  //Serial.println(menuItem);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(15, 0);
  display.print("DISPLAY OPTIONS");
  display.drawFastHLine(15, 10, 90, WHITE);
  //display.display();
  
  display.setCursor(8, 15);
  display.print("General ");

  display.setCursor(8, 25);
  display.print("Environment ");

  display.setCursor(8, 35);
  display.print("Sensors");
  
  //if (upButton.isPressed())
  if (upButton.isPressed() && page == 1)
  //if(digitalRead(UP_BUTTON) == false && page == 1)
  {
    menuItem--;    
    //updateOLED();
    if (menuItem == 0){
      menuItem = 3;
      Serial.print(menuItem);
      Serial.print(" ");
      Serial.println(page);
      option3();
    }
      if (menuItem == 1) 
      {
        Serial.println("Menu Item 1");
      }
      if (menuItem == 2)
      {
        Serial.println("Menu Item 2");
      }
    //display.print(">General");
  } else {
    //display.print(" General");
  }
    display.display();
}

  void OLEDDisplay::option1 () {
  display.setCursor(0, 15);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.print(">");
  display.display();
}

  void OLEDDisplay::option2 (){
  display.setCursor(0, 25);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.print(">");
  display.display();  
}

  void OLEDDisplay::option3 (){
  display.setCursor(0, 35);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.print(">");
  display.display();  
}
  void OLEDDisplay::updateOLED() {
  display.clearDisplay();
  display.display();
  }

Thank you in advance

Hello l_ombre

You could design and programme your own button manager that contains the desired function

Yes, Paul. That’s the help I’m looking for

What you you mean when you say "recognised"? Do you mean that pushing the buttons has no effect?

How are your buttons wired?

I'm happy with how the buttons are wired because if I add this code to the main loop, I see the correct output on the serial monitor:

  if (enterButton.isPressed()) {
    Serial.println("Enter Button is pressed");
  }
  else {
  if (upButton.isPressed()) {
    Serial.println("Up Button is pressed");
  }
  else {
    if (downButton.isPressed()) {
    Serial.println("Down Button is pressed");
    }
  }
  }

My buttons are wired to pins D3(selectButton), D4 (upButton) and D5(downButton), so I'm positive that they are wired and working correctly. What I would like is for the buttons to be detected in the Oled.cpp implementation and I'm unable to achieve that at the moment

Should this be

PushButton *selectButton;

and then

selectButton->init();

?

What I don't understand is why this doesn't give a compile error

this->selectButton = selectButton;

because this->selectButton is type PushButton, but selectButton is type &PushButton (i.e. a reference to a PushButton object).

Maybe I'm showing my ignorance!

Hi Paul,

Thanks for the suggestions, but your changes stop the program from compiling.

I wouldn't say you're showing your ignorance but perhaps we are mixing approaches to programming classes. Did you try your updates for yourself and did your program compile?

No, I'm typing suggestions from my smartphone.

Not saying it's a solution but, I made up a sketch with just the pushbutton parts and got this warning.

C:\Users\User\AppData\Local\Temp\.arduinoIDE-unsaved202416-6412-19qjl26.0u58\sketch_feb6a\PushButton.cpp: In member function 'void PushButton::readState()':
C:\Users\User\AppData\Local\Temp\.arduinoIDE-unsaved202416-6412-19qjl26.0u58\sketch_feb6a\PushButton.cpp:43:10: warning: return-statement with a value, in function returning 'void' [-fpermissive]
   return state ;                   //to store the state inside the class
          ^~~~~

Maybe you don't have your compiler warning level high enough to see this:

not doing much for you??
maybe you should try the other construct you constructed..

good luck.. ~q

Pushbuttons have 2 pins, one is connected to an input pin. What is the other one connected?

To ground. As mentioned in an earlier post, I know the buttons are working because I can output their status to the serial interface with the lines I mentioned in the main loop.

nano?? i guessed wrong..
simmed it on a mega yesterday before commenting..
Your project simmed..

don't have the dht, led in the sim, didn't see them in orig sketch..

curious, did you try using the other construct yet??

good luck.. ~q

Hey there,

If my "simmed" you mean that it compiled, I got to the same stage.
In the meantime, I called the constructor with the following arguments, so perhaps I'm edging closer to the solution, hopefully. Here's the current main.ino:

#include "PushButton.h"
#include "Oled.h"


#define selectButton 3
#define upButton 4
#define downButton 5


PushButton select(selectButton, true, true);
PushButton up(upButton, true, true);
PushButton down(downButton, true, true);



OLEDDisplay oledDisplay(select, up, down);


void setup() {
  Serial.begin(115200);

  oledDisplay.init();
  

}

void loop() {

  oledDisplay.homeScreen();




}

No, It means, I put this project into an online simulator..
Click the link I posted to see it..

a little bit better, class still needs more, but you should see something on one of the buttons..

good luck.. ~q

1 Like

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