OLED- Button Press Counter

About The Project

In this project, we will learn how to count the number of button- presses and display the result on an OLED.

OLED

An OLED (Organic Light Emitting Diode) display is a type of screen technology that uses organic compounds to produce light when an electric current is applied. OLED displays are known for their high contrast ratios, vibrant colours, and the ability to be very thin and flexible. They are commonly used in smartphones, TVs, wearable devices, and various electronics projects.

Circuit Wiring

OLED Library

To use the OLED display with your Arduino, you need to install the necessary libraries and include their header files in your code.

Install the Adafruit GFX Library:

    • Search for Adafruit GFX in the Library Manager.
    • Find the Adafruit GFX library by Adafruit and click Install.

Program Code

C++
// www.matthewtechub.com
// oled display number of button push

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

#define SCREEN_WIDTH 128 // OLED display width,  in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // create SSD1306 display object connected to I2C

const int buttonPin = 7;  // button pin
unsigned long lastCount = 0;
unsigned long buttonPressCount = 0;

bool lastButtonState = HIGH;  // last state of the button
bool buttonState = HIGH;      // current state of the button

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

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

  // initialize OLED display with address 0x3C for 128x64
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    while (true);
  }

  delay(2000);         // wait for initializing
  oled.clearDisplay(); // clear display

  oled.setTextSize(2);          // text size
  oled.setTextColor(WHITE);     // text color
  oled.setCursor(0, 0);        // position to display

  pinMode(buttonPin, INPUT_PULLUP);  // set the button pin as input with internal pull-up resistor
}

void loop() {
  int reading = digitalRead(buttonPin);  // read the state of the switch into a local variable

  // check to see if you just pressed the button (i.e., the input went from HIGH to LOW), and you've waited long enough since the last press to ignore any noise:
  if (reading != lastButtonState) {
    lastDebounceTime = millis();  // reset the debouncing timer
  }

  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 (reading != buttonState) {
      buttonState = reading;

      // only count the button press if the new button state is LOW
      if (buttonState == LOW) {
        buttonPressCount++;
      }
    }
  }

  // only update the display when the button press count changes
  if (lastCount != buttonPressCount) {
    Serial.println(buttonPressCount); // print count to Serial Monitor
    oled.clearDisplay(); // clear display
    oled.setCursor(0, 10); // reset cursor position
    oled.println(buttonPressCount); // display count
    oled.display();      // show on OLED
    lastCount = buttonPressCount; // update lastCount
  }

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

This project continuously monitors the state of a button and increments a counter each time the button is pressed. The current count is displayed on an OLED screen. The code includes debouncing logic to prevent false counts due to noisy button signals.

Code Explanation

Library Inclusions and Definitions

C++
   #include <Wire.h>
   #include <Adafruit_GFX.h>
   #include <Adafruit_SSD1306.h>

   #define SCREEN_WIDTH 128 // OLED display width,  in pixels
   #define SCREEN_HEIGHT 64 // OLED display height, in pixels

   Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // create SSD1306 display object connected to I2C
  • Includes the necessary libraries for the OLED display.
  • Defines the width and height of the OLED screen.
  • Creates an instance of the SSD1306 display.

Pin and Variable Declarations

C++
   const int buttonPin = 7;  // button pin
   unsigned long lastCount = 0;
   unsigned long buttonPressCount = 0;

   bool lastButtonState = HIGH;  // last state of the button
   bool buttonState = HIGH;      // current state of the button

   unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
   unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
  • Specifies the pin connected to the button.
  • Initializes variables to store the button press count and debouncing states.

Setup Function

C++
   void setup() {
     Serial.begin(9600);

     // initialize OLED display with address 0x3C for 128x64
     if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
       Serial.println(F("SSD1306 allocation failed"));
       while (true);
     }

     delay(2000);         // wait for initializing
     oled.clearDisplay(); // clear display

     oled.setTextSize(2);          // text size
     oled.setTextColor(WHITE);     // text color
     oled.setCursor(0, 0);        // position to display

     pinMode(buttonPin, INPUT_PULLUP);  // set the button pin as input with internal pull-up resistor
   }
  • Initializes the serial communication for debugging.
  • Initializes the OLED display.
  • Configures the button pin as an input with an internal pull-up resistor.

Loop Function

C++
   void loop() {
     int reading = digitalRead(buttonPin);  // read the state of the switch into a local variable

     // check to see if you just pressed the button (i.e., the input went from HIGH to LOW), and you've waited long enough since the last press to ignore any noise:
     if (reading != lastButtonState) {
       lastDebounceTime = millis();  // reset the debouncing timer
     }

     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 (reading != buttonState) {
         buttonState = reading;

         // only count the button press if the new button state is LOW
         if (buttonState == LOW) {
           buttonPressCount++;
         }
       }
     }

     // only update the display when the button press count changes
     if (lastCount != buttonPressCount) {
       Serial.println(buttonPressCount); // print count to Serial Monitor
       oled.clearDisplay(); // clear display
       oled.setCursor(0, 10); // reset cursor position
       oled.println(buttonPressCount); // display count
       oled.display();      // show on OLED
       lastCount = buttonPressCount; // update lastCount
     }

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

Let’s break down the loop() function step by step to explain what it does:

C++
int reading = digitalRead(buttonPin);  // read the state of the switch into a local variable
  • The digitalRead(buttonPin) function reads the current state of the button (either HIGH or LOW) and stores it in the reading
C++
if (reading != lastButtonState) {
  lastDebounceTime = millis();  // reset the debouncing timer
}
  • This checks if the button state has changed since the last loop iteration. If the state has changed, the debounce timer (lastDebounceTime) is reset to the current time using millis().
C++
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 (reading != buttonState) {
    buttonState = reading;

    // only count the button press if the new button state is LOW
    if (buttonState == LOW) {
      buttonPressCount++;
    }
  }
}
  • This checks if the elapsed time since the last state change is greater than the debounce delay (debounceDelay). This helps to filter out any noise or spurious changes in the button state.
  • If the button state has remained stable for longer than the debounce delay, the buttonState variable is updated to the current reading.
  • If the new button state is LOW (indicating a button press), the buttonPressCount is incremented.
C++
if (lastCount != buttonPressCount) {
  Serial.println(buttonPressCount); // print count to Serial Monitor
  oled.clearDisplay(); // clear display
  oled.setCursor(0, 10); // reset cursor position
  oled.println(buttonPressCount); // display count
  oled.display();      // show on OLED
  lastCount = buttonPressCount; // update lastCount
}
  • This block updates the OLED display only if the button press count has changed.
  • It prints the new count to the Serial Monitor for debugging purposes.
  • The display is cleared, the cursor is reset, and the new button press count is displayed on the OLED.
  • The lastCount variable is updated to the current buttonPressCount to keep track of changes.
C++
lastButtonState = reading;  // save the reading. Next time through the loop, it'll be the lastButtonState
  • The current button reading is saved in lastButtonState for comparison in the next loop iteration.

Try Yourself

Modify the project to count down and display the count on the OLED.

Leave a Reply

Your email address will not be published. Required fields are marked *

error: Content is protected !!