Button Click Counting With Virtual 7 Segment Display

by Trevor Lee in Circuits > Arduino

346 Views, 2 Favorites, 0 Comments

Button Click Counting With Virtual 7 Segment Display

dd7segcounter.jpg

Accurate counting hardware button click can be challenging, due to button signal bouncing effect.

Other than 2 physical buttons attached to an Arduino Nano microcontroller board, all will be software based, including button click detection, as well as that 7 Segment Display is realized virtually with DumbDisplay.

Setup Arduino IDE

add_library.png

In order to be able to compile and run the sketch shown here, you will first need to install the DumbDisplay Arduino library.

Open your Arduino IDE; go to the menu item Tools | Manage Libraries, and type "dumbdisplay" in the search box there.

Connections

dd7segcounter_onnection.png
  • Connect D4 to one pin of the button on the left side; connect GND to the other pin of the button.
  • Connect D2 to one pin of the button on the right side; connect GND to the other pin of the button.

The Sketch

Although Arduino Nano is used here, I believe the sketch will work for other types of boards, of cause, with some adaptions.

The sketch is not complicated, and is based on, and extended from, the example otg7segment that comes with the library you just installed.

#include "dumbdisplay.h"
#define PIN_LEFT PIN4
#define PIN_RIGHT PIN2
// create the DumbDisplay object; assuming USB connection with 115200 baud
DumbDisplay dumbdisplay(new DDInputOutput(115200));
// declare a 7-segment layer object, to be created in setup()
SevenSegmentRowDDLayer *sevenSeg;
class ButtonPressTracker {
public:
ButtonPressTracker() {
this->pressed = false; // assume initially not pressed
this->blackOutMillis = 0;
}
bool setPressed(bool pressed) {
long nowMillis = millis();
if (blackOutMillis != 0) {
long diff = blackOutMillis - nowMillis;
if (diff < 0) {
blackOutMillis = 0;
}
}
if (blackOutMillis == 0) {
if (pressed != this->pressed) {
this->pressed = pressed;
blackOutMillis = nowMillis + 50;
return this->pressed;
}
}
return false;
}
private:
bool pressed;
long blackOutMillis;
};
ButtonPressTracker leftTracker;
ButtonPressTracker rightTracker;
int count = 0;
void setup() {
pinMode(PIN_RIGHT, INPUT_PULLUP);
pinMode(PIN_LEFT, INPUT_PULLUP);
// create the 7-segment layer object, with 3 7-segment digits
sevenSeg = dumbdisplay.create7SegmentRowLayer(3);
sevenSeg->border(5, "black", "round");
sevenSeg->padding(5);
sevenSeg->resetSegmentOffColor(DD_RGB_COLOR(0xff, 0xee, 0xff));
sevenSeg->showNumber(count);
}
void loop() {
int left = digitalRead(PIN_LEFT);
int right = digitalRead(PIN_RIGHT);
bool rightPressed = rightTracker.setPressed(right == 0);
bool leftPressed = leftTracker.setPressed(left == 0);
int preCount = count;
if (leftPressed) {
count -= 1;
}
if (rightPressed) {
count += 1;
}
if (count != preCount) {
sevenSeg->showNumber(count);
}
}

How the sketch makes use of virtual 7 Segment Display shoud be fairly obvious. Basic steps:

  • Globally declare a DumbDisplay object; as well as a pointer to SevenSegmentRowDDLayer, which will be created in the setup() block
// create the DumbDisplay object; assuming USB connection with 115200 baud
DumbDisplay dumbdisplay(new DDInputOutput(115200));
SevenSegmentRowDDLayer *sevenSeg;
  • In the setup() block, actually create a SevenSegmentRowDDLayer object, with 3 digits
 // create the 7-segment layer object, with 3 7-segment digits
sevenSeg = dumbdisplay.create7SegmentRowLayer(3);
  • When need to display numbers to the 7 segment display (SevenSegmentRowDDLayer), simply call showNumber()
 sevenSeg->showNumber(count);

As for checking button click, the object ButtonPressTracker is used. The idea is pretty simple:

  • You continously set the button state ("pressed") by calling the method setPressed() of ButtonPressTracker
  • The method setPressed() will only return true when it is considered a button click
 int left = digitalRead(PIN_LEFT);
int right = digitalRead(PIN_RIGHT);
bool rightPressed = rightTracker.setPressed(right == 0);
bool leftPressed = leftTracker.setPressed(left == 0);

The method setupPressed() helps to detect button click by making sure of two conditions:

  • the "pressed" state doesn't change too frequently; in fact, in 50ms from the last state change, no further state change will be accepted
  • only return true if the "pressed" state is changed to pressed
bool setPressed(bool pressed) {
long nowMillis = millis();
if (blackOutMillis != 0) {
long diff = blackOutMillis - nowMillis;
if (diff < 0) {
blackOutMillis = 0;
}
}
if (blackOutMillis == 0) {
if (pressed != this->pressed) {
this->pressed = pressed;
blackOutMillis = nowMillis + 50;
return this->pressed;
}
}
return false;
}

From my own experience, this "debouncing" works fairly well.

Upload the Sketch and Run It

Other than this sketch for your Arduino Nano, you will need to prepare two more addition things:

  • You will need to be able to attach your Arduino Nano to your Android phone. To do this, you will need an OTG adaptor, which allows you to plug your Arduino Nano to your phone via the usual USB cable.
  • You will certainly need to install the DumbDisplay Android app.

After uploading the sketch, re-plug the USB cable to your phone via an OTG adaptor. Then, open the DumbDisplay Android app on your phone, and make connection.

Click the buttons! See that the button on the left side will decrement the count; and the button on the right side will increment the count.

Click quickly! See if the click detection is accurate? I will keep my fingers crossed!

Enjoy!

Merely counting is not very interesting. In fact, I will be coming up with a more interesting application, extended from this setup. Until then, enjoy!

Peace be with you. Jesus loves you. May God bless you!