Arduino : Timer with 7 Segment displays

Aims

Components

Circuit Diagram

Breadboard view of the circuit: arduino_timer_1_bb.pdf

Schematic of the timer circuit: arduino_timer_1_schem.pdf

Warning

These circuit diagrams are correct except for one thing: I have not checked to see if the 7 segment wiring order is compatible with the order in which the digits are defined in the code. You many need to alter the order of the black wires to make these compatible. Or, alternatively, alter the code!

Procedure & Codes

/*
 * Timer : Lap mode.
 * Press Start once to start timer.
 * Stop will stop the display but not the timer.
 *   Stop pressed again will reset to 0.
 *   Start pressed after a single stop will re-start timer
 *   display. 
 */
 
byte digits[10][8] = { { 1,1,1,1,1,1,0,0 },  // = 0
                       { 0,1,1,0,0,0,0,0 },  // = 1
                       { 1,1,0,1,1,0,1,0 },  // = 2
                       { 1,1,1,1,0,0,1,0 },  // = 3
                       { 0,1,1,0,0,1,1,0 },  // = 4
                       { 1,0,1,1,0,1,1,0 },  // = 5
                       { 1,0,1,1,1,1,1,0 },  // = 6
                       { 1,1,1,0,0,0,0,0 },  // = 7
                       { 1,1,1,1,1,1,1,0 },  // = 8
                       { 1,1,1,0,0,1,1,0 }   // = 9
                     };

int segmentPins[] = {2,3,4,5,6,7,8,9};
int displayPins[] = {10,11};
int numSegments = 8; 
int numDisplays = 2;
int startPin = 12;
int stopPin = 13;

int time = 0;
boolean timerStarted = false;
int timeUnits = 100; // in MS

void setup()
{  
  for (int i=0; i < numSegments; i++)
  {
    pinMode(segmentPins[i], OUTPUT);
  }
  for (int i=0; i < numDisplays; i++)
  {
    pinMode(displayPins[i], OUTPUT);
  }
  digitalWrite(displayPins[0], HIGH);
  digitalWrite(displayPins[1], HIGH);
  
  // Define the Start and Stop pins. We use internall PULLUP resisitors
  // so the switches can be connected directly, i.e., without resistors.
  pinMode(startPin,INPUT_PULLUP);
  pinMode(stopPin,INPUT_PULLUP);
  
  // Serial port:
  Serial.begin(9600);  // Output to Serial
  while (! Serial);    // Wait untilSerial is ready
  Serial.println("Timer:");

}

void writeDot(byte dot) {
  digitalWrite(segmentPins[7], dot);
}
    
void sevenSegWrite(byte digit) {
  byte pin = 2;
  for (byte segCount = 0; segCount < 7; ++segCount) {
    digitalWrite(pin, digits[digit][segCount]);
    ++pin;
  }
}

void loop()
{
  boolean startTimer = not digitalRead(startPin);
  boolean stopTimer = not digitalRead(stopPin);
  
  //Serial.print("Start timer = ");
  //Serial.print(startTimer);
  //Serial.print("  Stop timer = ");
  //Serial.println(stopTimer);
  
  if (startTimer && not timerStarted)
  {
    //Serial.println("Start Timer");
    time = updateTime(time,true);
    timerStarted = true;
    //delay(1);
  }
  if (stopTimer)
  {
    if (timerStarted)
    {
      //Serial.println("Stop Timer");
      timerStarted = false;
      //updateDisplay(time);
      delay(500); // We need a reasonable delay else multiple
                  // key presses are recorded.
    }
    else
    {
      // Reset the time
      time = 0;
      updateDisplay(time);
    }
  }
  
  updateDisplay(time);
  
  if (timerStarted)
  {
    time = updateTime(time,false);
  }
}

void updateDisplay(int time)
{
  int units = time % 10;
  int tens  = time / 10;
  setDigit(0);
  setSegments(units);
  delay(5);
  setDigit(1);
  setSegments(tens);
  delay(5);
}

int updateTime(int time, boolean reset)
{
  // Update time using function millis() that returns the time since
  // code was run in milliseconds.
  static unsigned long lastMilliS; //this should be initialised to 0
  unsigned long currMilliS = millis();
  
  //Serial.print("Time (before) = ");
  //Serial.println(time);
  if (reset)
  {
    lastMilliS = currMilliS;
  }
  
  if ((currMilliS > (lastMilliS + timeUnits)) && (time < 100))
  {
    // More than 1 sec has passed since the last call. So we need to update 
    // the time. 
    // Calculate the real time passed. It could, in principle, be more
    // than 1 sec. This could be the case if the main loop() included a 
    // lot of operations or delay() statements. In these cases, the time could
    // be updated by more than 1 sec. We therefore need to check to make sure 
    // we do not get less than 0.
    int timePassed = (currMilliS - lastMilliS)/timeUnits;
    time += timePassed;
    if (Serial.available())                    // In general, output to Serial
    {                                          // only if input is detected.
      Serial.print("Time = ");
      Serial.print(time);
      Serial.print("  timePassed = ");
      Serial.println(timePassed);
    }
    // Update the value of lastMilliS:
    lastMilliS = currMilliS;
  }
  else if (time > 99 )
  {
    time = 0;
  } 
  if (Serial.available())                    // In general, output to Serial
  {                                          // only if input is detected.
    Serial.print("Time = ");
    Serial.println(time);
  }
  return time;
}

void setDigit(int digit)
{
  for (int i=0; i < numDisplays; i++)
  {
    digitalWrite(displayPins[i], (digit != i));
  }
}

void setSegments(int n)
{
  for (int i=0; i < numSegments; i++)
  {
    digitalWrite(segmentPins[i],  digits[n][i]);
  }
}

AJMPublic/teaching/arduino-pi/projects/arduino/timer (last edited 2021-04-14 13:18:27 by apw109)