Cant stop code from being run after reset

HazardsMind-

It has to be like this " elapsedTime = millis(); - startTime; ".

It is supposed to be a regular timer that works in the "background" and when i press the button i get a readout of how far it has come

These variables -
int lastButtonState; // variable to store last button state probably should be int lastButtonState = 0;
byte lastbuttonState2 = 0; // new global variable - I think you created this one, and thought you used it when you really just wanted to initialize lastButtonState.
byte buttonState1 = 0;
byte buttonState2 = 0;

and this little bit of code -

buttonState1 = digitalRead(buttonPin); // so the button isn't pressed here
delay(20);
buttonState2 = digitalRead(buttonPin); // and the button isn't pressed here

if(buttonState1 == buttonState2) { // then this is true because not pressed == not pressed
if(buttonState2 != lastButtonState) { // and since lastButtonState was never initialized we don't know what it might be so this can be true also.
activate(); // and activate() runs because every condition passed.
lastButtonState = buttonState2;
}
}

Ok, so when the button is pressed, it starts the timer and continiously shows it on the screen? Because right now your code starts timing as soon as it resets, that is going to happen. But if you want it to appear to start when you press the button, then that is different.

That is correct, i want it to appear to start when i press the button..

What do i have to do to the code to get it working as it should?

Webca:
That is correct, i want it to appear to start when i press the button..

What do i have to do to the code to get it working as it should?

Remind me exactly what behaviour you're trying to achieve? Your initial post sounded trivially simple and I don't follow the need for all this timing and state handling code.

Ok then, I got this.

Change the LCD I2C stuff back to your LCD setup.

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

LiquidCrystal_I2C lcd(0x20,20,4); //MINE


#define ledPin  13                  // LED connected to digital pin 13
#define buttonPin 9                 // button on pin 4

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;// variable used to store fractional part of time

boolean start = false;
byte lastbuttonState2 = 0; // new global variable
byte buttonState1 = 0;
byte buttonState2 = 0;

void setup()
{
  Serial.begin(9600);

  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Test");

  pinMode(ledPin, OUTPUT);         // sets the digital pin as output

  pinMode(buttonPin, INPUT);       // not really necessary, pins default to INPUT anyway
  digitalWrite(buttonPin, HIGH);   // turn on pullup resistors. Wire button so that press shorts pin to ground.
  lcd.init();                      // initialize the lcd  MINE
  lcd.backlight();              // MINE
}

void loop()
{ 
  buttonState1 = digitalRead(buttonPin);
  delay(20);
  buttonState2 = digitalRead(buttonPin);

  if(buttonState1 == buttonState2) {
    if(buttonState2 == HIGH){
      start = true;
      startTime = millis();
      lastButtonState = buttonState2;
    }
  
  if(start == true){
  elapsedTime =   millis() - startTime;              // store elapsed time
    lastButtonState = buttonState;                     // store buttonState in lastButtonState, to compare next time

    lcd.setCursor(0,1);

    lcd.print("   ");
    // routine to report elapsed time 
    lcd.print( (int)(elapsedTime / 1000UL));         // divide by 1000 to convert to seconds - then cast to an int to print

    lcd.print(".");                             

    fractional = (int)(elapsedTime % 1000UL);

    if (fractional == 0)
      lcd.print("000");     
    else if (fractional < 10)    
      lcd.print("00");       
    else if (fractional < 100)
      lcd.print("0");        

    lcd.print(fractional);  // print fractional part of time 
  }
  }
}

I took everything out of the activate() function, just to test it without the use of any other functions.

Now what this does is it waits for the button to be pressed, in my case buttonState2 = HIGH (yours might be LOW) then starts the timer at 0.000 and counts. It will reset the timer every time the button is pressed.

I am trying your sketch and what happens is it shows the counter in the display and when i click the button it resets the counter.

I want the counter to run in the background (not visible in the display) and when i click on the button after for example 5 seconds it shows 5.000 in the display and if i then click the button after 2 seconds again i want it to show 7.000 in the display.

I feel we are getting close though, and i really appreciate you sticking with me on this HazardsMind:)

Ok, now I see what you want to do. The way you had it the first time, kinda work, but it started the count as soon as the arduino started up. So now all you need to do is make it so that,
*You press the button once, starts timer in the background.
*Press same button again, and it shows the time.

For this look at what PeterH wrote,

The simplest way to do that is to put a loop in setup() that reads the switch state repeatedly until the button press is detected.

In which case you would use a while loop to check the state of the button, if it is pressed then you store the current millis and pass it on to the loop function.
In the loop function, you then check the button state again, and if that is pressed, you show the time. Using this method, it will NOT reset the timer until the arduino itself is reset.

Im sure you can do this on your own, so give it a try, and if not post what you have.

Update, you dont need to use PeterH's suggestion (No offense Peter), I got it to work on my end with just a single new IF/ELSE and boolean statement.

Hint!
Add the new boolean statement (globally false) before the "start = true" line (that exact line) with the same boolean inside the IF statement set to true (The lockout). Then add a button check to "start == true", button check AND start == true. After that IF statement's closing bracket, put the ELSE statement to clear the screen.

Its that easy.

Also you can get rid of buttonstate 1 == buttonstate2 and just have buttonState2 == HIGH. No debounce needed.

Do you know -why- there's debounce?

Yes, I'm the one who put it in his code.

You've got a delay(20) in there. Your minimum response is over 20 ms....

It'd be smoother to loop while ( now - startPress > 10 ) true after 10 ms continuous contact, Arduino can check that button 8000 times in 10 ms so why have it do nothing for 20 ms?

I still cant get it to work...

Here is the code:

#include <Wire.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


#define ledPin  13                  // LED connected to digital pin 13
#define buttonPin 9                 // button on pin 4

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                     // variable used to store fractional part of time

boolean test = false;
boolean start = false;
byte lastbuttonState2 = 0;          // new global variable
byte buttonState1 = 0;
byte buttonState2 = 0;

void setup()
{
  Serial.begin(9600);

  lcd.begin(16, 4);
  // Print a message to the LCD.
  lcd.print("Test");

  pinMode(ledPin, OUTPUT);         // sets the digital pin as output

  pinMode(buttonPin, INPUT);       // not really necessary, pins default to INPUT anyway
  digitalWrite(buttonPin, HIGH);   // turn on pullup resistors. Wire button so that press shorts pin to ground.

}

void loop()
{ 
  buttonState1 = digitalRead(buttonPin);
  delay(20);
  
  buttonState2 = digitalRead(buttonPin);

  if(buttonState1 == buttonState2) {
    if(buttonState2 == HIGH){
      start = true;
      startTime = millis();
      lastButtonState = buttonState2;
    }
  
  if(start == true){
  elapsedTime =   millis() - startTime;              // store elapsed time
    lastButtonState = buttonState;                     // store buttonState in lastButtonState, to compare next time

    lcd.setCursor(0,2);

    lcd.print(" ");
    // routine to report elapsed time 
    lcd.print( (int)(elapsedTime / 1000UL));         // divide by 1000 to convert to seconds - then cast to an int to print

    lcd.print(".");                             

    fractional = (int)(elapsedTime % 1000UL);

    if (fractional == 0)
      lcd.print("000");     
    else if (fractional < 10)    
      lcd.print("00");       
    else if (fractional < 100)
      lcd.print("0");        

    lcd.print(fractional);  // print fractional part of time 
  }
  if(test == true){
    if(buttonState1 == HIGH)
    start == true;
    else;{}
    } 
  }
}

GoForSmoke:
You've got a delay(20) in there. Your minimum response is over 20 ms....

It'd be smoother to loop while ( now - startPress > 10 ) true after 10 ms continuous contact, Arduino can check that button 8000 times in 10 ms so why have it do nothing for 20 ms?

I ment it to be 10 but I pressed 2 instead, and just never bothered to change it. It's a crude way to do it, I know, but it works as a temporary debounce.

Webca:
I still cant get it to work...

Here is the code:

#include <Wire.h>

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define ledPin  13                  // LED connected to digital pin 13
#define buttonPin 9                // button on pin 4

int value = LOW;                    // previous value of the LED
int buttonState;                    // variable to store button state
int lastButtonState;                // variable to store last button state
long interval = 100;                // blink interval - change to suit
long previousMillis = 0;            // variable to store last time LED was updated
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
int fractional;                    // variable used to store fractional part of time

boolean test = false;
boolean start = false;
byte lastbuttonState2 = 0;          // new global variable
byte buttonState1 = 0;
byte buttonState2 = 0;

void setup()
{
  Serial.begin(9600);

lcd.begin(16, 4);
  // Print a message to the LCD.
  lcd.print("Test");

pinMode(ledPin, OUTPUT);        // sets the digital pin as output

pinMode(buttonPin, INPUT);      // not really necessary, pins default to INPUT anyway
  digitalWrite(buttonPin, HIGH);  // turn on pullup resistors. Wire button so that press shorts pin to ground.

}

void loop()
{
  buttonState1 = digitalRead(buttonPin);
  delay(20);
 
  buttonState2 = digitalRead(buttonPin);

if(buttonState1 == buttonState2) {
    if(buttonState2 == HIGH){
      start = true;
      startTime = millis();
      lastButtonState = buttonState2;
    }
 
  if(start == true){
  elapsedTime =  millis() - startTime;              // store elapsed time
    lastButtonState = buttonState;                    // store buttonState in lastButtonState, to compare next time

lcd.setCursor(0,2);

lcd.print(" ");
    // routine to report elapsed time
    lcd.print( (int)(elapsedTime / 1000UL));        // divide by 1000 to convert to seconds - then cast to an int to print

lcd.print(".");

fractional = (int)(elapsedTime % 1000UL);

if (fractional == 0)
      lcd.print("000");   
    else if (fractional < 10)   
      lcd.print("00");     
    else if (fractional < 100)
      lcd.print("0");

lcd.print(fractional);  // print fractional part of time
  }
  if(test == true){
    if(buttonState1 == HIGH)
    start == true;
    else;{}
    }
  }
}

I guess my hint wasn't easy enough to understand. It's only 3 new lines you need to add, along with any brackets.

I am new at this so the learning curve is pretty steep.

couldnt you add the 3 lines in the code for me?

Time debounced button presses, start to start not release to start.
LED 13 lights when the button is pressed. TX flashes when debounce is done.

Tested with UNO 3, serial monitor and jumper from pin 9 to gnd as button.

//  Time debounced button presses, start to start not release to start.  

//#include <Wire.h>
//#include <LiquidCrystal.h>

// LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


#define LEDPIN  13                  // LED connected to digital pin 13
#define BPIN 9                 // button on pin 4

byte buttonState;                    // variable to store button state
unsigned long debounce = 0UL; // variable to store last time LED was updated
unsigned long Timer ;         // start/elapsed time for stop watch

void setup()
{
  Serial.begin(9600);

  //lcd.begin(16, 4);
  // Print a message to the LCD.
  //lcd.print("Test");

  Serial.println("Test");

  pinMode( LEDPIN, OUTPUT );         // sets the digital pin as output
  digitalWrite( LEDPIN, LOW );   // turn on pullup resistors. Wire button so that press shorts pin to ground.

  pinMode( BPIN, INPUT );       // not really necessary, pins default to INPUT anyway
  digitalWrite( BPIN, HIGH );   // turn on pullup resistors. Wire button so that press shorts pin to ground.

  Timer = millis(); // Timer now is start millis
}

void loop()
{ 
  digitalWrite( LEDPIN, LOW );

  while ( digitalRead( BPIN )); // button is not pressed

  digitalWrite( LEDPIN, HIGH );

  debounce = millis();
  while (( millis() - debounce < 10UL ) && 
    ( buttonState = !digitalRead( BPIN ))); // button pressed && time not up

  if ( buttonState )  // success if contact holds till time is up, 
  {
    Timer = millis() - Timer; // Timer now is elapsed millis

    /*
      lcd.setCursor(0,2);
     
     lcd.print( " " );
     // routine to report elapsed time 
     lcd.print( Timer / 1000UL ); // convert to seconds and print    
     lcd.print( "." );                             
     
     Timer = Timer % 1000UL; // Timer now is remaining millis < 1 sec
     
     if ( Timer < 100UL )
     {
     lcd.print( "0" );     
     if ( Timer < 10UL )
     {    
     lcd.print( "0" );
     }
     }    
     
     lcd.print( Timer );  
     */
    Serial.println();

    Serial.print( " " );
    // routine to report elapsed time 
    Serial.print( Timer / 1000UL );         // divide by 1000 to convert to seconds - then cast to an int to print

    Serial.print( "." );                             

    Timer = Timer % 1000UL; // Timer now is remaining millis < 1 sec

    if ( Timer < 100UL )
    {
      Serial.print( "0" );     
      if ( Timer < 10UL )
      {    
        Serial.print( "0" );
      }
    }    

    Serial.println( Timer );  

    Timer = millis(); // start millis before the button is released

    if ( !digitalRead( BPIN ))
    {
      while ( !digitalRead( BPIN )); // wait until BPIN is released
    }
  }
}

Thanks to everyone for helping me in this mather, and a special thanks to "HazardsMind" for solving my problem.

Here is the functioning code HazardsMind gave me:

#include <Wire.h>
 #include <LiquidCrystal.h>

 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


 #define ledPin  13                  // LED connected to digital pin 13
 #define buttonPin 9                 // button on pin 4

 int value = LOW;                    // previous value of the LED
 int buttonState;                    // variable to store button state
 int lastButtonState;                // variable to store last button state
 long interval = 100;                // blink interval - change to suit
 long previousMillis = 0;            // variable to store last time LED was updated
 long startTime ;                    // start time for stop watch
 long elapsedTime ;                  // elapsed time for stop watch
 int fractional;                     // variable used to store fractional part of time

 boolean test = false;
 boolean start = false;
 boolean lockout = false;            //**NEW BOOLEAN**
 byte lastbuttonState2 = 0;          // new global variable
 byte buttonState1 = 0;
 byte buttonState2 = 0;

 void setup()
 {
   Serial.begin(9600);

   lcd.begin(16, 4);
   // Print a message to the LCD.
   lcd.print("Test");

   pinMode(ledPin, OUTPUT);         // sets the digital pin as output

   pinMode(buttonPin, INPUT);       // not really necessary, pins default to INPUT anyway
   digitalWrite(buttonPin, HIGH);   // turn on pullup resistors. Wire button so that press shorts pin to ground.

 }

 void loop()
 {  // no more debounce
   buttonState2 = digitalRead(buttonPin);
   if(buttonState2 == HIGH){
     if(lockout == false){ // #1
       start = true;
       startTime = millis();
       lastButtonState = buttonState2;
       lockout = true; // (The lockout) this will make sure it does not go back to this IF statement
     }
   }
   if(buttonState2 == HIGH && start == true){ // #2
     elapsedTime =   millis() - startTime;              // store elapsed time
     lastButtonState = buttonState;                     // store buttonState in lastButtonState, to compare next time

     lcd.setCursor(0,2);

     lcd.print(" ");
     // routine to report elapsed time
     lcd.print( (int)(elapsedTime / 1000UL));         // divide by 1000 to convert to seconds - then cast to an int to print

     lcd.print(".");

     fractional = (int)(elapsedTime % 1000UL);

     if (fractional == 0)
       lcd.print("000");
     else if (fractional < 10)
       lcd.print("00");
     else if (fractional < 100)
       lcd.print("0");

     lcd.print(fractional);  // print fractional part of time
   }
   else lcd.clear(); // #3
 }

Hey, at least he got rid of the delays. Now it's responsive!

He's still working millis() with signed longs but you won't be running this any 24 days straight so no problem.

It's still good practice (so you don't trip up later doing "what worked" before) to use unsigned long or unsigned long long to work with millis() and micros(). Both of those functions return unsigned long which is clue #1 about best use of those values.

Micros() rolls over in 1.193... hours using unsigned long. It turns negative in half that with signed. Millis() can measure intervals to over 48 days because it takes 49.7... to overflow using unsigned long. With signed, just under 25 days to find that bug. With unsigned long long the longest interval is over 4 billion times as large, counting millisecs. The sun is not that old! With signed... you should live to see the bug!
Or of course knowing about rollover the clever programmer writes some logic to handle it. But why do that when there's no need for extra code at all with unsigned long.
If signed integers are like measuring sticks with 2 ends for - and +, unsigned integers are circles like clock faces. You measure around the circle and don't worry about crossing zero, it comes out in the math always as a positive. The sign is in the direction from-to you measured, not in the result, unsigned don't have sign.