Software

Trinket sketch to build a react or 'like' button that counts button presses and displays them on a 7-segment or 14-segment LED backpack.

You need the following hardware to build this device:

Usage

Load the right sketch in Arduino depending on your hardware. The 7-segment display should use the TrinketReactCounter_7segment sketch, and the 14-segment quad alphanumeric display should use the TrinketReactCounter_14segment sketch. Make sure the following libraries are installed too (using the library manager or a manual install):

// Adafruit Trinket React Counter Sketch - 7-segment display
//
// Use a 7-segment LED backpack to display the number of times a 
// button has been pressed.  Great for building a physical 'like'
// or react button.  The value will be stored  in EEPROM so it 
// will persist between power down/up.
//
// NOTE: As-is this sketch needs to run on a Trinket because it
// assumes the switch on pin #1 has a pull-down resistor to ground.
// If using another board without this pull-down you can explicitly
// add a ~10kohm resistor from digital #1 to ground.
//
// Author: Tony DiCola
// License: MIT (https://opensource.org/licenses/MIT)
#include <EEPROM.h>
#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"


// Uncomment the line below to reset the counter value in EEPROM to zero.
// After uncommenting reload the sketch and during the setup the counter
// will be reset.  Then comment the line again and reload to start again
// (if you don't comment it out then every time the board powers on it
// will reset back to zero!).
//#define RESET_COUNT

// OR just hold the button for longer than the RESET_HOLD_SECOND below
// to reset the count!

// Configuration:
#define LED_BACKPACK_ADDRESS   0x70   // I2C address of the backpack display.
                                      // Keep the default 0x70 unless you
                                      // change the backpack's address bridges.

#define COUNT_BUTTON_PIN       1      // Digital input connected to the button that
                                      // will increase the count. This line should
                                      // have a pull-down resistor to ground.  The
                                      // opposite side of the button should be
                                      // connected to a high level like 5V or 3.3V.

#define COUNT_ADDRESS          0      // Address in EEPROM to store the counter.
                                      // This will take 2 bytes (16-bit value).
                                      // You don't need to change this unless you
                                      // want to play with different EEPROM locations.

#define RESET_HOLD_SECONDS     5      // Number of seconds to hold the button down to
                                      // force a reset of the count to zero.  Set to 0
                                      // to disable this functionality.

// 7-segment display
Adafruit_7segment backpack = Adafruit_7segment();
uint32_t holdStart = 0;

void update_display() {
  // Get the count value from EEPROM and print it to the display.
  uint16_t count;
  EEPROM.get(COUNT_ADDRESS, count);
  backpack.print(count, DEC);
  backpack.writeDisplay();
}

void setup() {
  // Setup button inputs.
  pinMode(COUNT_BUTTON_PIN, INPUT);
  
  // Initialize the LED backpack display.
  backpack.begin(LED_BACKPACK_ADDRESS);

  // Clear the count in EEPROM if desired.
  #ifdef RESET_COUNT
    uint16_t count = 0;
    EEPROM.put(COUNT_ADDRESS, count);
  #endif

  // Update the display with the current count value.
  update_display();

  // Reset the last known time the button wasn't being held.
  holdStart = millis();
}

void loop() {
  // Take a couple button readings with a small delay in between to detect when
  // the signal changes from high to low, i.e. the button was released.
  int firstCount = digitalRead(COUNT_BUTTON_PIN);
  delay(20);
  int secondCount = digitalRead(COUNT_BUTTON_PIN);

  // Check for count button release.
  if (firstCount == HIGH && secondCount == LOW) {
    // Button was released!
    // Increment the count value stored in EEPROM.
    uint16_t count;
    EEPROM.get(COUNT_ADDRESS, count);
    count += 1;
    EEPROM.put(COUNT_ADDRESS, count);
    // Update the display with the latest count value.
    update_display();
  }

  // Reset the hold start if the button wasn't pressed (i.e. first and last were not both high levels).
  if ((firstCount != HIGH) || (secondCount != HIGH)) {
    holdStart = millis();
  }

  // Check if the button has been held for the amount of reset time.
  if ((RESET_HOLD_SECONDS > 0) && ((millis() - holdStart) >= (RESET_HOLD_SECONDS*1000))) {
    // Reset to zero and update the display!
    uint16_t count = 0;
    EEPROM.put(COUNT_ADDRESS, count);
    update_display();
    // Reset the hold time to start over again.
    holdStart = millis();
    // Flash the display a few times to give time to remove finger.
    for (int i=0; i<5; ++i) {
      delay(200);
      backpack.clear();
      backpack.writeDisplay();
      delay(200);
      update_display();
    }
  }
}
// Adafruit Trinket React Counter Sketch - 14-segment quad alpha display
//
// Use a 14-segment quad alphanumeric LED backpack to display the 
// number of times a button has been pressed.  Great for building
// a physical  'like' or react button.  The value will be stored 
// in EEPROM so it will persist between power down/up.
//
// NOTE: As-is this sketch needs to run on a Trinket because it
// assumes the switch on pin #1 has a pull-down resistor to ground.
// If using another board without this pull-down you can explicitly
// add a ~10kohm resistor from digital #1 to ground.
//
// Author: Tony DiCola
// License: MIT (https://opensource.org/licenses/MIT)
#include <EEPROM.h>
#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"


// Uncomment the line below to reset the counter value in EEPROM to zero.
// After uncommenting reload the sketch and during the setup the counter
// will be reset.  Then comment the line again and reload to start again
// (if you don't comment it out then every time the board powers on it
// will reset back to zero!).
//#define RESET_COUNT

// OR just hold the button for longer than the RESET_HOLD_SECOND below
// to reset the count!

// Configuration:
#define LED_BACKPACK_ADDRESS   0x70   // I2C address of the backpack display.
                                      // Keep the default 0x70 unless you
                                      // change the backpack's address bridges.

#define COUNT_BUTTON_PIN       1      // Digital input connected to the button that
                                      // will increase the count. This line should
                                      // have a pull-down resistor to ground.  The
                                      // opposite side of the button should be
                                      // connected to a high level like 5V or 3.3V.

#define COUNT_ADDRESS          0      // Address in EEPROM to store the counter.
                                      // This will take 2 bytes (16-bit value).
                                      // You don't need to change this unless you
                                      // want to play with different EEPROM locations.

#define RESET_HOLD_SECONDS     5      // Number of seconds to hold the button down to
                                      // force a reset of the count to zero.  Set to 0
                                      // to disable this functionality.

// 14-segment quad alphanumeric display
Adafruit_AlphaNum4 backpack = Adafruit_AlphaNum4();
uint32_t holdStart = 0;

void update_display() {
  // Get the count value from EEPROM and print it to the display.
  uint16_t count;
  EEPROM.get(COUNT_ADDRESS, count);
  // Use writeDigitRaw function to write out each digit for the thousands,
  // hundreds, tens, and ones place.
  int thousands = count / 1000;
  int remainder = count % 1000;
  int hundreds = remainder / 100;
  remainder = remainder % 100;
  int tens = remainder / 10;
  remainder = remainder % 10;
  // Check if the value is too large to display and just print dashes.
  if (thousands >= 10) {
    backpack.writeDigitAscii(0, '-');
    backpack.writeDigitAscii(1, '-');
    backpack.writeDigitAscii(2, '-');
    backpack.writeDigitAscii(3, '-');
  }
  else
  {
    // Print out the number starting from the first non-zero digit.
    if (thousands > 0) {
      backpack.writeDigitAscii(0, '0'+thousands);
      backpack.writeDigitAscii(1, '0'+hundreds);
      backpack.writeDigitAscii(2, '0'+tens);
      backpack.writeDigitAscii(3, '0'+remainder);
    }
    else if (hundreds > 0) {
      backpack.writeDigitAscii(1, '0'+hundreds);
      backpack.writeDigitAscii(2, '0'+tens);
      backpack.writeDigitAscii(3, '0'+remainder);
    }
    else if (tens > 0) {
      backpack.writeDigitAscii(2, '0'+tens);
      backpack.writeDigitAscii(3, '0'+remainder);
    }
    else {
      backpack.writeDigitAscii(3, '0'+remainder);
    }
  }
  backpack.writeDisplay();
}

void setup() {
  // Setup button inputs.
  pinMode(COUNT_BUTTON_PIN, INPUT);
  
  // Initialize the LED backpack display.
  backpack.begin(LED_BACKPACK_ADDRESS);

  // Clear the count in EEPROM if desired.
  #ifdef RESET_COUNT
    uint16_t count = 0;
    EEPROM.put(COUNT_ADDRESS, count);
  #endif

  // Update the display with the current count value.
  update_display();

  // Reset the last known time the button wasn't being held.
  holdStart = millis();
}

void loop() {
  // Take a couple button readings with a small delay in between to detect when
  // the signal changes from high to low, i.e. the button was released.
  int firstCount = digitalRead(COUNT_BUTTON_PIN);
  delay(20);
  int secondCount = digitalRead(COUNT_BUTTON_PIN);

  // Check for count button release.
  if (firstCount == HIGH && secondCount == LOW) {
    // Button was released!
    // Increment the count value stored in EEPROM.
    uint16_t count;
    EEPROM.get(COUNT_ADDRESS, count);
    count += 1;
    EEPROM.put(COUNT_ADDRESS, count);
    // Update the display with the latest count value.
    update_display();
  }

  // Reset the hold start if the button wasn't pressed (i.e. first and last were not both high levels).
  if ((firstCount != HIGH) || (secondCount != HIGH)) {
    holdStart = millis();
  }

  // Check if the button has been held for the amount of reset time.
  if ((RESET_HOLD_SECONDS > 0) && ((millis() - holdStart) >= (RESET_HOLD_SECONDS*1000))) {
    // Reset to zero and update the display!
    uint16_t count = 0;
    EEPROM.put(COUNT_ADDRESS, count);
    update_display();
    // Reset the hold time to start over again.
    holdStart = millis();
    // Flash the display a few times to give time to remove finger.
    for (int i=0; i<5; ++i) {
      delay(200);
      backpack.clear();
      backpack.writeDisplay();
      delay(200);
      update_display();
    }
  }
}
This guide was first published on Mar 13, 2016. It was last updated on Mar 13, 2016.
This page (Software) was last updated on Jul 18, 2020.