60 Second Count Up Timer Help

Hi,

I am trying to make a timer based on a 2-digit 7-segment display. When a signal is sent from a reed or hall switch, I want the timer to start counting up from 00 in one second increments until the magnetic switch signal is turned off (whether the timer counts to 60 or 99 is largely irrelevant). Ideally, when the magnetic switch is turned off, the display would hold the ending value for a period of 10 seconds and then go blank waiting to be activated again from 00 on the next actuation.

The parts I ordered are:

  1. Arduino Nano
  2. A3144 Hall Effect Sensor
  3. Common Cathode 10 Pin 2 Bit 7 Segment Led Display Red
  4. Reed Sensor Module Magnetic Switch Module Normally Open

If anyone could help me out with the code and the best way to implement this idea it would be a massive help.

triggered, timer start counting, don’t stop till triggered to stop.

Ok so there is this thing called millis() that counts the number of milli seconds the MCU has been running. A 1000 millis equals one second.

triggered, store current millis(). when stop trigger comes in, elapsed time equals millis() -storedmillis.

Find the tutorials on this site about using millis() for timing and millis() for doing several things at the same time.

You made it hard for yourself by choosing a display that has no controller IC. Now you are going to have to write code to time multiplex the two digits…

I’ll admit I don’t know what a controller IC is. I chose the display that I did because of the size and format. I am trying to mount the display into the paddle handle of an espresso machine so size and form was a constraining factor for me. That said, if you know of a 2-digit 7 segment display which would make my life easier, I am more than willing to swap out the one I currently have.

An example: Driving 7-segment Displays with MAX7219 - LinkIt 7697 for Arduino

Here is a sketch I wrote to drive a raw 4-digit 7-segment display. Perhaps parts of it can be of use to you:

// Bit maps for the seven segment display

// Segment Cathodes (0/LOW for on, 1/HIGH for off)
const byte Segments[] =
{
  0b11000000, // 0
  0b11001111, // 1
  0b10100100, // 2
  0b10000110, // 3
  0b10001011, // 4
  0b10010010, // 5
  0b10010000, // 6
  0b11000111, // 7
  0b10000000, // 8
  0b10000011, // 9
};

const byte ColonLowerDot = 12;
const byte ColonUpperDot = 13;

// List of digit select lines, least significant digit first
// Digit Common Anodes (HIGH for on, LOW for off)
const byte DigitCount = 4;
const byte DigitPins[DigitCount] = {A0, 2, 3, 4};

// Segment Cathodes (LOW for on, HIGH for off)
const byte SegmentCount = 7;
const unsigned char SegmentPins[SegmentCount] = {5, 6, 7, 8, 9, 10, 11};

void setup()
{
  for (int i = 0; i < DigitCount; i++)
  {
    pinMode(DigitPins[i], OUTPUT);
    digitalWrite(DigitPins[i], LOW);
  }

  for (int i = 0; i < SegmentCount; i++)
  {
    pinMode(SegmentPins[i], OUTPUT);
    digitalWrite(SegmentPins[i], HIGH);
  }

  digitalWrite(ColonLowerDot, HIGH);
  digitalWrite(ColonUpperDot, HIGH);

  pinMode(ColonLowerDot, OUTPUT);
  pinMode(ColonUpperDot, OUTPUT);
}

void loop()
{
  // Get time since last reset
  unsigned long hundredths = millis() / 10;
  unsigned long seconds = hundredths / 100;
  unsigned long minutes = seconds / 60;
  int hours = minutes / 60;
  int clock;

  if (seconds < 100)
    // Display seconds.hundredths up to 100 seconds, then minutes:seconds
    clock = (seconds % 100) * 100 + (hundredths % 100);
  else if (minutes < 100)
    // Display minutes:seconds up to 100 minutes, then hours/minutes
    clock = (minutes % 100) * 100 + (seconds % 60);
  else
    clock = (hours % 100) * 100 + (minutes % 60);

  // Clear all segments before enabling a digit
  for (int s = 0; s < SegmentCount; s++)
  {
    digitalWrite(SegmentPins[s], HIGH);
  }

  // Display each digit, right to left
  for (int i = 0; i < DigitCount; i++)
  {
    // Peel a digit off the low end of the number
    int digit = clock % 10;
    clock /= 10;

    // Blank the MSD if it is zero
    if (i == 3 && digit == 0)
    {
      for (int s = 0; s < SegmentCount; s++)
        digitalWrite(SegmentPins[s], HIGH);
    }
    else
    {
      // Display the digit on the seven segments
      unsigned char segments = Segments[digit];
      for (int s = 0; s < SegmentCount; s++)
      {
        digitalWrite(SegmentPins[s], segments & 1);
        segments >>= 1;
      }
    }

    if (seconds < 100)
    {
      // Steady decimal point when showing seconds and hundredths
      digitalWrite(ColonLowerDot, HIGH);
      digitalWrite(ColonUpperDot, LOW);
    }
    else if (minutes < 100)
    {
      // Steady colon when showing minutes and seconds
      digitalWrite(ColonLowerDot, LOW);
      digitalWrite(ColonUpperDot, LOW);
    }
    else
    {
      // Make the colon blink each second
      digitalWrite(ColonLowerDot, seconds & 1);
      digitalWrite(ColonUpperDot, seconds & 1);
    }

    // Turn on the digit briefly
    digitalWrite(DigitPins[i], HIGH);  // Select one digit
    delayMicroseconds(3000UL);  // Higher numbers give higher brightness but more flicker
    digitalWrite(DigitPins[i], LOW);
  }
}
1 Like

Ok, so I grabbed a 4 digit I2C display that and I have a program for a stopwatch which counts to 60:00 seconds and repeats.

Stopwatch.ino (4.7 KB)

This program has Start, Pause and Reset Functions which can be executed by entering S,P,R into the serial monitor.

I found a second program for a pushbutton and wired the pushbutton to pin 7 on the Arduino but I have absolutely no clue how I would combine these programs to start the timer when the button is pressed and to pause the program after the button is released.

button.ino (641 Bytes)

Is there a simple way to do this?

startcounting button pin attached as an interrupt.
stopcounting button pin attached as interrupt.

have a global declared startcounting = true set in the button push isr.
have a global declared stopcounting = true set in the button push isr.

in loop()

if(statcounting) start the count

if(stopcounting) stop the count, set the startbutton = false, set the stopcounting = false do the thing with your time figuring.

Here is an example stopwatch sketch that I wrote. It uses a Start button and a Stop/Reset button. It should be easy to either pause or fully reset the timer when the Start button is released.

/////////////////////////////////////
//  Stopwatch Example
//
//  Written by: John Wasser
/////////////////////////////////////

const byte StartButtonPin = 2;  // Button wired from pin to GND
const byte StopResetButtonPin = 3; // 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;

void setup()
{
  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;
      }
    }
  }

  // Get time since last reset
  unsigned long DisplayTime;
  if (IsRunning)
    DisplayTime = ElapsedTime + (currentTime - LastStartTime);
  else
    DisplayTime = ElapsedTime;

////////////////
// Add code here to display "DisplayTime" which is a number of 
// milliseconds.
///////////////
}
1 Like

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