Project tutorial

Arduino Mutitasking: Clock + Stopwatch + Timer © CC BY-NC-ND

This project is about an Arduino running a digital clock, a stopwatch, and a timer simultaneously!

  • 6,862 views
  • 10 comments
  • 43 respects

Components and supplies

Apps and online services

About this project

1) Introduction

This project is about a digital clock plus a stopwatch (hundredths of seconds) and a timer (1 to 99 minutes) for Arduino.

Everything working simultaneuouly using only the internal clock of Arduino with excelent accuracy for non professional applications!!

It is an interesting use of multitasking with a single microcontroler and simple functions like millis().

Video

Video Description (Portuguese Version)

Video (Stopwatch - Comparative Test)

2) Material

  • Arduino UNO-R3
  • Multi-Function Shield

The Multi-Function Shield is used to simplify and speed up the prototype development.

Main features:

  • 4 digit 7-segment LED display module driven by two serial 74HC595's
  • 4 x surface mount LED's in a parallel configuration
  • 10K adjustable precision potentiometer
  • 3 x independent push buttons
  • Piezo buzzer
  • DS18B20 temperature sensor interface
  • LM35 temperature sensor interface
  • Infrared receiver interface
  • Serial interface header for convenient connection to serial modules such as Bluetooth, wireless interface, voice module, a voice recognition module, etc.

3) Computer Multitasking

There is a good explanation about Computer Multitasking at Wikipedia:

"In computing, multitasking is the concurrent execution of multiple tasks (also known as processes) over a certain period of time. New tasks can interrupt already started ones before they finish, instead of waiting for them to end."

"Multitasking does not require parallel execution of multiple tasks at exactly the same time; instead, it allows more than one task to advance over a given period of time. Even on multiprocessor computers, multitasking allows many more tasks to be run than there are CPUs."

The two ways of applying multitasking to the Arduino are using interrupts and millis() function.

The function millis()"Returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days."

The main difference between delay() and millis() is that with the first, you wait for a certain period of time and with the second, you know how much time has passed.

Using millis() it is possible to control multiple events only by monitoring the time between start and stop of all procedures.

For example, when the procedure of stopwatch starts to run, a variable is set to initial time in miliseconds and then is calculated the difference between the current time read by millis() and the initial time.

And the same is for the timer procedure.

void readKey() {
 // Initial time for Stopwatch
 if (key1) {
  startStopwatchTime = millis();
 }
 // Initial time for Timer
 if (key2) {
  startTimerTime = millis();
 }
}
void loop() {
 // Stopwatch Mode
 if (mode == 1) {
  currentStopwatchTime = millis() - startStopwatchTime;
 }
 // Timer Mode
 if (mode == 2) {                  
  currentTimerTime = millis() - startTimerTime;
 }
}

Repeating this process is possible to move to different routines keeping all information about the lapse time of them.

Every time when a routine is restarted, the lapse time is updated considering the current millis() and the initial reference time.

This is the magic provided by the clock of microprocessor.

4) Setup of Device

- Hour Mode

  • Hour (0 to 23): press the Left button to add 1 hour.
  • Minute (0 to 59): press the Middle button to add 1 minute.
  • Next Mode: press the Right button to move to Stopwatch mode.

- StopwatchMode

  • Start/Stop: press the Left button to start or to stop the stopwatch.
  • Lapse Time: press the Middle button when stopwatch is running.
  • Reset: press the Middle button to reset the stopwatch when it is stopped.
  • Next Mode: press the Right button to move to Timer mode.

Notes:

  • The total time of the stopwatch is 299.99 seconds (5 minutes).
  • After 99.99 seconds, a second dot of display is shown (first at right) to indicate the virtual digit "1" to count until 199.99 seconds.
  • After 199.99 seconds, a third dot is shown to symbolize the virtual digit "2" to count until 299.99 seconds.

- TimerMode:

  • Start/Reset: press the Left button to start or to reset the timer.
  • Set timer: press the Middle button to adjust the total time (1 to 99 minutes).
  • Next Mode: press the Right button to move to Hour mode.

Notes:

  • When the countdown time is completed, a buzzer starts a warning sound.
  • The warning buzzer works in all modes.
  • The buzzer can be turned off only in the Timer mode.

Code

Stopwatch_and_Digital_Clock_with_Multi_Shield_V1_4.inoArduino
Coding for Arduino UNO-R3 & Multi-Function Shield
/*   Project:   Stopwatch and Digital Clock

     Hardware:  Arduino UNO-R3 & Multi-Shield
     Author:    LAGSILVA
     Date:      30.Sep.2018
     Version:   V1.4
*/

#include <Time.h>                               // Time library
#include <TimeLib.h>
#include <MsTimer2.h>                           // Timer library

// Module connection pins (Digital Pins)
#define LATCH_PIN 4                             // Arduino UNO conection on Pin #4  = Latch of Display Module
#define CLK_PIN 7                               // Arduino UNO conection on Pin #7  = Clock of Display Module
#define DATA_PIN 8                              // Arduino UNO conection on Pin #8  = Data of Display Module

#define BTN_1_PIN A1
#define BTN_2_PIN A2
#define BTN_3_PIN A3

//    Display:

//        A
//      ----
//   F |    | B
//      -G -
//   E |    | C
//      ----
//       D

//   Chars Code
byte N[] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6, 0xC6};

byte mode = 0;
int chrono, countdown, minutoCount = 1, segundoCount = 0, hora = 0, minuto = 0, minutoStart = 1;
unsigned long tiChrono, tiCountdown, lastT, diffTime = 0, lastTime = 0;
boolean ajustaHora = true, ajustaMinuto = true, chronograph = true;
boolean startChrono = false, startCountdown = false;
boolean lap = false;
boolean buzzerStatus = false;


void setup() {

  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);

  pinMode(BTN_1_PIN, INPUT);
  pinMode(BTN_2_PIN, INPUT);
  pinMode(BTN_3_PIN, INPUT);

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  pinMode(3, OUTPUT);                                       // Buzzer pin
  digitalWrite(3, HIGH);                                    // Buzzer off

  MsTimer2::set(130, kbdRead);                              // Timer library for buttons reading
  MsTimer2::start();

}


void loop() {

  if (mode == 0) {                                          // Clock Mode

    int hora = hour();
    int minuto = minute();

    int dezenaHora = hora / 10;
    int unidadeHora = hora % 10;
    int dezenaMinuto = minuto / 10;
    int unidadeMinuto = minuto % 10;

    displayChars(N[dezenaHora], 0);                         // Display Digit 0
    displayChars(N[unidadeHora], 1);                        // Display Digit 1
    displayChars(N[dezenaMinuto], 2);                       // Display Digit 2
    displayChars(N[unidadeMinuto], 3);                      // Display Digit 3
    displayChars(1, 1);                                     // Display Dot at Digit 2
    displayChars(1, 3);                                     // Display Dot at Digit 4
    displayChars(0, 3);                                     // Reset Dot at Digit 4

    buzzer();

  }


  if (mode == 1) {                                                // Chronograph Mode

    if (startChrono == true && lap == false) {                    // Start Chronograph
      chrono = ((millis() - tiChrono) / 10 + lastT);
      diffTime = chrono - lastTime;
    }

    int tempChrono = chrono % 10000;

    if (startChrono == false && lap == false) {                   // Stop Chronograph
      tiChrono = millis();
      lastT = chrono;
      lastTime = 0;
    }

    if (startChrono == false && lap == true) {                    // Stop Chronograph and exit LAP (lapse time) mode
      chrono = ((millis() - tiChrono) / 10 + lastT) % 10000;
      lap = false;
    }

    if (startChrono == true && lap == true) {                     // Start LAP (lapse time) mode
      lastTime = chrono;
      chrono = diffTime;
    }

    if (chrono >= 29999) {
      startChrono = false;
      tempChrono = 9999;
    }

    int dezenaSeg = tempChrono / 1000;
    int unidadeSeg = tempChrono / 100 % 10;
    int dezenaCentesimo = tempChrono % 100 / 10;
    int unidadeCentesimo = tempChrono % 10;

    displayChars(N[dezenaSeg], 0);                         // Display Digit 0
    displayChars(N[unidadeSeg], 1);                        // Display Digit 1
    displayChars(N[dezenaCentesimo], 2);                   // Display Digit 2
    displayChars(N[unidadeCentesimo], 3);                  // Display Digit 3
    displayChars(1, 1);                                    // Display Dot at Digit 2
    displayChars(0, 1);                                    // Reset Dot at Digit 2

    if (chrono > 9999) {
      displayChars(1, 3);                                  // Display Dot at Digit 4 (>=100s)
      displayChars(0, 3);                                  // Reset Dot at Digit 4 (>=100s)
    }
    else {
      displayChars(0, 3);                                  // Reset Display Dot at Digit 4
    }

    if (chrono > 19999) {
      displayChars(1, 2);                                  // Display Dot at Digit 3 (>=200s)
      displayChars(0, 2);                                  // Reset Dot at Digit 3 (>=200s)
    }
    else {
      displayChars(0, 2);                                  // Reset Display Dot at Digit 4
    }

    buzzer();

  }


  if (mode == 2) {                                          // Countdown Mode

    if (startCountdown == true) {
      countdown = (millis() - tiCountdown) / 1000;
      minutoCount = (minutoStart * 60 - countdown) / 60;
      segundoCount = (minutoStart * 60 - countdown) % 60;
    }

    if (startCountdown == false) {
      tiCountdown = millis();
      minutoCount = minutoStart;
      segundoCount = 0;
      buzzerStatus = false;
    }

    if (minutoCount >= 0 && segundoCount >= 0) {
      int dezenaMinuto = minutoCount / 10;
      int unidadeMinuto = minutoCount % 10;
      int dezenaSegundo = segundoCount / 10;
      int unidadeSegundo = segundoCount % 10;

      displayChars(N[dezenaMinuto], 0);                     // Display Digit 0
      displayChars(N[unidadeMinuto], 1);                    // Display Digit 1
      displayChars(N[dezenaSegundo], 2);                    // Display Digit 2
      displayChars(N[unidadeSegundo], 3);                   // Display Digit 3
      displayChars(1, 1);                                   // Display Dot at Digit 2
      displayChars(0, 1);                                   // Reset Dot at Digit 2
    }
    else {
      displayChars(1, 0);                                   // Display Dot at Digit 0
      displayChars(1, 1);                                   // Display Dot at Digit 1
      displayChars(1, 2);                                   // Display Dot at Digit 2
      displayChars(1, 3);                                   // Display Dot at Digit 3
      displayChars(0, 3);                                   // Reset Dot at Digit 3

      buzzerStatus = true;                                  // Start buzzer alarm
    }

    buzzer();

  }

}


void displayChars(byte num, byte disp) {                    // Chars Display Routine

  byte k, charsM = 0;

  charsM = num;

  digitalWrite(LATCH_PIN, LOW);
  shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, ~charsM);           // Display number
  shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, 128 >> disp);       // Set Digits (0-1-2-3)
  digitalWrite(LATCH_PIN, HIGH);

}


void kbdRead() {                                                  // Push Buttons Reading

  ajustaHora = digitalRead(BTN_1_PIN);
  ajustaMinuto = digitalRead(BTN_2_PIN);
  chronograph = digitalRead(BTN_3_PIN);

  if (!chronograph) {                                             // Set Mode (Clock = 0 / Chronograph = 1 / Countdown = 2)
    mode = (mode + 1) % 3;
  }

  if (!ajustaHora && mode == 0) {                                 // Set Hour
    adjustTime(3600);
  }

  if (!ajustaMinuto && mode == 0) {                               // Set Minute
    adjustTime(60);
  }

  if (!ajustaHora && mode == 1) {                                 // Chronograph Status (Start = TRUE / Stop = FALSE)
    startChrono = !startChrono;
  }

  if (!ajustaMinuto && mode == 1 && startChrono == true) {        // Chronograph in mode LAP (Lapse Time)
    lap = !lap;
    lastTime = 0;
  }

  if (!ajustaMinuto && mode == 1 && startChrono == false) {       // Reset Chronograph
    chrono = 0;
    startChrono = false;
  }

  if (!ajustaHora && mode == 2) {                                 // Start Countdown
    startCountdown = !startCountdown;
  }

  if (!ajustaMinuto && mode == 2 && startCountdown == false) {    // Set Countdown time
    minutoStart = constrain((minutoStart + 1) % 100, 1, 99);
    segundoCount = 0;
  }

}


void buzzer() {                                                   // Buzzer Alarm

  if (startCountdown == true) {
    countdown = (millis() - tiCountdown) / 1000;
    minutoCount = (minutoStart * 60 - countdown) / 60;
    segundoCount = (minutoStart * 60 - countdown) % 60;
  }

  if (minutoCount == 0 && segundoCount == 0) {                    // Start buzzer alarm
    buzzerStatus = true;
  }

  if (buzzerStatus == true) {                                     // Buzzer alarm on
    digitalWrite(3, LOW);
    delayMicroseconds(50);
    digitalWrite(3, HIGH);
    delay(50);
  }

}

Comments

Similar projects you might like

Amazing Binary Clock using LED Matrix Module

Project tutorial by LAGSILVA

  • 9,351 views
  • 10 comments
  • 50 respects

Analog Clock with LED Matrix and Arduino

Project tutorial by LAGSILVA

  • 12,237 views
  • 8 comments
  • 39 respects

4-Stroke Digital Clock With Arduino

Project showcase by LAGSILVA

  • 11,103 views
  • 9 comments
  • 39 respects

(Updated) Digital Clock w/ Mirrored Display for UNO-R3 & 101

Project tutorial by LAGSILVA

  • 993 views
  • 0 comments
  • 3 respects

Digital & Binary Clock In 8 Digits x 7 Segments LED Display

Project showcase by LAGSILVA

  • 1,827 views
  • 2 comments
  • 9 respects

Digital Clock with Arduino, RTC and Shift Register 74HC595

Project tutorial by LAGSILVA

  • 20,727 views
  • 16 comments
  • 46 respects
Add projectSign up / Login