Go Down

Topic: Pausing a Countdown Timer using Switch Case and A Rotary Encoder (Read 1 time) previous topic - next topic

sholland91

Hello, I am working on making a countdown timer using a rotary encoder and a 7 segment 4 digit led display.
The program works as follows:
Case 1: Set Time
     - Rotate encoder to change seconds and minutes on display
     - If the encoder is pressed in, switch to the Run Timer Case
Case 2: Run Timer
     - Counts down from the time set in Case 1
     - If the encoder is pressed in, switch to the Pause Timer Case
Case 3: Pause Timer
     - Stop the timer from counting down.
     - Rotate encoder to change seconds and minutes on display
     - If the encoder is pressed in, switch to the Run Timer Case

Case 1 and 2 work perfectly. Pausing the timer allows me to change the values of the timer. When I press the encoder in again, however, the timer jumps to how many seconds have elapsed.
ie. If I pause the timer at 1:30 and wait 25 seconds before pressing the encoder again, the display quickly counts down from 1:30 to 1:05 and then continues to count as usual. If I wait more than 1:30, the timer speeds all the way down to 0.

I have tried to store my seconds and minutes values as new integers while the encoder is pressed, and then reassign the values when I press the encoder again. This does nothing though.
Below is the snippet of code that's not working. "mode = " is my switch case command.
Code: [Select]

void ReadEncoder() //Reads the State of the Encoder and adjust the Display accordingly. CW rotation = + "increment" seconds, CCW = - "increment" seconds
{
  int Position, Press;
  seconds = constrain (seconds, -1, 60); //constrains the seconds value between -1 and 60

    _ResetPins();
  _lowlevel_ReadEncoder(Position, Press);
  int Position2, Press2;
  do
  {
    _lowlevel_ReadEncoder(Position2, Press2);
  }
  while ((Position2 == Position) && (Press2 == Press));
  if (Position2 != Position) //if there is a poisition change:
  {
    // "Forward" is shown by the position going from (0 to 1) or (1 to 3)
    // or (3 to 2) or (2 to 0).  Anything else indicates that the user is
    // turning the device the other way.  Remember: this is Gray code, not
    // binary.
    int isFwd = ((Position == 0) && (Position2 == 1)) ||
      ((Position == 1) && (Position2 == 3)) ||
      ((Position == 3) && (Position2 == 2)) ||
      ((Position == 2) && (Position2 == 0));
    delay(Encoder_Sensitivity);
    if (isFwd == 1) //if Encoder is moved forwards (CW), advance seconds by defined increment value
    {
      seconds= seconds + increment;
    }
    if (isFwd == 0) // if encoder is moved backwards(CCW):
    {
      if (seconds == 0)// if we are already at zero seconds, check to make sure we can reduce a minute
      {
        if (minutes > 0)// if the minutes can be reduced (i.e. not zero) then remove one minute and reset seconds to 59
        {       
          minutes --;
          seconds = 60-increment;
        }
      }
      else
      {
        seconds = seconds - increment;//if seconds were not = 0, then decrease seconds value by the increment value
      }
    }
  }

  if (seconds>59)    // When seconds = 60:
  {
    minutes++;          // Add one minute
    seconds -= 60;      // Reset seconds
  }

  if (Press2 != Press) //if the encoder is pressed down:
  {
    delay(Press_Sensitivity);
    mode = Run_Timer;
  }
  Position = Position2;
  Press = Press2;

  Serial7Segment.print('v');
  sprintf(tempString, "%02d%02d", minutes, seconds);
  Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S
  Serial.println(tempString);
}

//-------------------------------------------------------------------------------------------------
void countdownTimer() //this will start counting down from the time set using the encoder. This begins when the encoder button is pressed.
{
  seconds = constrain (seconds, -1, 60);
  if( (millis() - millisTimer) > 1000)
  {
    millisTimer += 1000; //Adjust the timer forward 1 second
    if (seconds == 0)// if we are already at zero seconds, check to make sure we can reduce a minute
    {
      if (minutes > 0)// if the minutes can be reduced (i.e. not zero) then remove one minute and reset seconds to 59
      {       
        minutes --;
        seconds = 59;
      }
    }
    else{
      seconds--;//if seconds were not = 0, then decrease seconds value by the increment value
    }
    sprintf(tempString, "%02d%02d", minutes, seconds);
    Serial7Segment.write(0x77);  // Decimal, colon, apostrophe control command
    Serial7Segment.write(1<<COLON); // Turns on colon, apostrophoe, and far-right decimal
    Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S

    Serial.println(tempString);
  }

  if (minutes == 0 & seconds == 0)
  {
    digitalWrite(Relay, LOW);
    Serial7Segment.print("0000"); //Send the hour and minutes to the display
    mode = Set_Timer;
  }

  if (digitalRead(Encoder_Press)== LOW)
  {
    delay(Press_Sensitivity);
    mode = Pause_Timer;
  }
}

//-----------------------------------------------------------------------------------------
void PauseTimer()
{
  seconds_hold = seconds;
  minutes_hold = minutes;

  sprintf(tempString, "%02d%02d", minutes_hold, seconds_hold);
  Serial7Segment.write(0x77);  // Decimal, colon, apostrophe control command
  Serial7Segment.write(1<<COLON); // Turns on colon, apostrophoe, and far-right decimal
  Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S

  if (digitalRead(Encoder_Press) == LOW)
  {
    delay(Press_Sensitivity);
    seconds = seconds_hold;
    minutes = minutes_hold; 
    mode = Run_Timer;
  }

  mode = Set_Timer;
}


Any thoughts?
Thanks!

sholland91

And here is my entire code:
Code: [Select]
#include <SoftwareSerial.h>

//CONFIGURATION:
/// Pins From Components to Arduino:///
const int LCD_SS = 8;           //SS On LCD Board
const int LCD_RX = 7;           //RX On LCD Board
const int Encoder_A = 14;       //3rd Pin on the Top of Potentiometer to A0 on Arduino
const int Encoder_B = 15;       //1st Pin on the Top of Potentiometer to A1 on Arduino
const int Encoder_Press = 12;   //1st Pin on Bottom of Potentiometer
const int MagSwitch= 13;        //Either Lead from Magnet Switch
const int Relay = 2;            //CTRL from Relay Board

/// Other Setup Information:_________________________
// - VCC from LCD Board to 5v                        //
// - GND from LCD Board to Ground                    //
// - 1st Pin on Bottom of Potentiometer to Ground    //
// - 2nd Pin of Potentiometer to Ground              //
// - Other Lead of Magnet Switch to Ground           //
// - 5V of Relay Board to 5V                         //
// - GND of Relay Baord to Ground                    //
//___________________________________________________//

// VARIABLES:
const int increment = 30; //change this value to change the seconds increment when setting the timer
const int Encoder_Sensitivity = 150;
const int Press_Sensitivity = 150;

//////////////////////////////////////////////////////////////////////////////////////////////////////
SoftwareSerial Serial7Segment(LCD_SS, LCD_RX);
#define COLON       4
char tempString[4];

long millisTimer;
byte seconds = 00;
byte minutes = 00;

int mode = 0;
#define Set_Timer   0
#define Run_Timer   1
#define Pause_Timer 2

int seconds_hold;
int minutes_hold;

//---------------------------------------------------------------------------------------
static void _ResetPins()
{
  pinMode(Encoder_A, INPUT);
  digitalWrite(Encoder_A, HIGH);

  pinMode(Encoder_B, INPUT);
  digitalWrite(Encoder_B, HIGH);

  pinMode(Encoder_Press, INPUT);
  digitalWrite(Encoder_Press, HIGH);

  Serial7Segment.write(0x77);  // Decimal, colon, apostrophe control command
  Serial7Segment.write(1<<COLON);
}

//---------------------------------------------------------------------------------------
void _lowlevel_ReadEncoder(int &rotate, int& press)
{
  rotate = (digitalRead(Encoder_B) * 2) + digitalRead(Encoder_A);
  press = digitalRead(Encoder_Press);
}

//-----------------------------------------------------------------------------------------
void SetTimer() //Reads the State of the Encoder and adjust the Display accordingly. CW rotation = + "increment" seconds, CCW = - "increment" seconds
{
  int Position, Press;
  seconds = constrain (seconds, -1, 60); //constrains the seconds value between -1 and 60

    _ResetPins();
  _lowlevel_ReadEncoder(Position, Press);
  int Position2, Press2;
  do
  {
    _lowlevel_ReadEncoder(Position2, Press2);
  }
  while ((Position2 == Position) && (Press2 == Press));
  if (Position2 != Position) //if there is a poisition change:
  {
    // "Forward" is shown by the position going from (0 to 1) or (1 to 3)
    // or (3 to 2) or (2 to 0).  Anything else indicates that the user is
    // turning the device the other way.  Remember: this is Gray code, not
    // binary.
    int isFwd = ((Position == 0) && (Position2 == 1)) ||
      ((Position == 1) && (Position2 == 3)) ||
      ((Position == 3) && (Position2 == 2)) ||
      ((Position == 2) && (Position2 == 0));
    delay(Encoder_Sensitivity);
    if (isFwd == 1) //if Encoder is moved forwards (CW), advance seconds by defined increment value
    {
      seconds= seconds + increment;
    }
    if (isFwd == 0) // if encoder is moved backwards(CCW):
    {
      if (seconds == 0)// if we are already at zero seconds, check to make sure we can reduce a minute
      {
        if (minutes > 0)// if the minutes can be reduced (i.e. not zero) then remove one minute and reset seconds to 59
        {       
          minutes --;
          seconds = 60-increment;
        }
      }
      else
      {
        seconds = seconds - increment;//if seconds were not = 0, then decrease seconds value by the increment value
      }
    }
  }

  if (seconds>59)    // When seconds = 60:
  {
    minutes++;          // Add one minute
    seconds -= 60;      // Reset seconds
  }

  if (Press2 != Press) //if the encoder is pressed down:
  {
    delay(Press_Sensitivity);
    mode = Run_Timer;
  }
  Position = Position2;
  Press = Press2;

  Serial7Segment.print('v');
  sprintf(tempString, "%02d%02d", minutes, seconds);
  Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S
  Serial.println(tempString);
}

//-------------------------------------------------------------------------------------------------
void countdownTimer() //this will start counting down from the time set using the encoder. This begins when the encoder button is pressed.
{
  seconds = constrain (seconds, -1, 60);
  if( (millis() - millisTimer) > 1000)
  {
    millisTimer += 1000; //Adjust the timer forward 1 second
    if (seconds == 0)// if we are already at zero seconds, check to make sure we can reduce a minute
    {
      if (minutes > 0)// if the minutes can be reduced (i.e. not zero) then remove one minute and reset seconds to 59
      {       
        minutes --;
        seconds = 59;
      }
    }
    else{
      seconds--;//if seconds were not = 0, then decrease seconds value by the increment value
    }
    sprintf(tempString, "%02d%02d", minutes, seconds);
    Serial7Segment.write(0x77);  // Decimal, colon, apostrophe control command
    Serial7Segment.write(1<<COLON); // Turns on colon, apostrophoe, and far-right decimal
    Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S

    Serial.println(tempString);
  }

  if (minutes == 0 & seconds == 0)
  {
    digitalWrite(Relay, LOW);
    Serial7Segment.print("0000"); //Send the hour and minutes to the display
    mode = Set_Timer;
  }

  if (digitalRead(Encoder_Press)== LOW)
  {
    delay(Press_Sensitivity);
    mode = Pause_Timer;
  }
}

//-----------------------------------------------------------------------------------------
void PauseTimer()
{
  seconds_hold = seconds;
  minutes_hold = minutes;

  sprintf(tempString, "%02d%02d", minutes_hold, seconds_hold);
  Serial7Segment.write(0x77);  // Decimal, colon, apostrophe control command
  Serial7Segment.write(1<<COLON); // Turns on colon, apostrophoe, and far-right decimal
  Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S

  if (digitalRead(Encoder_Press) == LOW)
  {
    delay(Press_Sensitivity);
    seconds = seconds_hold;
    minutes = minutes_hold; 
    mode = Run_Timer;
  }

  mode = Set_Timer;
}
//-------------------------------------------------------------------------------------------
void setup()
{
  // configure the pins
  _ResetPins();

  Serial.begin(9600);

  Serial7Segment.begin(9600); //Talk to the Serial7Segment at 9600 bps
  Serial7Segment.write('v'); //Reset the display - this forces the cursor to return to the beginning of the display
  Serial7Segment.print("0000"); //Send the hour and minutes to the display
}

void loop()
{
  if (digitalRead(MagSwitch) == LOW) //if magnetic switch is detected
    // switches modes depending on button press
  {
    switch(mode){
      digitalWrite(Relay, LOW); //Relay off
      case (Set_Timer): //reads encoder and sets time
      SetTimer();
      break;

      case (Run_Timer): //counts down timer
      digitalWrite(Relay, HIGH); //relay on
      //      minutes = minutes_hold;
      //      seconds = seconds_hold;
      countdownTimer(); //run countdown script (above)
      break;

      case (Pause_Timer):
      digitalWrite(Relay, LOW);
      PauseTimer();
      break;     
    }
  }

  else if (digitalRead(MagSwitch) == HIGH) //if no magnetic switch detected
  {
    digitalWrite (Relay, LOW);
    minutes = 0;
    seconds = 0;
    Serial7Segment.print("OFF "); //Send the hour and minutes to the display
    mode = Set_Timer;
  } 
}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy