Mission 23 · Stage 3

Stopwatch

millis() arithmetic for elapsed time

Store elapsed time in variables using millis() and print seconds on Serial.

Stopwatch circuit diagram

Pin connections

Part 1Part 2

Pushbutton

pin 1

Arduino

pin 2

Pushbutton

pin 2

Arduino

GND

See it

Make a real stopwatch!

Press once to start, press again to stop — the screen counts the seconds for you.

Sports timers and kitchen timers work the very same way.

The story

The problem

The board needs to remember when you started and whether the timer is running.

Think of it like

It's like a stopwatch on a phone — it remembers the moment you pressed start.

Meet the parts

It keeps the time and watches the button.

Arduino

The brain

Loading part…

How it works

1

Did you press the button?

When you press, we start or stop the timer.

if (digitalRead(BUTTON_PIN) == LOW)
2

Start or stop

running flips between yes and no. When it turns on, we remember the start time in startMs.

running = !running;
if (running) startMs = millis();
3

Show the time

While running, we take the clock now minus startMs to get the seconds, and show them.

unsigned long elapsed = millis() - startMs;
Serial.print(elapsed / 1000.0, 2);

Then loop back to step 1

Build the circuit

Follow these steps in order. Match the wires to the colors shown.

  1. 1

    Place Arduino

    Place the Arduino (uno) on the breadboard.

    Arduino placed — ready to time!

    Loading part…

Try it

  • Press the button once to start — the screen shows the seconds counting up.
  • Press again to stop and see your final time.

Peek at code

The timer boxes

const int BUTTON_PIN = 2;
unsigned long startMs = 0;
bool running = false;

startMs remembers when you started, and running tells us if the timer is ticking.

Start and stop on a press

    if (running) {
      startMs = millis();
      Serial.println("Started!");
    } else {
      unsigned long elapsed = millis() - startMs;
      Serial.print("Stopped at ");
      Serial.print(elapsed / 1000.0, 2);
      Serial.println(" seconds");
    }
    while (digitalRead(BUTTON_PIN) == LOW) {
      delay(20);
    }
  }
  if (running) {

A press flips running and either saves the start time or shows the final time.

The time ticking up

    Serial.print("Time: ");
    Serial.print(elapsed / 1000.0, 2);
    Serial.println(" s");
    delay(500);
  }
  delay(20);
}

While running is yes, loop() keeps showing the time as it grows.

Show full sketch (stopwatch.ino)
const int BUTTON_PIN = 2;
unsigned long startMs = 0;
bool running = false;
void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Stopwatch — press button to start/stop");
}
void loop() {
  if (digitalRead(BUTTON_PIN) == LOW) {
    running = !running;
    if (running) {
      startMs = millis();
      Serial.println("Started!");
    } else {
      unsigned long elapsed = millis() - startMs;
      Serial.print("Stopped at ");
      Serial.print(elapsed / 1000.0, 2);
      Serial.println(" seconds");
    }
    while (digitalRead(BUTTON_PIN) == LOW) {
      delay(20);
    }
  }
  if (running) {
    unsigned long elapsed = millis() - startMs;
    Serial.print("Time: ");
    Serial.print(elapsed / 1000.0, 2);
    Serial.println(" s");
    delay(500);
  }
  delay(20);
}

Quick quiz

Q1. What is a variable?

  • A. A named box that stores a value
  • B. A kind of wire
  • C. Just a wait
Why: Yes! A variable is a named box, like startMs holding the start time.

Q2. What does startMs = millis() save?

  • A. The moment the stopwatch started
  • B. The final score
  • C. The button pin number
Why: Yes! startMs remembers the moment the timer turned on.

Code lab — try on your own

  1. Make the loop rest a little longer — change delay(20) to delay(40) at the very end of loop().

    Hint: Line 32, the last line of loop().

  2. Add a note (comment) on the startMs = millis() line that says it remembers the start time.

    Hint: Line 13.

Code walkthrough

A line-by-line tour of the sketch — the same steps as in Robot Gurukul Studio.

Program overview

Big idea

Every Arduino program has a top part, a setup() part that runs once, and a loop() part that runs again and again.

In this project

A button starts and stops a timer, and the screen shows the seconds counting up.

Tip

Read from the top to the bottom. Tap any word or line if you need help!

const int BUTTON_PIN = 2;
unsigned long startMs = 0;
bool running = false;

setup()

Big idea

setup() runs one time when the board turns on.

In this project

It gets the button on pin 2 ready and opens the message screen.

Why here

Things we do only once go inside setup().

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Stopwatch — press button to start/stop");
}

loop()

Big idea

loop() runs again and again, forever.

In this project

This is where we watch the button and show the timer counting up.

Why here

Things that repeat go inside loop().

void loop() {
  if (digitalRead(BUTTON_PIN) == LOW) {
    running = !running;
    if (running) {
      startMs = millis();
      Serial.println("Started!");
    } else {
      unsigned long elapsed = millis() - startMs;
      Serial.print("Stopped at ");
      Serial.print(elapsed / 1000.0, 2);
      Serial.println(" seconds");
    }
    while (digitalRead(BUTTON_PIN) == LOW) {
      delay(20);
    }
  }
  if (running) {
    unsigned long elapsed = millis() - startMs;
    Serial.print("Time: ");
    Serial.print(elapsed / 1000.0, 2);
    Serial.println(" s");
    delay(500);
  }
  delay(20);
}

Try this: Change a number inside loop(), then press Run to see what happens.

pinMode

Big idea

pinMode tells a pin if it will listen or push power out.

In this project

It sets pin 2 to listen for the button press.

Why here

It goes in setup() because we only set it once.

  pinMode(BUTTON_PIN, INPUT_PULLUP);

digitalRead

Big idea

digitalRead checks if a pin is ON or OFF.

In this project

It checks if the button is being pressed.

Why here

It goes in loop() so we can react the moment you press.

  if (digitalRead(BUTTON_PIN) == LOW) {

delay

Big idea

delay means wait. Nothing else happens while it waits.

In this project

A tiny wait helps the button read cleanly.

Why here

Right after we check the button.

      delay(20);

millis

Big idea

millis() is a clock that counts how long the board has been awake, in tiny pieces of a second.

In this project

We use it to figure out how much time has passed.

Why here

In loop() when we need to know the time.

      startMs = millis();

begin

Big idea

Serial.begin opens a message screen so the board can talk to the computer.

In this project

It lets us print the timer.

Why here

It goes in setup() once, before we print anything.

  Serial.begin(9600);

print

Big idea

Serial.print writes words or a number on the screen and stays on the same line.

In this project

It writes the time so far on the same line.

Why here

In loop() so we can see the time tick up.

      Serial.print("Stopped at ");

println

Big idea

Serial.println writes on the screen and then jumps to a new line.

In this project

It prints a friendly hello when the board turns on.

Why here

So each message gets its own line.

  Serial.println("Stopwatch — press button to start/stop");