Button code that can control a function (start, pause and reset)

Hello all

I am looking to do something ordinary that controls the extra ordinary. But I need some good button code to do it. I am looking to have two buttons control a 4 digit 7 segment display that is a board with 4 pins ( CLK, DI0, GND, 5V+) It uses the tm1637.h header file for control. I have got it working but I now need button code to start and stop it as well as reset it with a second button. My buttons are wire correctly and are working here is my wiring diagram

I have code that starts up and runs the timer just fine just need to control it and use the buttons to manipulate it, I am just a hobby guy who has no scholastic programming experience just good with circuits and computers, so I would really appreciate the help. the LED’s and buzzer can be ignored at this point just want the control of the display with the two buttons, a start stop button and a reset button. Here is the code so far and I know that the button code is the simplest control a LED code from the beginners book.

#include <TimerOne.h>
#include "TM1637.h"
#define ON 1
#define OFF 0

int8_t TimeDisp[] = {0x00,0x00,0x00,0x00};
unsigned char ClockPoint = 1;
unsigned char Update;
unsigned char halfsecond = 0;
unsigned char second = 0;
unsigned char minute = 0;
unsigned char hour = 12;

const int buttonPin = 8;
const int buttonPin2 = 9;
int buttonState = 0;
int buttonState2 = 0;
  
#define CLK 3//pins definitions for TM1637 and can be changed to other ports
#define DIO 2
TM1637 tm1637(CLK,DIO);

void setup()
{
  pinMode(buttonPin, INPUT);
  pinMode(buttonPin2, INPUT);
  tm1637.set();
  tm1637.init();
  Timer1.initialize(500000);//timing for 500ms
  Timer1.attachInterrupt(TimingISR);//declare the interrupt serve routine:TimingISR
}
void loop(){
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH){
    clockwork();
  }
  else {
    clockwork();
  }
}




void clockwork(){
  (Update == ON);{
    TimeUpdate();
    tm1637.display(TimeDisp);
  }
}


void TimingISR()
{
  halfsecond ++;
  Update = ON;
  if(halfsecond == 2){
    second ++;
    if(second == 60)
    {
      minute ++;
      if(minute == 60)
      {
        hour ++;
        if(hour == 24)hour = 0;
        minute = 0;
      }
      second = 0;
    }
    halfsecond = 0;
  }
 // Serial.println(second);
  ClockPoint = (~ClockPoint) & 0x01;
}
void TimeUpdate(void)
{
  if(ClockPoint)tm1637.point(POINT_ON);
  else tm1637.point(POINT_OFF);
  TimeDisp[0] = minute / 10;
  TimeDisp[1] = minute % 10;
  TimeDisp[2] = second / 10;
  TimeDisp[3] = second % 10;
  Update = ON;
}

So any button code that can start and stop this clockwork(); function would be great. I am sure others could be helped by a solution because these new seven segment displays are cheap and available and make wiring so easy. Thanks again and God bless you and all people on the earth, those that belong to Christ Jesus Lord over many Gentiles as well as others and their gods.

MoJoeRedRog

If you format your code with the auto format function (ctrl-T), you may be surprised

#include <TimerOne.h>
#include "TM1637.h"
#define ON 1
#define OFF 0

int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
unsigned char ClockPoint = 1;
unsigned char Update;
unsigned char halfsecond = 0;
unsigned char second = 0;
unsigned char minute = 0;
unsigned char hour = 12;

const int buttonPin = 8;
const int buttonPin2 = 9;
int buttonState = 0;
int buttonState2 = 0;

#define CLK 3//pins definitions for TM1637 and can be changed to other ports
#define DIO 2
TM1637 tm1637(CLK, DIO);

void setup()
{
  pinMode(buttonPin, INPUT);
  pinMode(buttonPin2, INPUT);
  tm1637.set();
  tm1637.init();
  Timer1.initialize(500000);//timing for 500ms
  Timer1.attachInterrupt(TimingISR);//declare the interrupt serve routine:TimingISR
}


void loop() {
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
    clockwork();
  }
  else {
    clockwork();
  }
}

void clockwork() {
  Update == ON
  TimeUpdate();
  tm1637.display(TimeDisp);
}


void TimingISR()
{
  halfsecond++;
  Update = ON;
  if (halfsecond == 2) {
    second ++;
    if (second == 60)
    {
      minute++;
      if (minute == 60)
      {
        hour++;
        if (hour == 24)
          hour = 0;
        minute = 0;
      }
      second = 0;
    }
    halfsecond = 0;
  }
  // Serial.println(second);
  ClockPoint = (~ClockPoint) & 0x01;
}


void TimeUpdate(void)
{
  if (ClockPoint)
    tm1637.point(POINT_ON);
  else
    tm1637.point(POINT_OFF);
  TimeDisp[0] = minute / 10;
  TimeDisp[1] = minute % 10;
  TimeDisp[2] = second / 10;
  TimeDisp[3] = second % 10;
  Update = ON;
}

Also, every variable used inside yoru ISR should be declared as ‘volatile’ so the compiler does the right thing.

blh64:
Also, every variable used inside yoru ISR should be declared as ‘volatile’ so the compiler does the right thing.

Thanks for that formatting instruction. I did as you said. Still I have no working button code. I tried some simple stuff but cant get it to work. I am pretty sure this display clockwork() function needs to constantly refresh in the loop to keep time. Not sure how to do that and have it ready to stop with a button. I am going to start messing around with some debouncing that I found on hackster io. Here is my code so far:)

#include <Bounce2.h>    //a debouncing library
#include <TimerOne.h>   //the timers library
#include "TM1637.h"     //the 4-digit-7 seg display library
#define ON 1
#define OFF 0

int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
volatile char ClockPoint = 1;
volatile char Update;
volatile char halfsecond = 0;
volatile char second = 0;
volatile char minute = 0;
volatile char hour = 12;

const byte startButton = 8;         //my buttons
Bounce startDebouncer1 = Bounce();
const byte resetButton = 9;
Bounce resetDebouncer2 = Bounce();


#define CLK 3   //pins definitions for TM1637 and can be changed to other ports
#define DIO 2
TM1637 tm1637(CLK, DIO);

void setup()
{
  pinMode(startButton, INPUT_PULLUP);     //Button setup for both buttons
  startDebouncer1.attach(startButton);
  startDebouncer1.interval(1); //debouncer time in ms
  pinMode(resetButton, INPUT_PULLUP);
  resetDebouncer2.attach(resetButton);
  resetDebouncer2.interval(1);
  tm1637.set();                   //display set up and initialization
  tm1637.init();
  Timer1.initialize(500000);//timing for 500ms starting the timer
  Timer1.attachInterrupt(TimingISR);//declare the interrupt serve routine:TimingISR
}

bool startState = LOW;
bool resetState = LOW;


void loop() {

  clockwork();    //in this state it makes the display count by the second
  //up to the 99th minute


}

void clockstop() {  //Not sure if this would stop the clock
  //or not, tried it doesn't work but still need better button code
  //right now there is no button code.

  (Update == OFF); {
    TimeUpdate();
    tm1637.display(TimeDisp);
  }
}



void clockwork() {   //The function that starts and runs the clock
  //needs to be running all the time the clock
  //is on.
  (Update == ON); {
    TimeUpdate();
    tm1637.display(TimeDisp);
  }
}


void TimingISR()  //Not exactly sure what this does.
//included in the sample code for the display
{
  halfsecond ++;
  Update = ON;
  if (halfsecond == 2) {
    second ++;
    if (second == 60)
    {
      minute ++;
      if (minute == 60)
      {
        hour ++;
        if (hour == 24)hour = 0;
        minute = 0;
      }
      second = 0;
    }
    halfsecond = 0;
  }
  // Serial.println(second);
  ClockPoint = (~ClockPoint) & 0x01;
}
void TimeUpdate(void)              //this is more code for the display
{
  if (ClockPoint)tm1637.point(POINT_ON);
  else tm1637.point(POINT_OFF);
  TimeDisp[0] = minute / 10;
  TimeDisp[1] = minute % 10;
  TimeDisp[2] = second / 10;
  TimeDisp[3] = second % 10;
  Update = ON;
}

If any body can share some of their genius with me and get me up and running I would really appreciate it. I really like this seven segment display it looks great and what better use than a stop watch. or a Bomb timmer but I gave up the G - had in the last life ROFL (sorry not sure if that’s allow) only kidding I am a Canadian Greek the only bombs I know are that legal cannabis.

Cheers and thanks for any help

Did you look at any of the examples that came with the bounce2 library? They show you how to use it. Also, you should move all your update code out of your ISR so everything doesn’t need to be volatile.

Try this (untested)

#include <Bounce2.h>    //a debouncing library
#include <TimerOne.h>   //the timers library
#include "TM1637.h"     //the 4-digit-7 seg display library
#define ON 1
#define OFF 0

int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
bool ClockPoint = true;
volatile bool Update;

char halfsecond = 0;
char second = 0;
char minute = 0;
char hour = 12;

const byte startButtonPin = 8;         //my buttons
const byte resetButtonPin = 9;
Bounce startDeButton = Bounce();
Bounce resetButton = Bounce();


#define CLK 3   //pins definitions for TM1637 and can be changed to other ports
#define DIO 2
TM1637 tm1637(CLK, DIO);

void setup()
{
  pinMode(startButtonPin, INPUT_PULLUP);     //Button setup for both buttons
  startButton.attach(startButtonPin);
  startButton.interval(25); //debouncer time in ms
  pinMode(resetButtonPin, INPUT_PULLUP);
  resetButton.attach(resetButtonPin);
  resetButton.interval(25);
  tm1637.set();                   //display set up and initialization
  tm1637.init();
  Timer1.initialize(500000);//timing for 500ms starting the timer
  Timer1.attachInterrupt(TimingISR);//declare the interrupt serve routine:TimingISR
  resetClock();
}

bool running = false;

void loop() {

  startButton.update();
  resetButton.update();

  if ( startButton.fell() ) {
    // start button was pressed, (HIGH to LOW) so toggle running mode
    running = !running;
  }

  if ( resetButton.fell() ) {
    // reset button was pressed, reset clock
    resetClock();
  }

  if ( Update == true && running == true ) {
    // time to update the clock if we are are running
    Update = false;
    timeUpdate();
    displayTime();
  }
}


void displayTime() {

  if (ClockPoint) {
    tm1637.point(POINT_ON);
  }
  else {
    tm1637.point(POINT_OFF);
  }
  TimeDisp[0] = minute / 10;
  TimeDisp[1] = minute % 10;
  TimeDisp[2] = second / 10;
  TimeDisp[3] = second % 10;
  tm1637.display(TimeDisp);
}


void TimingISR() {
  // time for a half second time advance
  Update = true;
}

void timeUpdate(void) {
  halfsecond++;
  if (halfsecond == 2) {
    halfsecond = 0;
    second++;
    if (second == 60) {
      second = 0;
      minute++;
      if (minute == 60) {
        minute = 0;
        hour++;
        if (hour == 24) {
          hour = 0;
        }
      }
    }
  }
  // Serial.println(second);
  ClockPoint = !ClockPoint;
}

void resetClock() {
  second = 0;
  minute = 0;
  hour = 12;
  displayTime();
}

blh64:
Did you look at any of the examples that came with the bounce2 library? They show you how to use it. Also, you should move all your update code out of your ISR so everything doesn't need to be volatile.

I tried your code and it works perfect. Thank you kindly for all the assistance on this one. I still have more functions to add to the project before its done but the heavy lifting I believe is now finished. Glory to your God for he is good :slight_smile:

Thanks a million blh64 I added the buzzer easily and also the RBG Leds. now Its time to finish soldering my LED strand and making my enclosure. If any one is interested here is the final code for the complete working project.

include <FastLED.h>    //Library for the RGB LED's
#include <Bounce2.h>    //a debouncing library
#include <TimerOne.h>   //the timers library
#include "TM1637.h"     //the 4-digit-7 seg display library
#define ON 1
#define OFF 0

#define PIN_STRIP1 7      //Declarations for the Leds
#define COLOR_ORDER RGB
#define LED_TYPE WS2812
#define NUM_LEDS 8
int NumStrip1 = 0;
uint8_t max_bright = 255;
struct CRGB leds1[NUM_LEDS];

#define NOTE_D5 587  //music notes for buzzer
#define NOTE_G5 784

int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00};
bool ClockPoint = true;
volatile bool Update;

char halfsecond = 0;
char second = 0;
char minute = 0;
char hour = 12;

const byte startButtonPin = 8;         //my buttons
const byte resetButtonPin = 9;
Bounce startButton = Bounce();
Bounce resetButton = Bounce();

const byte buzzer = 12;

#define CLK 3   //pins definitions for TM1637 and can be changed to other ports
#define DIO 2
TM1637 tm1637(CLK, DIO);

void setup()
{
  LEDS.addLeds<LED_TYPE, PIN_STRIP1, COLOR_ORDER>(leds1, NUM_LEDS);   //Leds startup code
  FastLED.setBrightness(max_bright);
  FastLED.clear();
  FastLED.show();
  pinMode(startButtonPin, INPUT_PULLUP);     //Button setup for both buttons
  startButton.attach(startButtonPin);
  startButton.interval(25); //debouncer time in ms
  pinMode(resetButtonPin, INPUT_PULLUP);
  resetButton.attach(resetButtonPin);
  resetButton.interval(25);
  pinMode(buzzer, OUTPUT);
  tm1637.set();                   //display set up and initialization
  tm1637.init();
  Timer1.initialize(500000);//timing for 500ms starting the timer
  Timer1.attachInterrupt(TimingISR);//declare the interrupt serve routine:TimingISR
  resetClock();
}

bool running = false;

void loop() {

  startButton.update();
  resetButton.update();

  if ( startButton.fell() ) {
    // start button was pressed, (HIGH to LOW) so toggle running mode
    ledsStart();  //lights up green
    buzz();       //a simple buzzer
    running = !running;
  }

  if ( resetButton.fell() ) {
    // reset button was pressed, reset clock
    ledsReset();        //runs the function to light leds
    buzz2();            //a simple buzzer
    resetClock();
  }

  if ( Update == true && running == true ) {
    // time to update the clock if we are are running
    Update = false;
    timeUpdate();
    displayTime();
  }
}

void ResetStrips () {
  FastLED.clear();
  NumStrip1 = 0;
  FastLED.show();
}

void displayTime() {

  if (ClockPoint) {
    tm1637.point(POINT_ON);
  }
  else {
    tm1637.point(POINT_OFF);
  }
  TimeDisp[0] = minute / 10;
  TimeDisp[1] = minute % 10;
  TimeDisp[2] = second / 10;
  TimeDisp[3] = second % 10;
  tm1637.display(TimeDisp);
}


void TimingISR() {
  // time for a half second time advance
  Update = true;
}

void timeUpdate(void) {
  halfsecond++;
  if (halfsecond == 2) {
    halfsecond = 0;
    second++;
    if (second == 60) {
      second = 0;
      minute++;
      if (minute == 60) {
        minute = 0;
        hour++;
        if (hour == 24) {
          hour = 0;
        }
      }
    }
  }
  // Serial.println(second);
  ClockPoint = !ClockPoint;
}

void resetClock() {
  second = 0;
  minute = 0;
  hour = 12;
  displayTime();
}

void buzz() {  //buzzer code
  tone(buzzer, NOTE_D5);
  delay(300);
  noTone(buzzer);
}

void buzz2() {  //buzzer code
  tone(buzzer, NOTE_G5);
  delay(700);
  noTone(buzzer);
}

void ledsStart() {          //Turns on the Leds, mine go Green :)
  leds1[3] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[2] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[1] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[0] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[4] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[5] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[6] = CRGB::Red;
  FastLED.show();
  delay(1);
  leds1[7] = CRGB::Red;
  FastLED.show();
  delay(1);
}


void ledsReset() {        //Turns the Leds red
  leds1[3] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[2] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[1] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[0] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[4] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[5] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[6] = CRGB::Green;
  FastLED.show();
  delay(1);
  leds1[7] = CRGB::Green;
  FastLED.show();
  delay(1);
}

Again thanks BLH64 could not have done it with out your help and the grace of the Lord Jesus Christ.:slight_smile:

Cheers!

If you led colors are not coming out correctly, you have the wrong order specified in your definition

#define COLOR_ORDER GRB

That is the order for neopixels.

Also, if you want your buttons to be responsive all the time, don’t use delay() inside your buzz() and buzz2() functions. Take a look at the BlinkWithoutDelay example for how to do timing without blocking on a delay() call.

It might not matter in this case, but a good technique to learn.

1 Like