resetting using millis()

Hey everyone, im working on a launch system for a model rocket. Im running into an issue where my countdown starts whether i have flipped the "Go No Go switch". If i leave the switch in "Standby (sb)" the program displays "sb" as it should. but once its flipped it appears the timer started when the arduino mega started. im not sure how to prevent this. I will include my code below.

#include "SevSeg.h"
SevSeg sevseg;

volatile static int deciSeconds;
volatile bool GNG = false;

void setup() {

  //setting up launch leds
  int red = 53;
  int yellow = 51;
  int blue = 49;
  pinMode(blue, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(red, OUTPUT);

  //setting up the display
  byte numDigits = 2;
  byte digitPins[] = {4, 5};
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_CATHODE;
  bool updateWithDelays = false; // Default. Recommended
  bool leadingZeros = true;

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);
  sevseg.setBrightness(90);

  //setting up the button interrupts
  attachInterrupt(digitalPinToInterrupt(18), GNGswitch, RISING); // if timer is not counting down flip reset switch

}

void loop() {

  if (GNG) {
    int red = 53;
    int yellow = 51;
    int blue = 49;
    
    static unsigned long timestamp = millis();
    // deciSeconds = 100; //10 deciSeconds = 1 sec
    if (millis() - timestamp >= 1000 && deciSeconds > 0 ) {
      timestamp += 100;
      deciSeconds--; // 100 milliSeconds is equal to 1 deciSecond


      sevseg.setNumber(deciSeconds, 1);
      digitalWrite(49, LOW);
      digitalWrite(51, HIGH);
    }

    if (deciSeconds == 0) {
      sevseg.setChars("ig");
      digitalWrite(51, LOW);
      digitalWrite(53, HIGH);;
    }
  }

  else {
    sevseg.setChars("sb");
    digitalWrite(49, HIGH);
    deciSeconds = 100;
  }

  sevseg.refreshDisplay(); // Must run repeatedly

}


void GNGswitch() {
  if (!GNG) {
    deciSeconds = 100;
    GNG = true;
  }

}

Please use code tags (</> button on the toolbar) when you post code or warning/error messages. The reason is the forum software can interpret parts of your code as markup, leading to confusion, wasted time, and a reduced chance for you to get help with your problem. This will also make it easier to read your code and to copy it to the IDE or editor. If your browser doesn't show the posting toolbar, then you can just manually add the code tags:
[code]``[color=blue]// your code is here[/color]``[/code]
Using code tags and other important information is explained in the How to use this forum post. Please read it.

Please always do an Auto Format (Tools > Auto Format in the Arduino IDE or Ctrl + B in the Arduino Web Editor) on your code before posting it. This will make it easier for you to spot bugs and make it easier for us to read.

MrZRman:

    static unsigned long timer = millis();

if (millis() + timer >= 100 && deciSeconds >0 ) {
      timer -= 100;

Try changing it to this:

    if (millis() - timer >= 100 && deciSeconds > 0 ) {  // it's been more than 100 ms
      timer += 100;

I think "timestamp" is a better variable name than "timer".

Check how to use this Forum, hove to attach code using code tags.
If "time variable ==" is a not a safe test. >= or =< is more often better.
GNG is set true in loop but I dont see where it's set false.

I dont see where it's set false.

It's done in GNGswitch(), which is called by the interrupt on pin 18:

attachInterrupt(digitalPinToInterrupt(18), GNGswitch, RISING);

Ok. Hard to see. More comments in Your sketch..... Let's keep on searching.
Is timer ininition done properly? The switch seams to be read by the GNG-library. Is the setup of pin 18 correct? Is INPUT_PULLUP or a pulldown resistor needed?
Attach Your wiring diagram.

I think it helps to establish a "time zero" when the rising edge of GNG occurs by saving the values of millis() then and counting from there:

How about:

#include "SevSeg.h"
SevSeg sevseg;

volatile static int deciSeconds;
volatile bool GNG = false;

unsigned long
    GNGStartTime;

void setup() 
{
    //setting up the display
    byte numDigits = 2;
    byte digitPins[] = {4,5};
    byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
    bool resistorsOnSegments = false; 
    byte hardwareConfig = COMMON_CATHODE; 
    bool updateWithDelays = false; 
    bool leadingZeros = true; 

    sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);
    sevseg.setBrightness(90);
  
    //setting up the button interrupts
    pinMode(18, INPUT);
    attachInterrupt(digitalPinToInterrupt(18), GNGswitch, RISING); 

    deciSeconds = 100;

}//setup

void loop() 
{  
    unsigned long
        timeNow;
        
    if(GNG)
    {
        static unsigned long timer = millis();
        // deciSeconds = 100; //10 deciSeconds = 1 sec
        timeNow = millis();
        if( deciSeconds && ((timeNow - GNGStartTimer) >= 100) ) 
        {
            deciSeconds--;
            GNGStartTimer = timeNow;    
            
            sevseg.setNumber(deciSeconds,1);

        }//if

        if (deciSeconds == 0) 
        {
            sevseg.setChars("ig");
            
        }//if
         
    }//if GNG
    else
    {
        sevseg.setChars("sb");
        deciSeconds=100;
        
    }//else
  
    sevseg.refreshDisplay(); 
  
}//loop

void GNGswitch() 
{
    if(!GNG)
    {
        deciSeconds=100;
        GNG=true;

        GNGStartTime = millis();
        
    }//if
 
}//GNGswitch

Railroader:

Ok. Hard to see. More comments in Your sketch..... Let's keep on searching.
Is timer ininition done properly? The switch seams to be read by the GNG-library. Is the setup of pin 18 correct? Is INPUT_PULLUP or a pulldown resistor needed?
Attach Your wiring diagram.

adjusting my to this worked.

if (millis() - timer >= 100 && deciSeconds > 0 ) {  // it's been more than 100 ms


      timer += 100;

I just need to mess with the interrupt more.

Railroader what program should i use to show my wiring diagram? ive never made one before.

Write the wiring by hand, make a picture and attach it using, not code- tags, but one of the others. That makes the picture dhow up directly in the topic.

MrZRman:
Hey everyone, im working on a launch system for a model rocket. Im running into an issue where my countdown starts whether i have flipped the "Go No Go switch". If i leave the switch in "Standby (sb)" the program displays "sb" as it should. but once its flipped it appears the timer started when the arduino mega started. im not sure how to prevent this. I will include my code below.

volatile bool GNG = false;

......

void loop() {

if (GNG) {

..........

else {
    sevseg.setChars("sb");
    digitalWrite(49, HIGH);
    deciSeconds = 100;
  }

sevseg.refreshDisplay(); // Must run repeatedly

}

I don't think that your switch matters with that code.

Railroader:
Check how to use this Forum, hove to attach code using code tags.
If "time variable ==" is a not a safe test. >= or =< is more often better.
GNG is set true in loop but I dont see where it's set false.

I have updated my code (including comments :slight_smile: )and uploaded my schematic:

#include "SevSeg.h"
SevSeg sevseg;

volatile static int deciSeconds = 100; //10 deciSeconds = 1 sec TOTAL COUNTDOWN TIME: 10 Seconds
volatile bool GNG = false; //set the Go No Go switch to off, user must make input to change via interrupt

//setting up launch leds
int red = 53;
int yellow = 51;
int blue = 49;

void setup() {

  pinMode(blue, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(red, OUTPUT);

  //setting up the seven segment display according to sevseg library
  byte numDigits = 2; //# of segment displays
  byte digitPins[] = {4, 5}; //pins the segments' cathodes are connected to
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; //
  bool resistorsOnSegments = false;
  byte hardwareConfig = COMMON_CATHODE; //type of segment display being used
  bool updateWithDelays = false;
  bool leadingZeros = true;

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros); //sets up the arduino to use the segment display
  sevseg.setBrightness(90);

  //setting up the interrupts. ALL INTERRUPTS ARE BELOW loop function
  attachInterrupt(digitalPinToInterrupt(18), GNGswitch, CHANGE); //GNGswitch will change GNG to true allowing the countdown to begin
  attachInterrupt(digitalPinToInterrupt(19), Holdswitch, CHANGE); //Pauses the countdown and holds current value of the timer
  attachInterrupt(digitalPinToInterrupt(20), countDownResetswitch, CHANGE); //resets the countdown

}

void loop() {

  if (GNG) { //if the switch is flipped to the on position, the ISR will run changing GNG to true allowing the countdown to begin
    static unsigned long timestamp = millis();
    if (millis() - timestamp >= 1000 && deciSeconds > 0 ) {
      timestamp += 100;
      deciSeconds--; // 100 milliSeconds is equal to 1 deciSecond

      sevseg.setNumber(deciSeconds, 1); //(displays the countdown value [deciSeconds], decimal will be on the first segment display)
      digitalWrite(blue, LOW);
      digitalWrite(yellow, HIGH);
    }

    if (deciSeconds == 0) { //If statement shows that rocket has launched once the countdown reaches 0)
      sevseg.setChars("ig");
      digitalWrite(yellow, LOW);
      digitalWrite(red, HIGH);;
    }
  }

  else if (!GNG && deciSeconds == 100) { //Shows the rocket is in standby mode waiting for the go to begin countdown
    sevseg.setChars("sb");
    digitalWrite(blue, HIGH);
    deciSeconds = 100;
  }

  else { //displays the countdown when the rocket is in hold. i.e if the hold button is pressed with 5 seconds remaining in the countdown, the display will show 5.0)
    sevseg.setNumber(deciSeconds, 1);
  }

  sevseg.refreshDisplay(); // Must run repeatedly for the segment display to show

}


void GNGswitch() { //Changes the bool GNG to True allowing the countdown to begin
  if (!GNG) {
    GNG = true;
  }
}

void Holdswitch () { //Changes the bool GNG to false pausing the countdown
  GNG = false;
}

void countDownResetswitch() { //resets countdown to 10 seconds. 10 deciSeconds = 1 second.
  deciSeconds = 100;
}

I do have an issue where once I flip the GNG switch (labeled on the schematic) it takes about 5 seconds for the countdown to start and none of the other interrupts seem to work. I have tried them each once the count down has started and the GNG switch in the default position. Im not sure whats going on here.

Nice diagram. You need to learn about the miracle of INPUT_PULLUP.

static unsigned long timestamp = millis();

This statement only assigns the value of millis() to timestamp once. Because of the static declaration it will not do it again.

You do not need interrupts for buttons pushed by humans. Not ever. Even for emergency-stop. Re-write it without interrupts.

Look into "button debounce". I suspect you are getting bounces which may cause problems.