Timer function problems

Hey guys,

I'm making a 3-step automated process which includes a timer. The timer() function skips the seconds for which it has been idle for. for example, if I were selecting the process for 15 seconds, when the timer() function begins, the countdown decreases by 15 seconds very quickly then starts counting down normally. How can I fix this? Sorry for the wall of code, I omitted a few functions to keep the post <9000 characters

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd (0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

//#define are constant variables which take up no memory
#define washLimSwitch 7 
#define dryerRelay 8
#define toasterOvenRelay 9
#define tempSwitch 10
#define goButton 11
#define selectButton 12
#define stopButton 2
#define thermistor A7
#define pot A3

bool goBit = 0, stopBit = 0; //Must use these instead of using digitalRead inside of functions (shit may get weird if you do)

byte process, processStep, selection;

double tempC, tempF;

unsigned int minutes;

unsigned long seconds,
              lastTick; 
              
long msTime; //has to be signed for error code purposes

const char *processArray[] = { //somehow, the only way to call a string array is to make it a pointer. Don't ask how, it just works.
                               "Washing",
                               "Drying",
                               "Curing"
                             };

const int    SAMPLE_NUMBER      = 10;


const double seriesRes  = 98200.0;

const double MAX_ADC            = 1023.0;

const double BETA               = 3950.0;

const double ROOM_TEMP          = 295.15;   // room temperature in Kelvin

const double RESISTOR_ROOM_TEMP = 115100.0;

byte menuSelect();

double getTemp(); //returns C

void timeSet(bool jumpToSixty);

unsigned long timer();

void cureStation();

void dryStation();

void washStation();

void setup() {

  //The three buttons
  pinMode(goButton, INPUT);
  pinMode(selectButton, INPUT);
  pinMode(stopButton, INPUT);

  //60 or 80 switch
  pinMode(tempSwitch, INPUT);

  pinMode(pot, INPUT);
  pinMode(thermistor, INPUT);
  
  pinMode(dryerRelay, OUTPUT);
  pinMode(toasterOvenRelay, OUTPUT);

  Serial.begin(9600);

  //initialize LCD
  lcd.begin(16,2);
  lcd.clear();
}

void loop() {
  process = menuSelect();

  if(digitalRead(goButton) == 1 && digitalRead(stopButton) == 0 && digitalRead(selectButton) == 0)
  {
   delay(500); //so pressing the go button at the main menu doesn't automatically start
   
   switch (process)
   {
     case 1: //washing
     {
      lcd.clear();
      timeSet(0);

      if(digitalRead(stopButton) == 1)
      break;
      
      washStation();
      selection++; //automatically goes to next step
      break;
     }
    case 2: //drying
     {
      lcd.clear();
      timeSet(0);
      
      if(digitalRead(stopButton) == 1)
      break;
      
      dryStation();
      selection++;
      break;
     }
    case 3: //curing
     {
      lcd.clear();
      timeSet(1);

      if(digitalRead(stopButton) == 1)
      break;
      
      cureStation();
      selection++;
      break;
     }
     default:
     {
      lcd.clear();
      lcd.print("Error - please");
      lcd.setCursor(0,1);
      lcd.print("make selection");
      delay(1000);
     }
   }
  }
  else
  {
    lcd.clear();
    do {
     lcd.print("Make a selection");
     lcd.setCursor(0,1);
  
     if(process == 1)
     {
      lcd.print("1 - washing      ");
     }
     else if(process == 2)
     {
      lcd.print("2 - drying      ");
     }
     else if(process == 3)
     {
      lcd.print("3 - curing      ");
     }
     else
     {
      lcd.print("Nothing selected");
     }
    }while(digitalRead(goButton) == 0 && digitalRead(selectButton) == 0);
  }
}

byte menuSelect()
{
  
  if(digitalRead(selectButton) == HIGH)
  {
    selection ++;
    delay(250);
  }

  if(selection >= 4)
  {
    selection = 1;
  }
  
  return selection;
}

void washStation()
{
  unsigned long countDown;
  processStep = 0;

  do
  {
    stopBit = digitalRead(stopButton);
    
    countDown = timer();
    
    printTime(countDown, 0);
         
  }while(msTime >= 1000 && stopBit == 0);
}

void dryStation()
{
  processStep = 1;
  
  do
  {
    stopBit = digitalRead(stopButton);
    
    msTime = timer();
      
    printTime(msTime, 0);
      
  }while(msTime >= 1000 && stopBit == 0);
}

void cureStation()
{
  processStep = 2;

  do
    {
      stopBit = digitalRead(stopButton);

      msTime = timer();
      
      printTime(msTime, 1);
      
    }while(msTime >= 1000 && stopBit == 0);
}

double getTemp() //returns C
{
  
}

void timeSet(bool jumpToSixty)
{
  byte fiveMinTime;
  int potVal, constrainedTime;
  
  delay(1000); //so you don't immediately start the processes by holding GO
  
  switch(process)
  {
    case 1: //washing; time = 5m -> 25m, 5m inc
    {
      do
      {
        goBit = digitalRead(goButton);
        stopBit = digitalRead(stopButton);
        
        potVal = analogRead(pot);
        constrainedTime = constrain(potVal, 0, 900);
        fiveMinTime = map(constrainedTime, 0, 900, 0, 4);
        minutes = map(fiveMinTime, 0, 4, 5, 25);
      
        lcd.clear();
        lcd.print("Set time: ");
        lcd.print(minutes);
        lcd.print(":00 ");
        delay(100);
        
        }while(goBit == 0 && stopBit == 0);

      msTime = minutes * 60000;
      seconds = (msTime / 1000) - (minutes * 60);
        
      break;
    } 
      
    case 2: //drying; time = 1m -> 5m, 1m inc
    {
      do
      {
        goBit = digitalRead(goButton);
        stopBit = digitalRead(stopButton);
        
        potVal = analogRead(pot);
        constrainedTime = constrain(potVal, 0, 900);
        minutes = map(constrainedTime,0, 900, 1, 5);

        lcd.clear();
        lcd.print("Set time: ");
        lcd.print(minutes);
        lcd.print(":00 ");
                        
        delay(100);
        
      }while(goBit == 0 && stopBit == 0);
      
      msTime = minutes * 60000;
      seconds = (msTime / 1000) - (minutes * 60);
        
      break;
    }
      
    case 3://curing; time = 10m -> 30m, 5m inc then jumpToSixty
    {
      do
      {
        goBit = digitalRead(goButton);
        stopBit = digitalRead(stopButton);
        
        potVal = analogRead(pot);
        constrainedTime = constrain(potVal, 0, 900); //change these values when using different value pots
        fiveMinTime = map(constrainedTime, 0, 900, 0, 5);
        minutes = map(fiveMinTime, 0, 5, 10, 35); 
        while(jumpToSixty == 1)
        {
          if(minutes > 30)
          {
            minutes = 60;
            break;
          }
          else
          break;
        }
      
        lcd.clear();
        lcd.print("Set time: ");
        lcd.print(minutes);
        lcd.print(":00 ");
        
        delay(100);

        }while(goBit == 0 && stopBit == 0);

        msTime = minutes * 60000;
        seconds = (msTime / 1000) - (minutes * 60);
        
        break;
      }
      
    default:
    {
      lcd.clear();
      do
      {
        lcd.print("Select Station");
      }while(
              digitalRead(goButton == 0) 
              || digitalRead(stopButton == 0) 
              || digitalRead(selectButton == 0)
            );
     
      break;
    }
  }  
}

unsigned long timer()
{  
  unsigned long currentMillis = millis();
  
  if(currentMillis - lastTick >= 1000)
  {
    msTime -= 1000; 
    lastTick += 1000; 
  }

  return(msTime);
}

void printTime(long milliseconds, bool printTemp) //there are no hours because the highest this project will go is 60 minutes
{
  seconds = milliseconds / 1000;
  minutes = seconds / 60;
  seconds = seconds - (minutes * 60);
  
      if(printTemp == 1)
      {
        tempC = getTemp();
        
        lcd.clear();
        lcd.print(processArray[processStep]);
        lcd.print(" - ");
        lcd.print(minutes);
        lcd.print(":");
        lcd.print(seconds);

        lcd.setCursor(0, 1);
        lcd.print(tempC);
        lcd.print((char)223); //degrees symbol
        lcd.print("C");
        delay(100);
      }
      else
      {
        lcd.clear();
        lcd.print(processArray[processStep]);
        lcd.print(" - ");
        lcd.print(minutes);
        lcd.print(":");
        lcd.print(seconds); 
        delay(100);
      }
}
//somehow, the only way to call a string array is to make it a pointer. Don't ask how, it just works.

You don't call an item in an array. A string is an array of characters. You could make a 2D array to hold the characters, or you could, as you are doing, make an array of pointers.

Understanding pointers is what distinguishes a real programmer from a wanna-be.

timer() is a really lousy name for that function. It doesn't time anything. A better name is certainly in order, and might reveal the problem.

Why does the function return the value of a global variable?

Personally, I would NOT be trying to count down in seconds. Time passes, on the Arduino, in milliseconds (or microseconds). Count the milliseconds that have passed. If it is necessary to display the (remaining) time to the user, THEN convert the remaining time to seconds and milliseconds.

seems to count (time) normally for me?

yes a string is an array, an array variable by itself is a pointer to the first location of the array, so an array of strings is really an array of pointers to string arrays.