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
// 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
#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
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
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
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:
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
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().
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.
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.
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.