How to implement pushbuttons into a stopwatch

Hello @johnwasser ,

I'm trying out this code.

I didn't find to buy 2x units of CI 7447, only one. So, I had to adapt your program in order to build a stopwatch only with 1 digit.

I've tested it and unofrtunatelly it didn't work. When I load the program into Arduino nothing happens with the display as well as when I press on the buttons (as shown in the photo).

Could You please help me to check if I re-wrote the right program considering only one display 7 segment?

  // This is where you would put your code to display the time
  byte seconds = displayTime / 1000;
  byte unitsDigit = seconds % 10;

  // Units Digit
  digitalWrite(6, unitsDigit & 0x01);  // Low bit
  digitalWrite(7, unitsDigit & 0x02);
  digitalWrite(8, unitsDigit & 0x04);
  digitalWrite(9, unitsDigit & 0x08);  // High bit
}

Thank you in advance.

The CI7447 has Open Collector outputs so it only works with Common Anode displays. Your wiring diagram shows your displays being used as Common Cathode displays. That is a hardware problem and no amount of software is going to fix it.

But I wired it as anode comum, in VCC:

@fermatias
If I'm allowed to give some directive advice

8 days have passed by until you posted your next question.
I don't know what you have done in these 8 days.

I highest recommend that you work on this project 5 to 8 hours for the next 8 days !
todays sunday 11.12.2022
monday 12.12.2022
tuesday 13.12.2022
wednesday 14.12.2022
thursday 15.12.2022
friday 16.12.2022
saturday 17.12.2022
sunday 18.12.2022

as you have experienced now for the second time
it is not done by finding a code, buying similar hardware, upload the online found code.

You have still such a huge lack of programming-knowledge and electronics-knowledge that you will need each and every minute to learn and proceed.

If you have luck it might be done within 8 to 9 hours. But I would not rely on hoping this.

How many times need you to be told to post the

complete and actual sketch ??

best regards Stefan

That's not what the wiring diagram in your initial post shows.

Were you ever able to get the display to show digits?

Yes, in the real situation I had to wire it differently, because I got a Anode Comum Display and used CI7747 instead of CI5411.

Yes, With simple counter program 0-9 it works normally. But as I said, I tried to implement your program only with 1 digit and it does not work. Maybe will it work only with 2 digits as your first program?

The software doesn't care if the hardware exists or not. The first program should have worked with one display, or two displays, or even no displays.

Perhaps you have made a mistake somewhere. Please show your entire sketch.

Here the real sketch about what was built:

That is a "schematic". An Arduino program is called a "sketch".

Your schematic looks correct to me. Now show the Arduino program (the 'sketch').

Here the 'sketch':

/////////////////////////////////////
//  Stopwatch Example
//
//  Written by: John Wasser
/////////////////////////////////////
const byte StartButtonPin = A1;  // Button wired from pin to GND
const byte StopResetButtonPin = A2; // Button wired from pin to GND
bool StartButtonWasPressed = false;
bool StopResetButtonWasPressed = false;

unsigned long DebounceTimer = 0;
const unsigned DebounceTime = 10;

bool IsRunning = false;
unsigned long ElapsedTime = 0;
unsigned long LastStartTime = 0;

static void ShowTheTime()
{
  static unsigned long lastDisplayTime = 0;
  unsigned long displayTime = ElapsedTime;
  if (IsRunning)
    displayTime += millis() - LastStartTime;

  if (displayTime != lastDisplayTime)
  {
    lastDisplayTime = displayTime;

  // This is where you would put your code to display the time
  byte seconds = displayTime / 1000;
  byte unitsDigit = seconds % 10;

  // Units Digit
  digitalWrite(6, unitsDigit & 0x01);  // Low bit
  digitalWrite(7, unitsDigit & 0x02);
  digitalWrite(8, unitsDigit & 0x04);
  digitalWrite(9, unitsDigit & 0x08);  // High bit
}
}
void setup()
{
  delay(200);

  pinMode(StartButtonPin, INPUT_PULLUP);
  pinMode(StopResetButtonPin, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentTime = millis();

  bool startButtonIsPressed = digitalRead(StartButtonPin) == LOW;
  bool stopResetButtonIsPressed = digitalRead(StopResetButtonPin) == LOW;

  // State Change Detection and debounce
  if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StartButtonWasPressed = startButtonIsPressed;
    DebounceTimer = currentTime;

    if (startButtonIsPressed)
    {
      // Just Pressed START
      if (!IsRunning)
      {
        // Starting/Restarting the timer
        LastStartTime = currentTime;
        IsRunning = true;
      }
      else
      {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
    }
  }

  // State Change Detection and debounce
  if (stopResetButtonIsPressed != StopResetButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StopResetButtonWasPressed = stopResetButtonIsPressed;
    DebounceTimer = currentTime;

    if (stopResetButtonIsPressed)
    {
      // Just Pressed STOP/RESET
      if (IsRunning)
      {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
      else
      {
        // Was not running so reset everything
        ElapsedTime = 0;
        IsRunning = false;
      }
    }
  }

  ShowTheTime();
}

very well done drawing the schematic by hand.
well done posting the code (the "sketch")

Do you have a digital multimeter? If Yes this would be very good for measuring.

Do you have a single LED and a resistor in the range of 220 Ohms up to 680 Ohms?
This LED could be used as a simple "logic analyser" if an output is switched HIGH LED lights up or LOW led stays off.

Another way of analysing is to add serial output for debugging

Hi @johnwasser

Your code is a very good example to show how far the "expert blindness for beginner difficulties" is going and how much this impacts easyness of understanding:

I added outputting the "elapsedtime" to the serial monitor but the time is not updating while the stop-watch is running.

I'm a pretty experienced programmer and still had difficulties to understand the logic of your code by reading it. Why the heck does elapsedtime not update???

So I added my own variables to make it happen.

Now imagine a beginner: How should a beginner ever come behind why elapsedtime is not updating inside the added function that simply prints elapsedtime to the serial monitor???

Here is my code-version

void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;

const unsigned long ReadyToStart = 1000;
const unsigned long WatchRunning = 50;
const unsigned long WatchStopped = 250;

unsigned long myStartTime;
unsigned long myStopTime;

unsigned long BlinkPeriod;

void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

/////////////////////////////////////
//  Stopwatch Example
//
//  Written by: John Wasser
/////////////////////////////////////
const byte StartButtonPin = A1;  // Button wired from pin to GND
const byte StopResetButtonPin = A2; // Button wired from pin to GND
bool StartButtonWasPressed = false;
bool StopResetButtonWasPressed = false;

unsigned long DebounceTimer = 0;
const unsigned DebounceTime = 10;

bool IsRunning = false;
unsigned long ElapsedTime = 0;
unsigned long LastStartTime = 0;

unsigned long PrintTimer = 0;

void ClearSerialMonitor() {
  for (int i = 0; i < 50; i++) {
    Serial.println();
  }
}

void ShowTimeInSerialMonitor() {
  static unsigned long myElapsedTime;

  if (IsRunning) {
    myElapsedTime = millis() - myStartTime;
  }
  else {
    myElapsedTime = myStopTime - myStartTime;    
  }

  
  if ( TimePeriodIsOver(PrintTimer,100) ) {
    ClearSerialMonitor();

    Serial.print("Johns ElapsedTime: ");
    Serial.print(ElapsedTime);
    Serial.println("  milliseconds");
    
    Serial.print("myElapsedTime: ");
    Serial.print(myElapsedTime);
    Serial.println("  milliseconds");
}  
}

static void ShowTheTime() {
  ShowTimeInSerialMonitor();
  
  static unsigned long lastDisplayTime = 0;
  unsigned long displayTime = ElapsedTime;
  if (IsRunning)
    displayTime += millis() - LastStartTime;
    
  if (displayTime != lastDisplayTime) {
    lastDisplayTime = displayTime;
    // This is where you would put your code to display the time
    byte seconds = displayTime / 1000;
    byte unitsDigit = seconds % 10;
    // Units Digit
    digitalWrite(6, unitsDigit & 0x01);  // Low bit
    digitalWrite(7, unitsDigit & 0x02);
    digitalWrite(8, unitsDigit & 0x04);
    digitalWrite(9, unitsDigit & 0x08);  // High bit
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();
  delay(200);
  pinMode(StartButtonPin, INPUT_PULLUP);
  pinMode(StopResetButtonPin, INPUT_PULLUP);
  BlinkPeriod = ReadyToStart;
}


void loop() {
  BlinkHeartBeatLED(OnBoard_LED, BlinkPeriod);
  
  unsigned long currentTime = millis();
  bool startButtonIsPressed = digitalRead(StartButtonPin) == LOW;
  bool stopResetButtonIsPressed = digitalRead(StopResetButtonPin) == LOW;
  
  // State Change Detection and debounce
  if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime) {
    // Button has changed state
    StartButtonWasPressed = startButtonIsPressed;
    DebounceTimer = currentTime;
    if (startButtonIsPressed) {
      myStartTime = millis();
      BlinkPeriod = WatchRunning; // added for debugging
      // Just Pressed START
      if (!IsRunning) {
        // Starting/Restarting the timer
        LastStartTime = currentTime;
        IsRunning = true;
      }
      else {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
    }
  }
  
  // State Change Detection and debounce
  if (stopResetButtonIsPressed != StopResetButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime) {
    // Button has changed state
    StopResetButtonWasPressed = stopResetButtonIsPressed;
    DebounceTimer = currentTime;
    if (stopResetButtonIsPressed) {
      BlinkPeriod = WatchStopped; // added for debugging
      myStopTime = millis();
      // Just Pressed STOP/RESET
      if (IsRunning) {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
      else {
        // Was not running so reset everything
        ElapsedTime = 0;
        myStartTime = 0;
        myStopTime  = 0;
        IsRunning = false;
        BlinkPeriod = ReadyToStart; // added for debugging
      }
    }
  }
  ShowTheTime();
}

additionally this part of your code

  // State Change Detection and debounce
  if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime) {
    // Button has changed state
    StartButtonWasPressed = startButtonIsPressed;
    DebounceTimer = currentTime;
    if (startButtonIsPressed) {
      myStartTime = millis();
      BlinkPeriod = WatchRunning; // added for debugging
      // Just Pressed START
      if (!IsRunning) {
        // Starting/Restarting the timer
        LastStartTime = currentTime;
        IsRunning = true;
      }
      else {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
    }
  }

is mixing debouncing and some other logic.
me personal I think the code would become easier to understand if there are functions
that do one thing

one function check for button-press including debouncing

another function only doing stop-watch logic.

as similar as possible as handling a "classical" stop-watch

pressing start which makes "something run"
pressing stop which stops "the running" (= stops the counting up)

best regards Stefan

You just forgot to set the pin mode on your output pins.

Add these to setup():

  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

Hi @johnwasser ,
Thanks, now it works.

My last question would be it: How Can I limit the display in any number? For example, I would like to limite the stopwatch from "0" to "5", instead of "0" to "9" repeatly.

Thank You.

@fermatias

Now you ask like you know really nothing about coding.

You should at least post your own try how this might be done

After having googled with words like "Arduino limit value "

byte unitsDigit = seconds % 10;
changes to
byte unitsDigit = seconds % 6;

Hi @johnwasser , thank you so much for your help with this case.

Now I will continue with my studies and understand as best as I can what was posted here by you as well as others.

Att.
Fernando Matias

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.